mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 20:30:38 +09:00
Compare commits
33 Commits
libssh-0.5
...
release-0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
232aca8969 | ||
|
|
48deb0ca46 | ||
|
|
59889da5a5 | ||
|
|
a958f6498b | ||
|
|
3ec11b46e9 | ||
|
|
c17ce2697b | ||
|
|
7fa1804cf1 | ||
|
|
ad86a378d9 | ||
|
|
ed660c29c3 | ||
|
|
6f47401173 | ||
|
|
d247b86202 | ||
|
|
a1c7dd99be | ||
|
|
11a6ed907d | ||
|
|
a8ce546f69 | ||
|
|
6e56d1dfb2 | ||
|
|
b07ec7a3d1 | ||
|
|
09d4029ac1 | ||
|
|
b62d0732d2 | ||
|
|
90a6d431a7 | ||
|
|
f7448eeb1c | ||
|
|
d411260a68 | ||
|
|
f8f0663eb9 | ||
|
|
cedc635ed0 | ||
|
|
ff819489b7 | ||
|
|
37dc2a5279 | ||
|
|
50ebbe636e | ||
|
|
101bf21d41 | ||
|
|
ae3bb42da5 | ||
|
|
918a912cd5 | ||
|
|
7ba81b974e | ||
|
|
b5e868fb8b | ||
|
|
693c041ba9 | ||
|
|
39c7e3c7dd |
@@ -1 +0,0 @@
|
||||
-Iinclude -Ibuild
|
||||
@@ -6,21 +6,14 @@ cmake_minimum_required(VERSION 2.6.0)
|
||||
# global needed variables
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
|
||||
set(APPLICATION_VERSION "0.3.2")
|
||||
|
||||
set(APPLICATION_VERSION_MAJOR "0")
|
||||
set(APPLICATION_VERSION_MINOR "5")
|
||||
set(APPLICATION_VERSION_PATCH "1")
|
||||
set(APPLICATION_VERSION_MINOR "3")
|
||||
set(APPLICATION_VERSION_PATCH "2")
|
||||
|
||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||
|
||||
# SOVERSION scheme: CURRENT.AGE.REVISION
|
||||
# If there was an incompatible interface change:
|
||||
# Increment CURRENT. Set AGE and REVISION to 0
|
||||
# If there was a compatible interface change:
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.2.1")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
set(LIBRARY_VERSION "3.2.0")
|
||||
set(LIBRARY_SOVERSION "3")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
set(CMAKE_MODULE_PATH
|
||||
@@ -29,7 +22,6 @@ set(CMAKE_MODULE_PATH
|
||||
|
||||
# add definitions
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefinePlatformDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
include(DefineInstallationPaths)
|
||||
include(DefineOptions.cmake)
|
||||
@@ -44,28 +36,16 @@ include(MacroAddPlugin)
|
||||
include(MacroCopyFile)
|
||||
|
||||
# search for libraries
|
||||
if (WITH_LIBZ)
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif (WITH_LIBZ)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
if (WITH_GCRYPT)
|
||||
find_package(GCrypt REQUIRED)
|
||||
find_package(OpenSSL)
|
||||
|
||||
if (NOT CRYPTO_FOUND)
|
||||
find_package(GCrypt)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
message(FATAL_ERROR "Could not find GCrypt")
|
||||
message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
else (WITH_GCRYPT)
|
||||
find_package(OpenSSL)
|
||||
if (NOT OPENSSL_FOUND)
|
||||
find_package(GCrypt)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
endif (NOT OPENSSL_FOUND)
|
||||
endif(WITH_GCRYPT)
|
||||
|
||||
# Find out if we have threading available
|
||||
set(CMAKE_THREAD_PREFER_PTHREADS ON)
|
||||
find_package(Threads)
|
||||
endif (NOT CRYPTO_FOUND)
|
||||
|
||||
# config.h checks
|
||||
include(ConfigureChecks.cmake)
|
||||
@@ -74,46 +54,17 @@ 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)
|
||||
|
||||
add_subdirectory(examples)
|
||||
|
||||
if (WITH_TESTING)
|
||||
find_package(CMockery REQUIRED)
|
||||
include(AddCMockeryTest)
|
||||
add_subdirectory(tests)
|
||||
endif (WITH_TESTING)
|
||||
|
||||
|
||||
message(STATUS "********************************************")
|
||||
message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
||||
|
||||
message(STATUS "zlib support: ${WITH_LIBZ}")
|
||||
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
||||
message(STATUS "SSH-1 support: ${WITH_SSH1}")
|
||||
message(STATUS "SFTP support: ${WITH_SFTP}")
|
||||
message(STATUS "Server support : ${WITH_SERVER}")
|
||||
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
|
||||
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 (UNIX AND NOT WIN32)
|
||||
if (WITH_SFTP AND WITH_SERVER)
|
||||
add_executable(samplessh sample.c)
|
||||
add_executable(samplesshd samplesshd.c)
|
||||
|
||||
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SFTP AND WITH_SERVER)
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
include(InstallRequiredSystemLibraries)
|
||||
|
||||
# For help take a look at:
|
||||
# http://www.cmake.org/Wiki/CMake:CPackConfiguration
|
||||
|
||||
@@ -12,8 +14,8 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
|
||||
### versions
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "5")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "1")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "3")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "2")
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
|
||||
|
||||
@@ -22,21 +24,16 @@ set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
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 CET")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "test.libssh.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
170
ChangeLog
170
ChangeLog
@@ -1,168 +1,6 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
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.
|
||||
* Fixed a bug in setting the options.
|
||||
|
||||
version 0.4.3 (released 2010-05-18)
|
||||
* Added global/keepalive responses.
|
||||
* Added runtime detection of WSAPoll().
|
||||
* Added a select(2) based poll-emulation if poll(2) is not available.
|
||||
* Added a function to expand an escaped string.
|
||||
* Added a function to expand the tilde from a path.
|
||||
* Added a proxycommand support.
|
||||
* Added ssh_privatekey_type public function
|
||||
* Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR.
|
||||
* Fixed sftp_chown.
|
||||
* Fixed sftp_rename on protocol version 3.
|
||||
* Fixed a blocking bug in channel_poll.
|
||||
* Fixed config parsing wich has overwritten user specified values.
|
||||
* Fixed hashed [host]:port format in knownhosts
|
||||
* Fixed Windows build.
|
||||
* Fixed doublefree happening after a negociation error.
|
||||
* Fixed aes*-ctr with <= OpenSSL 0.9.7b.
|
||||
* Fixed some documentation.
|
||||
* Fixed exec example which has broken read usage.
|
||||
* Fixed broken algorithm choice for server.
|
||||
* Fixed a typo that we don't export all symbols.
|
||||
* Removed the unneeded dependency to doxygen.
|
||||
* Build examples only on the Linux plattform.
|
||||
|
||||
version 0.4.2 (released 2010-03-15)
|
||||
* Added owner and group information in sftp attributes.
|
||||
* Added missing SSH_OPTIONS_FD option.
|
||||
* Added printout of owner and group in the sftp example.
|
||||
* Added a prepend function for ssh_list.
|
||||
* Added send back replies to openssh's keepalives.
|
||||
* Fixed documentation in scp code
|
||||
* Fixed longname parsing, this only workings with readdir.
|
||||
* Fixed and added support for several identity files.
|
||||
* Fixed sftp_parse_longname() on Windows.
|
||||
* Fixed a race condition bug in ssh_scp_close()
|
||||
* Remove config support for SSHv1 Cipher variable.
|
||||
* Rename ssh_list_add to ssh_list_append.
|
||||
* Rename ssh_list_get_head to ssh_list_pop_head
|
||||
|
||||
version 0.4.1 (released 2010-02-13)
|
||||
* Added support for aes128-ctr, aes192-ctr and aes256-ctr encryption.
|
||||
* Added an example for exec.
|
||||
* Added private key type detection feature in privatekey_from_file().
|
||||
* Fixed zlib compression fallback.
|
||||
* Fixed kex bug that client preference should be prioritary
|
||||
* Fixed known_hosts file set by the user.
|
||||
* Fixed a memleak in channel_accept().
|
||||
* Fixed underflow when leave_function() are unbalanced
|
||||
* Fixed memory corruption in handle_channel_request_open().
|
||||
* Fixed closing of a file handle case of errors in privatekey_from_file().
|
||||
* Fixed ssh_get_user_home_dir() to be thread safe.
|
||||
* Fixed the doxygen documentation.
|
||||
|
||||
version 0.4.0 (released 2009-12-10)
|
||||
* Added scp support.
|
||||
* Added support for sending signals (RFC 4254, section 6.9).
|
||||
* Added MSVC support.
|
||||
* Added support for ~/.ssh/config.
|
||||
* Added sftp extension support.
|
||||
* Added X11 forwarding support for client.
|
||||
* Added forward listening.
|
||||
* Added support for openssh extensions (statvfs, fstatvfs).
|
||||
* Added a cleaned up interface for setting options.
|
||||
* Added a generic way to handle sockets asynchronously.
|
||||
* Added logging of the sftp flags used to open a file.
|
||||
* Added full poll() support and poll-emulation for win32.
|
||||
* Added missing 64bit functions in sftp.
|
||||
* Added support for ~/ and SSH_DIR/ in filenames instead of %s/.
|
||||
* Fixed Fix channel_get_exit_status bug.
|
||||
* Fixed calltrace logging to make it optional.
|
||||
* Fixed compilation on Solaris.
|
||||
* Fixed resolving of ip addresses.
|
||||
* Fixed libssh compilation without server support.
|
||||
* Fixed possible memory corruptions (ticket #14).
|
||||
|
||||
version 0.3.4 (released 2009-09-14)
|
||||
* Added ssh_basename and ssh_dirname.
|
||||
* Added a portable ssh_mkdir function.
|
||||
* Added a sftp_tell64() function.
|
||||
* Added missing NULL pointer checks to crypt_set_algorithms_server.
|
||||
* Fixed ssh_write_knownhost if ~/.ssh doesn't exist.
|
||||
* Fixed a possible integer overflow in buffer_get_data().
|
||||
* Fixed possible security bug in packet_decrypt().
|
||||
* Fixed a possible stack overflow in agent code.
|
||||
|
||||
version 0.3.3 (released 2009-08-18)
|
||||
* Fixed double free pointer crash in dsa_public_to_string.
|
||||
* Fixed channel_get_exit_status bug.
|
||||
* Fixed ssh_finalize which didn't clear the flag.
|
||||
* Fixed memory leak introduced by previous bugfix.
|
||||
* Fixed channel_poll broken when delayed EOF recvd.
|
||||
* Fixed stupid "can't parse known host key" bug.
|
||||
* Fixed possible memory corruption (ticket #14).
|
||||
|
||||
version 0.3.2 (released 2009-08-05)
|
||||
* Added ssh_init() function.
|
||||
* Added sftp_readlink() function.
|
||||
@@ -171,14 +9,6 @@ version 0.3.2 (released 2009-08-05)
|
||||
* Fixed compilation on Solaris.
|
||||
* Fixed SSHv1 compilation.
|
||||
|
||||
version 0.3.1 (released 2009-07-14)
|
||||
* Added return code SSH_SERVER_FILE_NOT_FOUND.
|
||||
* Fixed compilation of SSHv1.
|
||||
* Fixed several memory leaks.
|
||||
* Fixed possible infinite loops.
|
||||
* Fixed a possible crash bug.
|
||||
* Fixed build warnings.
|
||||
* Fixed cmake on BSD.
|
||||
version 0.3.1 (released 2009-07-14)
|
||||
* Added return code SSH_SERVER_FILE_NOT_FOUND.
|
||||
* Fixed compilation of SSHv1.
|
||||
|
||||
@@ -4,7 +4,6 @@ include(CheckFunctionExists)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckTypeSize)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(TestBigEndian)
|
||||
|
||||
set(PACKAGE ${APPLICATION_NAME})
|
||||
set(VERSION ${APPLICATION_VERSION})
|
||||
@@ -16,143 +15,42 @@ 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)
|
||||
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
|
||||
endif (NOT GNUCC_VERSION EQUAL 34)
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||
|
||||
# HEADER FILES
|
||||
check_include_file(argp.h HAVE_ARGP_H)
|
||||
check_include_file(pty.h HAVE_PTY_H)
|
||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||
check_include_file(terminos.h HAVE_TERMIOS_H)
|
||||
|
||||
if (WIN32)
|
||||
check_include_file(wspiapi.h HAVE_WSPIAPI_H)
|
||||
if (NOT HAVE_WSPIAPI_H)
|
||||
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
|
||||
endif (NOT HAVE_WSPIAPI_H)
|
||||
check_include_file(ws2tcpip.h HAVE_WS2TCPIP_H)
|
||||
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
set(HAVE_GETADDRINFO TRUE)
|
||||
set(HAVE_GETHOSTBYNAME TRUE)
|
||||
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
|
||||
set(HAVE_SELECT TRUE)
|
||||
endif (WIN32)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
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)
|
||||
|
||||
if (CMAKE_HAVE_PTHREAD_H)
|
||||
set(HAVE_PTHREAD_H 1)
|
||||
endif (CMAKE_HAVE_PTHREAD_H)
|
||||
|
||||
# FUNCTIONS
|
||||
|
||||
check_function_exists(strncpy HAVE_STRNCPY)
|
||||
check_function_exists(vsnprintf HAVE_VSNPRINTF)
|
||||
check_function_exists(snprintf HAVE_SNPRINTF)
|
||||
|
||||
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
||||
if (WIN32)
|
||||
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)
|
||||
set(HAVE_GETADDRINFO TRUE)
|
||||
set(HAVE_GETHOSTBYNAME TRUE)
|
||||
set(HAVE_SELECT TRUE)
|
||||
else (WIN32)
|
||||
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||
check_function_exists(gethostbyname HAVE_GETHOSTBYNAME)
|
||||
check_function_exists(poll HAVE_POLL)
|
||||
check_function_exists(select HAVE_SELECT)
|
||||
endif (WIN32)
|
||||
|
||||
if (UNIX)
|
||||
if (NOT LINUX)
|
||||
# libsocket (Solaris)
|
||||
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
|
||||
if (HAVE_LIBSOCKET)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
|
||||
# libresolv
|
||||
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
|
||||
if (HAVE_LIBRESOLV)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
|
||||
endif (HAVE_LIBRESOLV)
|
||||
|
||||
# libnsl/inet_pton (Solaris)
|
||||
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
|
||||
if (HAVE_LIBNSL)
|
||||
set(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_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||
check_function_exists(poll HAVE_POLL)
|
||||
check_function_exists(select HAVE_SELECT)
|
||||
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
||||
check_function_exists(regcomp HAVE_REGCOMP)
|
||||
check_function_exists(ntohll HAVE_NTOHLL)
|
||||
endif (UNIX)
|
||||
|
||||
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
|
||||
|
||||
# LIBRARIES
|
||||
if (OPENSSL_FOUND)
|
||||
if (CRYPTO_FOUND)
|
||||
set(HAVE_LIBCRYPTO 1)
|
||||
endif (OPENSSL_FOUND)
|
||||
endif (CRYPTO_FOUND)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
set(HAVE_LIBGCRYPT 1)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
if (ZLIB_LIBRARY)
|
||||
if (Z_LIBRARY)
|
||||
set(HAVE_LIBZ 1)
|
||||
endif (ZLIB_LIBRARY)
|
||||
|
||||
if (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(HAVE_PTHREAD 1)
|
||||
endif (CMAKE_USE_PTHREADS_INIT)
|
||||
endif (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
endif (Z_LIBRARY)
|
||||
|
||||
# OPTIONS
|
||||
if (WITH_DEBUG_CRYPTO)
|
||||
set(DEBUG_CRYPTO 1)
|
||||
endif (WITH_DEBUG_CRYPTO)
|
||||
|
||||
if (WITH_DEBUG_CALLTRACE)
|
||||
set(DEBUG_CALLTRACE 1)
|
||||
endif (WITH_DEBUG_CALLTRACE)
|
||||
|
||||
# ENDIAN
|
||||
if (NOT WIN32)
|
||||
test_big_endian(WORDS_BIGENDIAN)
|
||||
endif (NOT WIN32)
|
||||
|
||||
@@ -3,19 +3,4 @@ option(WITH_SSH1 "Build with SSH1 support" OFF)
|
||||
option(WITH_SFTP "Build with SFTP support" ON)
|
||||
option(WITH_SERVER "Build with SSH server support" ON)
|
||||
option(WITH_STATIC_LIB "Build with a static library" OFF)
|
||||
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
|
||||
option(WITH_DEBUG_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)
|
||||
|
||||
if(WITH_BENCHMARKS)
|
||||
set(WITH_TESTING ON)
|
||||
endif(WITH_BENCHMARKS)
|
||||
|
||||
if (WITH_TESTING)
|
||||
set(WITH_STATIC_LIB ON)
|
||||
endif (WITH_TESTING)
|
||||
option(WITH_DEBUG_CRYPTO "Build with cryto debut output" OFF)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1272
Doxyfile.internal
Normal file
1272
Doxyfile.internal
Normal file
File diff suppressed because it is too large
Load Diff
2
INSTALL
2
INSTALL
@@ -68,8 +68,6 @@ If you want to install libssh after compilation run:
|
||||
## Running
|
||||
|
||||
The libssh binary can be found in the `build/libssh` directory.
|
||||
You can use `build/examples/samplessh` which is a sample client to
|
||||
test libssh on UNIX.
|
||||
|
||||
## About this document
|
||||
|
||||
|
||||
72
README
72
README
@@ -1,14 +1,14 @@
|
||||
libssh: the SSH library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The libSSH and its client
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-Aris Adamantiadis
|
||||
|
||||
1* Why ?
|
||||
-_-_-_-_-_
|
||||
|
||||
Why not ? :) I've began to work on my own implementation of the ssh protocol
|
||||
because i didn't like the currently public ones.
|
||||
Not any allowed you to import and use the functions as a powerful library,
|
||||
and so i worked on a library-based SSH implementation which was non-existing
|
||||
in the free and open source software world.
|
||||
Not any allow you to import and use the functions as a library, and so i
|
||||
worked on a library-based SSH implementation.
|
||||
|
||||
|
||||
2* How/Who ?
|
||||
@@ -16,56 +16,24 @@ in the free and open source software world.
|
||||
|
||||
If you downloaded this file, you must know what it is : a library for
|
||||
accessing ssh client services through C libraries calls in a simple manner.
|
||||
The client is there as a programming example and isn't at all doing its job
|
||||
correctly (doesn't verify public key hashes with the ones in ~/.ssh/
|
||||
and doesn't handle TERM - yet)
|
||||
Everybody can use this software under the terms of the LGPL - see the COPYING
|
||||
file
|
||||
|
||||
If you ask yourself how to compile libssh, please read INSTALL before anything.
|
||||
3* What ?
|
||||
-_-_-_-_-_
|
||||
|
||||
3* Where ?
|
||||
The SSH library features :
|
||||
-Full C library functions for manipulating a client-side SSH connection
|
||||
-Fully configurable sessions
|
||||
-Support for AES-128,AES-192,AES-256,blowfish, in cbc mode
|
||||
-use multiple SSH connections in a same process, at same time.
|
||||
-usable SFTP implementation
|
||||
-Public key and password authentication
|
||||
|
||||
4* Where ?
|
||||
-_-_-_-_-_-_
|
||||
|
||||
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
|
||||
---------------------------
|
||||
|
||||
We changed libssh to be typesafe now:
|
||||
|
||||
SSH_SESSION *session -> ssh_session session
|
||||
SFTP_SESSION *sftp -> sftp_session sftp
|
||||
CHANNEL *channel -> ssh_channel channel
|
||||
STRING *string -> ssh_string string
|
||||
...
|
||||
|
||||
The options structure has been removed and there is a new function. This
|
||||
function can set all available options now. You can find the enum in the
|
||||
header file and it is documented. Example:
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
|
||||
5* Copyright policy
|
||||
-_-_-_-_-_-_-_-_-_-_
|
||||
|
||||
The developers of libssh have a policy of asking for contributions to be made
|
||||
under the personal copyright of the contributor, instead of a corporate
|
||||
copyright.
|
||||
|
||||
There are some reasons for the establishment of this policy:
|
||||
|
||||
* Individual copyrights make copyright registration in the US a simpler
|
||||
process.
|
||||
* If libssh is copyrighted by individuals rather than corporations,
|
||||
decisions regarding enforcement and protection of copyright will, more
|
||||
likely, be made in the interests of the project, and not in the interests
|
||||
of any corporation’s shareholders.
|
||||
* If we ever need to relicense a portion of the code contacting individuals
|
||||
for permission to do so is much easier than contacting a company.
|
||||
http://0xbadc0de.be/?part=libssh
|
||||
|
||||
@@ -34,26 +34,15 @@ cleanup_and_exit () {
|
||||
}
|
||||
|
||||
function configure() {
|
||||
if [ -n "${CMAKEDIR}" ]; then
|
||||
${CMAKEDIR}/bin/cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
|
||||
else
|
||||
cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
|
||||
fi
|
||||
cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
|
||||
}
|
||||
|
||||
function compile() {
|
||||
if [ -f /proc/cpuinfo ]; then
|
||||
CPUCOUNT=$(grep -c processor /proc/cpuinfo)
|
||||
elif test `uname` = "SunOS" ; then
|
||||
CPUCOUNT=$(psrinfo -p)
|
||||
else
|
||||
CPUCOUNT="1"
|
||||
fi
|
||||
|
||||
CPUCOUNT=$(grep -c processor /proc/cpuinfo)
|
||||
if [ "${CPUCOUNT}" -gt "1" ]; then
|
||||
${MAKE} -j${CPUCOUNT} $1 || cleanup_and_exit $?
|
||||
make -j${CPUCOUNT} $1 || cleanup_and_exit $?
|
||||
else
|
||||
${MAKE} $1 || exit $?
|
||||
make $1 || exit $?
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -62,18 +51,13 @@ 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]"
|
||||
cleanup_and_exit
|
||||
}
|
||||
|
||||
cd ${BUILDDIR}
|
||||
|
||||
# the default CMake options:
|
||||
OPTIONS="--graphviz=${BUILDDIR}/libssh.dot"
|
||||
|
||||
# the default 'make' utility:
|
||||
MAKE="make"
|
||||
OPTIONS="--graphviz=${BUILDDIR}/libssh.dot -DUNIT_TESTING=ON -DWITH_SSH1=ON -DWITH_SERVER=ON"
|
||||
|
||||
while test -n "$1"; do
|
||||
PARAM="$1"
|
||||
@@ -100,9 +84,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"
|
||||
;;
|
||||
@@ -121,33 +102,6 @@ while test -n "$1"; do
|
||||
OPTIONS="${OPTIONS} -DSYSCONF_INSTALL_DIR=${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-cmakedir)
|
||||
CMAKEDIR="${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-make)
|
||||
MAKE="${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-ccompiler)
|
||||
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-withstaticlib)
|
||||
OPTIONS="${OPTIONS} -DWITH_STATIC_LIB=ON"
|
||||
;;
|
||||
*-unittesting)
|
||||
OPTIONS="${OPTIONS} -DWITH_TESTING=ON"
|
||||
;;
|
||||
*-clientunittesting)
|
||||
OPTIONS="${OPTIONS} -DWITH_CLIENT_TESTING=ON"
|
||||
;;
|
||||
*-withssh1)
|
||||
OPTIONS="${OPTIONS} -DWITH_SSH1=ON"
|
||||
;;
|
||||
*-withserver)
|
||||
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
|
||||
;;
|
||||
----noarg)
|
||||
echo "$ARG does not take an argument"
|
||||
cleanup_and_exit
|
||||
@@ -162,7 +116,7 @@ while test -n "$1"; do
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "${DOMAKE}" == "1" ]; then
|
||||
if [ ${DOMAKE} -eq 1 ]; then
|
||||
OPTIONS="${OPTIONS} -DCMAKE_BUILD_TYPE=${BUILD_TYPE}"
|
||||
fi
|
||||
|
||||
@@ -195,3 +149,4 @@ exec >&0 2>&0 # so that the logging tee finishes
|
||||
sleep 1 # wait till tee terminates
|
||||
|
||||
cleanup_and_exit 0
|
||||
|
||||
|
||||
@@ -1,23 +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@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
|
||||
function (ADD_CMOCKERY_TEST _testName _testSource)
|
||||
add_executable(${_testName} ${_testSource})
|
||||
target_link_libraries(${_testName} ${ARGN})
|
||||
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
|
||||
endfunction (ADD_CMOCKERY_TEST)
|
||||
@@ -1,71 +1,50 @@
|
||||
# define system dependent compiler flags
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(MacroCheckCCompilerFlagSSP)
|
||||
|
||||
if (UNIX AND NOT WIN32)
|
||||
#
|
||||
# Define GNUCC compiler flags
|
||||
#
|
||||
if (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||
# add -Wconversion ?
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
|
||||
if (CMAKE_COMPILER_IS_GNUCC)
|
||||
add_definitions(-Wall -Wextra -Wmissing-prototypes -Wdeclaration-after-statement -Wunused)
|
||||
|
||||
# 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)
|
||||
add_definitions(-fPIC)
|
||||
endif (WITH_FPIC)
|
||||
|
||||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
|
||||
endif (WITH_STACK_PROTECTOR)
|
||||
|
||||
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||
if (WITH_FORTIFY_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
|
||||
endif (WITH_FORTIFY_SOURCE)
|
||||
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||
|
||||
#
|
||||
# Check for large filesystem support
|
||||
#
|
||||
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS64_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
# 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
|
||||
)
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
|
||||
|
||||
add_definitions(${_lfs_CFLAGS})
|
||||
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)
|
||||
|
||||
check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
add_definitions(-fstack-protector)
|
||||
endif (WITH_STACK_PROTECTOR)
|
||||
|
||||
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||
if (WITH_FORTIFY_SOURCE)
|
||||
add_definitions(-D_FORTIFY_SOURCE=2)
|
||||
endif (WITH_FORTIFY_SOURCE)
|
||||
endif (CMAKE_COMPILER_IS_GNUCC)
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
if (MSVC)
|
||||
# Use secure functions by defaualt and suppress warnings about
|
||||
#"deprecated" functions
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
|
||||
endif (MSVC)
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
if (WIN32)
|
||||
# Same same
|
||||
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
|
||||
set(SBIN_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LIB_INSTALL_DIR "lib" CACHE PATH "-")
|
||||
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
|
||||
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
|
||||
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
|
||||
set(ICON_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(SOUND_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
|
||||
elseif (UNIX OR OS2)
|
||||
if (UNIX)
|
||||
IF (NOT APPLICATION_NAME)
|
||||
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
|
||||
SET(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -101,4 +90,18 @@ elseif (UNIX OR OS2)
|
||||
"${SHARE_INSTALL_PREFIX}/info"
|
||||
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
|
||||
)
|
||||
endif ()
|
||||
endif (UNIX)
|
||||
|
||||
if (WIN32)
|
||||
# Same same
|
||||
set(BIN_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(SBIN_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LIB_INSTALL_DIR "lib" CACHE PATH "-")
|
||||
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
|
||||
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
|
||||
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
|
||||
set(ICON_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(SOUND_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
|
||||
endif (WIN32)
|
||||
|
||||
|
||||
@@ -1,28 +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")
|
||||
@@ -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@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 (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,63 +0,0 @@
|
||||
# - Try to find CMockery
|
||||
# Once done this will define
|
||||
#
|
||||
# CMOCKERY_FOUND - system has CMockery
|
||||
# CMOCKERY_INCLUDE_DIRS - the CMockery include directory
|
||||
# CMOCKERY_LIBRARIES - Link these to use CMockery
|
||||
# CMOCKERY_DEFINITIONS - Compiler switches required for using CMockery
|
||||
#
|
||||
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(CMOCKERY_FOUND TRUE)
|
||||
else (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)
|
||||
|
||||
find_path(CMOCKERY_INCLUDE_DIR
|
||||
NAMES
|
||||
google/cmockery.h
|
||||
PATHS
|
||||
${_CMOCKERY_DIR}/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
$ENV{PROGRAMFILES}/cmockery/include
|
||||
)
|
||||
|
||||
find_library(CMOCKERY_LIBRARY
|
||||
NAMES
|
||||
cmockery
|
||||
PATHS
|
||||
${_CMOCKERY_DIR}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
$ENV{PROGRAMFILES}/cmockery/lib
|
||||
)
|
||||
|
||||
set(CMOCKERY_INCLUDE_DIRS
|
||||
${CMOCKERY_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (CMOCKERY_LIBRARY)
|
||||
set(CMOCKERY_LIBRARIES
|
||||
${CMOCKERY_LIBRARIES}
|
||||
${CMOCKERY_LIBRARY}
|
||||
)
|
||||
endif (CMOCKERY_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(CMockery DEFAULT_MSG CMOCKERY_LIBRARIES CMOCKERY_INCLUDE_DIRS)
|
||||
|
||||
# show the CMOCKERY_INCLUDE_DIRS and CMOCKERY_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(CMOCKERY_INCLUDE_DIRS CMOCKERY_LIBRARIES)
|
||||
|
||||
endif (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)
|
||||
@@ -6,65 +6,72 @@
|
||||
# GCRYPT_LIBRARIES - Link these to use GCrypt
|
||||
# GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2009-2011 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.
|
||||
#
|
||||
|
||||
|
||||
if (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
# set(GCRYPT_FOUND TRUE)
|
||||
# in cache already
|
||||
set(GCRYPT_FOUND TRUE)
|
||||
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
set(_GCRYPT_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/libgcrypt"
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
NAMES
|
||||
gcrypt.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR)
|
||||
|
||||
find_library(GCRYPT_LIBRARY
|
||||
NAMES
|
||||
gcrypt
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(GCRYPT_LIBRARY)
|
||||
|
||||
if (GCRYPT_LIBRARY)
|
||||
set(GCRYPT_FOUND TRUE CACHE INTERNAL "Wether the gcrypt library has been found" FORCE)
|
||||
endif (GCRYPT_LIBRARY)
|
||||
|
||||
set(GCRYPT_INCLUDE_DIRS
|
||||
${GCRYPT_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
set(GCRYPT_LIBRARIES
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GCRYPT_LIBRARY}
|
||||
)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
find_path(GCRYPT_ROOT_DIR
|
||||
NAMES
|
||||
include/gcrypt.h
|
||||
PATHS
|
||||
${_GCRYPT_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(ZLIB_ROOT_DIR)
|
||||
if (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
|
||||
set(GCRYPT_FOUND TRUE)
|
||||
endif (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
|
||||
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
NAMES
|
||||
gcrypt.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/lib/sfw/include
|
||||
${GCRYPT_ROOT_DIR}/include
|
||||
)
|
||||
set(GCRYPT_INCLUDE_DIRS ${GCRYPT_INCLUDE_DIR})
|
||||
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)
|
||||
|
||||
find_library(GCRYPT_LIBRARY
|
||||
NAMES
|
||||
gcrypt
|
||||
gcrypt11
|
||||
libgcrypt-11
|
||||
PATHS
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
${GCRYPT_ROOT_DIR}/lib
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GCrypt DEFAULT_MSG GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
|
||||
|
||||
endif (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
# - Try to find NSIS
|
||||
# Once done this will define
|
||||
#
|
||||
# NSIS_ROOT_DIR - Set this variable to the root installation of ZLIB
|
||||
#
|
||||
# Read-Only variables:
|
||||
# NSIS_FOUND - system has NSIS
|
||||
# NSIS_MAKE - NSIS creator executable
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2010-2011 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
set(_NSIS_ROOT_PATHS
|
||||
C:/NSIS/Bin
|
||||
"$ENV{PROGRAMFILES}/NSIS"
|
||||
)
|
||||
|
||||
find_program(NSIS_MAKE
|
||||
NAMES
|
||||
makensis
|
||||
PATHS
|
||||
${NSIS_ROOT_PATH}
|
||||
${NSIS_ROOT_PATH}/Bin
|
||||
${_NSIS_ROOT_PATHS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
|
||||
|
||||
mark_as_advanced(NSIS_MAKE)
|
||||
@@ -1,208 +1,159 @@
|
||||
# - Try to find OpenSSL
|
||||
# Once done this will define
|
||||
#
|
||||
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
|
||||
#
|
||||
# Read-Only variables:
|
||||
# OPENSSL_FOUND - system has OpenSSL
|
||||
# OPENSSL_INCLUDE_DIRS - the OpenSSL include directory
|
||||
# OPENSSL_LIBRARIES - Link these to use OpenSSL
|
||||
# OPENSSL_DEFINITIONS - Compiler switches required for using OpenSSL
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2006-2009 Kitware, Inc.
|
||||
# Copyright (c) 2006 Alexander Neundorf <neundorf@kde.org>
|
||||
# Copyright (c) 2009-2010 Mathieu Malaterre <mathieu.malaterre@gmail.com>
|
||||
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
|
||||
# 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.
|
||||
#
|
||||
|
||||
|
||||
if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
# 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)
|
||||
|
||||
if (UNIX)
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(_OPENSSL openssl)
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
endif (UNIX)
|
||||
find_path(OPENSSL_INCLUDE_DIR
|
||||
NAMES
|
||||
openssl/ssl.h
|
||||
PATHS
|
||||
${_OPENSSL_INCLUDEDIR}
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIR)
|
||||
|
||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
set(_OPENSSL_ROOT_HINTS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
||||
find_library(SSL_LIBRARY
|
||||
NAMES
|
||||
ssl
|
||||
PATHS
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(SSL_LIBRARY)
|
||||
|
||||
find_library(SSLEAY32_LIBRARY
|
||||
NAMES
|
||||
ssleay32
|
||||
PATHS
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(SSLEAY32_LIBRARY)
|
||||
|
||||
find_library(SSLEAY32MD_LIBRARY
|
||||
NAMES
|
||||
ssleay32MD
|
||||
PATHS
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(SSLEAY32MD_LIBRARY)
|
||||
|
||||
find_library(CRYPTO_LIBRARY
|
||||
NAMES
|
||||
crypto
|
||||
PATHS
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(CRYPTO_LIBRARY)
|
||||
|
||||
if (SSL_LIBRARY)
|
||||
set(SSL_FOUND TRUE CACHE INTERNAL "Wether the ssl library has been found" FORCE)
|
||||
endif (SSL_LIBRARY)
|
||||
|
||||
if (SSLEAY32_LIBRARY)
|
||||
set(SSLEAY32_FOUND TRUE CACHE INTERNAL "Wether the ssleay32 library has been found" FORCE)
|
||||
endif (SSLEAY32_LIBRARY)
|
||||
|
||||
if (SSLEAY32MD_LIBRARY)
|
||||
set(SSLEAY32MD_FOUND TRUE CACHE INTERNAL "Wether the ssleay32MD library has been found" FORCE)
|
||||
endif (SSLEAY32MD_LIBRARY)
|
||||
|
||||
if (CRYPTO_LIBRARY)
|
||||
set(CRYPTO_FOUND TRUE CACHE INTERNAL "Wether the crypto library has been found" FORCE)
|
||||
endif (CRYPTO_LIBRARY)
|
||||
|
||||
set(OPENSSL_INCLUDE_DIRS
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (SSL_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSL_LIBRARY}
|
||||
)
|
||||
endif (SSL_FOUND)
|
||||
|
||||
set(_OPENSSL_ROOT_PATHS
|
||||
"C:/OpenSSL/"
|
||||
"C:/OpenSSL-Win32/"
|
||||
"C:/OpenSSL-Win64/"
|
||||
"$ENV{PROGRAMFILES}/OpenSSL"
|
||||
"$ENV{PROGRAMFILES}/OpenSSL-Win32"
|
||||
"$ENV{PROGRAMFILES}/OpenSSL-Win64"
|
||||
if (SSLEAY32_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSLEAY32_LIBRARY}
|
||||
)
|
||||
endif (SSLEAY32_FOUND)
|
||||
|
||||
find_path(OPENSSL_ROOT_DIR
|
||||
NAMES
|
||||
include/openssl/ssl.h
|
||||
HINTS
|
||||
${_OPENSSL_ROOT_HINTS}
|
||||
PATHS
|
||||
${_OPENSSL_ROOT_PATHS}
|
||||
if (SSLEAY32MD_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSLEAY32MD_LIBRARY}
|
||||
)
|
||||
mark_as_advanced(OPENSSL_ROOT_DIR)
|
||||
endif (SSLEAY32MD_FOUND)
|
||||
|
||||
find_path(OPENSSL_INCLUDE_DIR
|
||||
NAMES
|
||||
openssl/ssl.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/lib/sfw/include
|
||||
${OPENSSL_ROOT_DIR}/include
|
||||
if (CRYPTO_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARY}
|
||||
)
|
||||
endif (CRYPTO_FOUND)
|
||||
|
||||
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIRS)
|
||||
if (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
endif (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
|
||||
|
||||
if (WIN32 AND NOT CYGWIN)
|
||||
# MINGW should go here too
|
||||
if (MSVC)
|
||||
# /MD and /MDd are the standard values - if someone wants to use
|
||||
# others, the libnames have to change here too
|
||||
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
|
||||
# TODO: handle /MT and static lib
|
||||
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
|
||||
# * MD for dynamic-release
|
||||
# * MDd for dynamic-debug
|
||||
# * MT for static-release
|
||||
# * MTd for static-debug
|
||||
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)
|
||||
|
||||
# Implementation details:
|
||||
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
|
||||
# libeay32MD.lib is identical to ../libeay32.lib, and
|
||||
# ssleay32MD.lib is identical to ../ssleay32.lib
|
||||
find_library(LIB_EAY_DEBUG
|
||||
NAMES
|
||||
libeay32MDd
|
||||
libeay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/VC
|
||||
)
|
||||
|
||||
find_library(LIB_EAY_RELEASE
|
||||
NAMES
|
||||
libeay32MD
|
||||
libeay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/VC
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_DEBUG
|
||||
NAMES
|
||||
ssleay32MDd
|
||||
ssleay32
|
||||
ssl
|
||||
PATHS ${OPENSSL_ROOT_DIR}/lib/VC
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_RELEASE
|
||||
NAMES
|
||||
ssleay32MD
|
||||
ssleay32
|
||||
ssl
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/VC
|
||||
)
|
||||
|
||||
if (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
||||
set(OPENSSL_LIBRARIES
|
||||
optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}
|
||||
optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG}
|
||||
)
|
||||
else (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
||||
set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
|
||||
endif (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
||||
|
||||
mark_as_advanced(SSL_EAY_DEBUG SSL_EAY_RELEASE)
|
||||
mark_as_advanced(LIB_EAY_DEBUG LIB_EAY_RELEASE)
|
||||
elseif (MINGW)
|
||||
# same player, for MingW
|
||||
find_library(LIB_EAY
|
||||
NAMES
|
||||
libeay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/MinGW
|
||||
)
|
||||
|
||||
find_library(SSL_EAY
|
||||
NAMES
|
||||
ssleay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/MinGW
|
||||
)
|
||||
|
||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
|
||||
else(MSVC)
|
||||
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
|
||||
find_library(LIB_EAY
|
||||
NAMES
|
||||
libeay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
find_library(SSL_EAY
|
||||
NAMES
|
||||
ssleay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
|
||||
endif(MSVC)
|
||||
else (WIN32 AND NOT CYGWIN)
|
||||
find_library(OPENSSL_SSL_LIBRARIES
|
||||
NAMES
|
||||
ssl
|
||||
ssleay32
|
||||
ssleay32MD
|
||||
PATHS
|
||||
${_OPENSSL_LIBDIR}
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
|
||||
find_library(OPENSSL_CRYPTO_LIBRARIES
|
||||
NAMES
|
||||
crypto
|
||||
PATHS
|
||||
${_OPENSSL_LIBDIR}
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
|
||||
mark_as_advanced(OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES)
|
||||
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
endif (WIN32 AND NOT CYGWIN)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OpenSSL DEFAULT_MSG OPENSSL_LIBRARIES OPENSSL_INCLUDE_DIRS)
|
||||
# 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)
|
||||
|
||||
|
||||
@@ -1,119 +1,79 @@
|
||||
# - Try to find ZLIB
|
||||
# Once done this will define
|
||||
#
|
||||
# ZLIB_ROOT_DIR - Set this variable to the root installation of ZLIB
|
||||
#
|
||||
# Read-Only variables:
|
||||
# ZLIB_FOUND - system has ZLIB
|
||||
# ZLIB_INCLUDE_DIRS - the ZLIB include directory
|
||||
# ZLIB_LIBRARIES - Link these to use ZLIB
|
||||
# ZLIB_DEFINITIONS - Compiler switches required for using ZLIB
|
||||
#
|
||||
# ZLIB_VERSION_STRING - The version of zlib found (x.y.z)
|
||||
# ZLIB_VERSION_MAJOR - The major version of zlib
|
||||
# ZLIB_VERSION_MINOR - The minor version of zlib
|
||||
# ZLIB_VERSION_PATCH - The patch version of zlib
|
||||
# ZLIB_VERSION_TWEAK - The tweak version of zlib
|
||||
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# The following variable are provided for backward compatibility
|
||||
#
|
||||
# ZLIB_MAJOR_VERSION - The major version of zlib
|
||||
# ZLIB_MINOR_VERSION - The minor version of zlib
|
||||
# ZLIB_PATCH_VERSION - The patch version of zlib
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2001-2009 Kitware, Inc.
|
||||
# Copyright (c) 2011 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# 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)
|
||||
|
||||
set(_ZLIB_ROOT_HINTS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]/include"
|
||||
find_path(ZLIB_INCLUDE_DIR
|
||||
NAMES
|
||||
zlib.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
mark_as_advanced(ZLIB_INCLUDE_DIR)
|
||||
|
||||
find_library(Z_LIBRARY
|
||||
NAMES
|
||||
z
|
||||
zlib
|
||||
zlib1
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(Z_LIBRARY)
|
||||
|
||||
if (Z_LIBRARY)
|
||||
set(Z_FOUND TRUE)
|
||||
endif (Z_LIBRARY)
|
||||
|
||||
set(ZLIB_INCLUDE_DIRS
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (Z_FOUND)
|
||||
set(ZLIB_LIBRARIES
|
||||
${ZLIB_LIBRARIES}
|
||||
${Z_LIBRARY}
|
||||
)
|
||||
endif (Z_FOUND)
|
||||
|
||||
set(_ZLIB_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/zlib"
|
||||
)
|
||||
if (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
|
||||
set(ZLIB_FOUND TRUE)
|
||||
endif (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
|
||||
|
||||
find_path(ZLIB_ROOT_DIR
|
||||
NAMES
|
||||
include/zlib.h
|
||||
HINTS
|
||||
${_ZLIB_ROOT_HINTS}
|
||||
PATHS
|
||||
${_ZLIB_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(ZLIB_ROOT_DIR)
|
||||
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)
|
||||
|
||||
# check for header file
|
||||
find_path(ZLIB_INCLUDE_DIR
|
||||
NAMES
|
||||
zlib.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/lib/sfw/include
|
||||
${ZLIB_ROOT_DIR}/include
|
||||
)
|
||||
mark_as_advanced(ZLIB_INCLUDE_DIR)
|
||||
# show the ZLIB_INCLUDE_DIRS and ZLIB_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES)
|
||||
|
||||
# check version number
|
||||
if (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
|
||||
file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$")
|
||||
|
||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}")
|
||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}")
|
||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}")
|
||||
|
||||
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}")
|
||||
|
||||
# only append a TWEAK version if it exists:
|
||||
set(ZLIB_VERSION_TWEAK "")
|
||||
if ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
|
||||
set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}")
|
||||
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_STRING}.${ZLIB_VERSION_TWEAK}")
|
||||
endif ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
|
||||
|
||||
set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}")
|
||||
set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}")
|
||||
set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}")
|
||||
endif (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
|
||||
|
||||
find_library(ZLIB_LIBRARY
|
||||
NAMES
|
||||
z
|
||||
zdll
|
||||
zlib
|
||||
zlib1
|
||||
PATHS
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
${ZLIB_ROOT_DIR}/lib
|
||||
)
|
||||
mark_as_advanced(ZLIB_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ZLIB DEFAULT_MSG ZLIB_INCLUDE_DIR ZLIB_LIBRARY)
|
||||
#find_package_handle_standard_args(ZLIB REQUIRED_VARS ZLIB_INCLUDE_DIR ZLIB_LIBRARY
|
||||
# VERSION_VAR ZLIB_VERSION_STRING)
|
||||
|
||||
if (ZLIB_FOUND)
|
||||
set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
|
||||
set(ZLIB_LIBRARIES ${ZLIB_LIBRARY})
|
||||
endif (ZLIB_FOUND)
|
||||
endif (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
|
||||
|
||||
@@ -1,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 the check_c_source_compiles macro.
|
||||
# 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)
|
||||
|
||||
MACRO (CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
|
||||
SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
CHECK_C_SOURCE_COMPILES("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
|
||||
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
ENDMACRO (CHECK_C_COMPILER_FLAG_SSP)
|
||||
|
||||
@@ -1,100 +1,127 @@
|
||||
# - Run Doxygen
|
||||
# -helper macro to add a "doc" target with CMake build system.
|
||||
# and configure doxy.config.in to doxy.config
|
||||
#
|
||||
# Adds a doxygen target that runs doxygen to generate the html
|
||||
# and optionally the LaTeX API documentation.
|
||||
# The doxygen target is added to the doc target as dependency.
|
||||
# i.e.: the API documentation is built with:
|
||||
# make doc
|
||||
#
|
||||
# USAGE: INCLUDE IN PROJECT
|
||||
#
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
# include(UseDoxygen)
|
||||
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
|
||||
# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
|
||||
# Creates .chm windows help file if MS HTML help workshop
|
||||
# (available from http://msdn.microsoft.com/workshop/author/htmlhelp)
|
||||
# is installed with its DLLs in PATH.
|
||||
#
|
||||
#
|
||||
# Variables you may define are:
|
||||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
|
||||
# Please note, that the tools, e.g.:
|
||||
# doxygen, dot, latex, dvips, makeindex, gswin32, etc.
|
||||
# must be in path.
|
||||
#
|
||||
# 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".
|
||||
# Note about Visual Studio Projects:
|
||||
# MSVS has its own path environment which may differ from the shell.
|
||||
# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1
|
||||
#
|
||||
# author Jan Woetzel 2004-2006
|
||||
# www.mip.informatik.uni-kiel.de/~jw
|
||||
|
||||
#
|
||||
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
macro(usedoxygen_set_default name value)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}")
|
||||
endif()
|
||||
endmacro()
|
||||
FIND_PACKAGE(Doxygen)
|
||||
|
||||
find_package(Doxygen)
|
||||
IF (DOXYGEN_FOUND)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
find_file(DOXYFILE_IN
|
||||
NAMES
|
||||
doxy.config.in
|
||||
PATHS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_ROOT}/Modules/
|
||||
NO_DEFAULT_PATH)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
||||
endif()
|
||||
# click+jump in Emacs and Visual Studio (for doxy.config) (jw)
|
||||
IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
|
||||
SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"")
|
||||
ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
|
||||
SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"")
|
||||
ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
|
||||
|
||||
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
|
||||
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
|
||||
# we need latex for doxygen because of the formulas
|
||||
FIND_PACKAGE(LATEX)
|
||||
IF (NOT LATEX_COMPILER)
|
||||
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
|
||||
ENDIF (NOT LATEX_COMPILER)
|
||||
IF (NOT MAKEINDEX_COMPILER)
|
||||
MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
|
||||
ENDIF (NOT MAKEINDEX_COMPILER)
|
||||
IF (NOT DVIPS_CONVERTER)
|
||||
MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
|
||||
ENDIF (NOT DVIPS_CONVERTER)
|
||||
FIND_PROGRAM(DOXYGEN_DOT_EXECUTABLE_PATH NAMES dot)
|
||||
IF (DOXYGEN_DOT_EXECUTABLE_PATH)
|
||||
SET(DOXYGEN_DOT_FOUND "YES")
|
||||
ENDIF (DOXYGEN_DOT_EXECUTABLE_PATH)
|
||||
|
||||
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
|
||||
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
|
||||
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
|
||||
@ONLY )
|
||||
# use (configured) doxy.config from (out of place) BUILD tree:
|
||||
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
|
||||
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
|
||||
# use static hand-edited doxy.config from SOURCE tree:
|
||||
SET(DOXY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
|
||||
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
|
||||
MESSAGE(STATUS "WARNING: using existing ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config instead of configuring from doxy.config.in file.")
|
||||
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
|
||||
IF (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
|
||||
# using template doxy.config.in
|
||||
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
|
||||
CONFIGURE_FILE(${CMAKE_MODULE_PATH}/doxy.config.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
|
||||
@ONLY )
|
||||
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
|
||||
ELSE (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
|
||||
# failed completely...
|
||||
MESSAGE(SEND_ERROR "Please create ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in (or doxy.config as fallback)")
|
||||
ENDIF(EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
|
||||
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
|
||||
|
||||
set(DOXYFILE_LATEX FALSE)
|
||||
set(DOXYFILE_PDFLATEX FALSE)
|
||||
set(DOXYFILE_DOT FALSE)
|
||||
ADD_CUSTOM_TARGET(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
|
||||
|
||||
find_package(LATEX)
|
||||
if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
|
||||
set(DOXYFILE_LATEX TRUE)
|
||||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
|
||||
# create a windows help .chm file using hhc.exe
|
||||
# HTMLHelp DLL must be in path!
|
||||
# fallback: use hhw.exe interactively
|
||||
IF (WIN32)
|
||||
FIND_PACKAGE(HTMLHelp)
|
||||
IF (HTML_HELP_COMPILER)
|
||||
SET (TMP "${CMAKE_CURRENT_BINARY_DIR}\\doc\\html\\index.hhp")
|
||||
STRING(REGEX REPLACE "[/]" "\\\\" HHP_FILE ${TMP} )
|
||||
# MESSAGE(SEND_ERROR "DBG HHP_FILE=${HHP_FILE}")
|
||||
ADD_CUSTOM_TARGET(winhelp ${HTML_HELP_COMPILER} ${HHP_FILE})
|
||||
ADD_DEPENDENCIES (winhelp doc)
|
||||
|
||||
IF (NOT TARGET_DOC_SKIP_INSTALL)
|
||||
# install windows help?
|
||||
# determine useful name for output file
|
||||
# should be project and version unique to allow installing
|
||||
# multiple projects into one global directory
|
||||
IF (EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
|
||||
IF (PROJECT_NAME)
|
||||
SET(OUT "${PROJECT_NAME}")
|
||||
ELSE (PROJECT_NAME)
|
||||
SET(OUT "Documentation") # default
|
||||
ENDIF(PROJECT_NAME)
|
||||
IF (${PROJECT_NAME}_VERSION_MAJOR)
|
||||
SET(OUT "${OUT}-${${PROJECT_NAME}_VERSION_MAJOR}")
|
||||
IF (${PROJECT_NAME}_VERSION_MINOR)
|
||||
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_MINOR}")
|
||||
IF (${PROJECT_NAME}_VERSION_PATCH)
|
||||
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_PATCH}")
|
||||
ENDIF(${PROJECT_NAME}_VERSION_PATCH)
|
||||
ENDIF(${PROJECT_NAME}_VERSION_MINOR)
|
||||
ENDIF(${PROJECT_NAME}_VERSION_MAJOR)
|
||||
# keep suffix
|
||||
SET(OUT "${OUT}.chm")
|
||||
|
||||
#MESSAGE("DBG ${PROJECT_BINARY_DIR}/doc/html/index.chm \n${OUT}")
|
||||
# create target used by install and package commands
|
||||
INSTALL(FILES "${PROJECT_BINARY_DIR}/doc/html/index.chm"
|
||||
DESTINATION "doc"
|
||||
RENAME "${OUT}"
|
||||
)
|
||||
ENDIF(EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
|
||||
ENDIF(NOT TARGET_DOC_SKIP_INSTALL)
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
ENDIF(HTML_HELP_COMPILER)
|
||||
# MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}")
|
||||
ENDIF (WIN32)
|
||||
ENDIF(DOXYGEN_FOUND)
|
||||
|
||||
if(PDFLATEX_COMPILER)
|
||||
set(DOXYFILE_PDFLATEX TRUE)
|
||||
endif()
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
set(DOXYFILE_DOT TRUE)
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET doxygen
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_MAKE_PROGRAM}
|
||||
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
endif()
|
||||
|
||||
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
|
||||
endif()
|
||||
|
||||
get_target_property(DOC_TARGET doc TYPE)
|
||||
if(NOT DOC_TARGET)
|
||||
add_custom_target(doc)
|
||||
endif()
|
||||
|
||||
add_dependencies(doc doxygen)
|
||||
endif()
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
|
||||
/************************** HEADER FILES *************************/
|
||||
|
||||
/* Define to 1 if you have the <argp.h> header file. */
|
||||
#cmakedefine HAVE_ARGP_H 1
|
||||
|
||||
/* Define to 1 if you have the <pty.h> header file. */
|
||||
#cmakedefine HAVE_PTY_H 1
|
||||
|
||||
@@ -26,63 +23,29 @@
|
||||
/* Define to 1 if you have the <openssl/aes.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_AES_H 1
|
||||
|
||||
/* Define to 1 if you have the <wspiapi.h> header file. */
|
||||
#cmakedefine HAVE_WSPIAPI_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/blowfish.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_BLOWFISH_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/des.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_DES_H 1
|
||||
|
||||
/* Define to 1 if you have the <pthread.h> header file. */
|
||||
#cmakedefine HAVE_PTHREAD_H 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
|
||||
|
||||
/* Define to 1 if you have the `_vsnprintf' function. */
|
||||
#cmakedefine HAVE__VSNPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `_vsnprintf_s' function. */
|
||||
#cmakedefine HAVE__VSNPRINTF_S 1
|
||||
|
||||
/* Define to 1 if you have the `strncpy' function. */
|
||||
#cmakedefine HAVE_STRNCPY 1
|
||||
|
||||
/* Define to 1 if you have the `cfmakeraw' function. */
|
||||
#cmakedefine HAVE_CFMAKERAW 1
|
||||
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#cmakedefine HAVE_GETADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the `gethostbyname' function. */
|
||||
#cmakedefine HAVE_GETHOSTBYNAME 1
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#cmakedefine HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#cmakedefine HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the `regcomp' function. */
|
||||
#cmakedefine HAVE_REGCOMP 1
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define to 1 if you have the `ntohll' function. */
|
||||
#cmakedefine HAVE_NTOHLL 1
|
||||
|
||||
/*************************** LIBRARIES ***************************/
|
||||
|
||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||
@@ -94,16 +57,12 @@
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#cmakedefine HAVE_LIBZ 1
|
||||
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#cmakedefine HAVE_PTHREAD 1
|
||||
|
||||
|
||||
/**************************** OPTIONS ****************************/
|
||||
|
||||
/* Define to 1 if you want to enable ZLIB */
|
||||
#cmakedefine WITH_LIBZ 1
|
||||
|
||||
/* Define to 1 if you want to enable SFTP */
|
||||
/* Define to 1 if you want to enable SSH1 */
|
||||
#cmakedefine WITH_SFTP 1
|
||||
|
||||
/* Define to 1 if you want to enable SSH1 */
|
||||
@@ -115,14 +74,14 @@
|
||||
/* Define to 1 if you want to enable debug output for crypto functions */
|
||||
#cmakedefine DEBUG_CRYPTO 1
|
||||
|
||||
/* Define to 1 if you want to enable pcap output support (experimental) */
|
||||
#cmakedefine WITH_PCAP 1
|
||||
|
||||
/* Define to 1 if you want to enable calltrace debug output */
|
||||
#cmakedefine DEBUG_CALLTRACE 1
|
||||
|
||||
/*************************** ENDIAN *****************************/
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#cmakedefine WORDS_BIGENDIAN 1
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
/* # undef WORDS_BIGENDIAN */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
886
doc/API.html
Normal file
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 +0,0 @@
|
||||
<!-- Doxygen TracFooter -->
|
||||
@@ -1,4 +0,0 @@
|
||||
<!-- Doxygen TracHeader -->
|
||||
<style>@import url(/chrome/site/doxygen.css);</style>
|
||||
<style>@import url(/chrome/site/tabs.css);</style>
|
||||
<!-- /Doxygen TracHeader -->
|
||||
@@ -1,373 +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_autopubkey() function also tries to authenticate using the
|
||||
SSH agent, if you have one running, or the "none" method otherwise.
|
||||
|
||||
If you wish to authenticate with public key by your own, follow these steps:
|
||||
- Retrieve the public key in a ssh_string using publickey_from_file().
|
||||
- Offer the public key to the SSH server using ssh_userauth_offer_pubkey().
|
||||
If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
|
||||
authenticate using the public key and you can go to the next step.
|
||||
- Retrieve the private key, using the privatekey_from_file() function. If
|
||||
a passphrase is needed, either the passphrase specified as argument or
|
||||
a callback (see callbacks section) will be used.
|
||||
- Authenticate using ssh_userauth_pubkey() with your public key string
|
||||
and private key.
|
||||
- Do not forget cleaning up memory using string_free() and privatekey_free().
|
||||
|
||||
Here is a minimalistic example of public key authentication:
|
||||
|
||||
@code
|
||||
int authenticate_pubkey(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_autopubkey(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_autopubkey
|
||||
@see ssh_userauth_offer_pubkey
|
||||
@see ssh_userauth_pubkey
|
||||
@see publickey_from_file
|
||||
@see publickey_from_privatekey
|
||||
@see string_free
|
||||
@see privatekey_from_file
|
||||
@see privatekey_free
|
||||
|
||||
|
||||
@subsection password Authenticating with a password
|
||||
|
||||
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, 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;
|
||||
|
||||
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];
|
||||
unsigned 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
|
||||
|
||||
*/
|
||||
1374
doc/doxy.config.in
1374
doc/doxy.config.in
File diff suppressed because it is too large
Load Diff
@@ -1,221 +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 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 (rc != SSH_OK) return rc;
|
||||
|
||||
rc = 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 = 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_forward_listen(),
|
||||
then ssh_channel_forward_accept().
|
||||
|
||||
When you call ssh_channel_forward_listen(), you can let the remote server
|
||||
chose the non-priviledged port it should listen to. Otherwise, you can chose
|
||||
your own priviledged or non-priviledged port. Beware that you should have
|
||||
administrative priviledges on the remote server to open a priviledged port
|
||||
(port number < 1024).
|
||||
|
||||
Below is an example of a very rough web server waiting for connections on port
|
||||
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;
|
||||
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_forward_listen(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_forward_accept(session, 60000);
|
||||
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,455 +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];
|
||||
unsigned 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) != 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.
|
||||
|
||||
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
|
||||
That's for thread safety, error messages that can be attached to a session
|
||||
aren't static anymore. Any error that happens during ssh_options_xxx()
|
||||
or ssh_connect() (i.e., outside of any session) can be retrieved by
|
||||
giving NULL as argument.
|
||||
|
||||
The SFTP subsystem has its own error codes, in addition to libssh ones.
|
||||
|
||||
|
||||
*/
|
||||
@@ -1,50 +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 (http://directory.fsf.org/project/libgcrypt/)
|
||||
or libcrypto (http://www.openssl.org/docs/crypto/crypto.html), two general-purpose
|
||||
cryptographic libraries.
|
||||
|
||||
This tutorial concentrates for its main part on the "client" side of libssh.
|
||||
To learn how to accept incoming SSH 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,24 +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.
|
||||
|
||||
On Windows you need to define LIBSSH_STATIC in the compiler command
|
||||
line. This is required cause the dynamic library needs to specify the
|
||||
dllimport attribute.
|
||||
|
||||
*/
|
||||
124
doc/mainpage.dox
124
doc/mainpage.dox
@@ -1,124 +0,0 @@
|
||||
/**
|
||||
|
||||
@mainpage
|
||||
|
||||
This is the online reference for developing with the libssh library. It
|
||||
documents the libssh C API and the C++ wrapper.
|
||||
|
||||
@section main-linking Linking
|
||||
|
||||
We created a small howto how to link libssh against your application, read
|
||||
@subpage libssh_linking.
|
||||
|
||||
@section main-tutorial Tutorial
|
||||
|
||||
You should start by reading @subpage libssh_tutorial, then reading the documentation of
|
||||
the interesting functions as you go.
|
||||
|
||||
@section main-features Features
|
||||
|
||||
The libssh library provides:
|
||||
|
||||
- Full C library functions for manipulating a client-side SSH connection
|
||||
- SSH2 and SSH1 protocol compliant
|
||||
- Fully configurable sessions
|
||||
- Server support
|
||||
- SSH agent authentication support
|
||||
- Support for AES-128, AES-192, AES-256, Blowfish, 3DES in CBC mode, and AES in CTR mode
|
||||
- Supports OpenSSL and GCrypt
|
||||
- Use multiple SSH connections in a same process, at same time
|
||||
- Use multiple channels in the same connection
|
||||
- Thread safety when using different sessions at same time
|
||||
- POSIX-like SFTP (Secure File Transfer) implementation with openssh extension support
|
||||
- SCP implementation
|
||||
- Large file system support (files bigger than 4GB)
|
||||
- RSA and DSS server public key supported
|
||||
- Compression support (with zlib)
|
||||
- Public key (RSA and DSS), password and keyboard-interactive authentication
|
||||
- Full poll()/WSAPoll() support and a poll-emulation for Win32.
|
||||
- Runs and tested under x86_64, x86, ARM, Sparc32, PPC under Linux, BSD, MacOSX, Solaris and Windows
|
||||
|
||||
@section main-copyright Copyright Policy
|
||||
|
||||
The developers of libssh have a policy of asking for contributions to be made
|
||||
under the personal copyright of the contributor, instead of a corporate
|
||||
copyright.
|
||||
|
||||
There are some reasons for the establishment of this policy:
|
||||
|
||||
@li Individual copyrights make copyright registration in the US a simpler
|
||||
process.
|
||||
@li If libssh is copyrighted by individuals rather than corporations,
|
||||
decisions regarding enforcement and protection of copyright will, more
|
||||
likely, be made in the interests of the project, and not in the interests
|
||||
of any corporation’s shareholders.
|
||||
@li If we ever need to relicense a portion of the code contacting individuals
|
||||
for permission to do so is much easier than contacting a company.
|
||||
|
||||
@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/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 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>
|
||||
|
||||
*/
|
||||
257
doc/scp.dox
257
doc/scp.dox
@@ -1,257 +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.
|
||||
|
||||
*/
|
||||
395
doc/sftp.dox
395
doc/sftp.dox
@@ -1,395 +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().
|
||||
|
||||
The following example prints the contents of remote file "/etc/profile". For
|
||||
each 1024 bytes of information read, it waits until the end of the read operation:
|
||||
|
||||
@code
|
||||
int sftp_read_sync(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type;
|
||||
sftp_file file;
|
||||
char buffer[1024];
|
||||
int nbytes, rc;
|
||||
|
||||
access_type = O_RDONLY;
|
||||
file = sftp_open(sftp, "/etc/profile", access_type, 0);
|
||||
if (file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
||||
while (nbytes > 0)
|
||||
{
|
||||
if (write(1, buffer, nbytes) != nbytes)
|
||||
{
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
if (nbytes < 0)
|
||||
{
|
||||
fprintf(stderr, "Error while reading file: %s\n", ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
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
|
||||
int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type;
|
||||
sftp_file file;
|
||||
char buffer[1024];
|
||||
int async_request;
|
||||
int nbytes;
|
||||
long counter;
|
||||
int rc;
|
||||
|
||||
access_type = O_RDONLY;
|
||||
file = sftp_open(sftp, "some_very_big_file", access_type, 0);
|
||||
if (file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
|
||||
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("%-22s %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,65 +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_pthread 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 can use a
|
||||
single session in several channels at the same time. This will 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_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_pthread);
|
||||
ssh_init();
|
||||
@endcode
|
||||
|
||||
However, you must be sure to link with the library ssh_threads_pthread. If
|
||||
you're using gcc, you must use the commandline
|
||||
@code
|
||||
gcc -o output input.c -lssh -lssh_threads_pthread
|
||||
@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
|
||||
|
||||
Good luck !
|
||||
*/
|
||||
@@ -1,48 +0,0 @@
|
||||
project(libssh-examples C CXX)
|
||||
|
||||
set(examples_SRCS
|
||||
authentication.c
|
||||
knownhosts.c
|
||||
connect_ssh.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
if (LINUX)
|
||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(scp_download scp_download.c ${examples_SRCS})
|
||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(samplessh sample.c ${examples_SRCS})
|
||||
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||
target_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)
|
||||
|
||||
if (WITH_SERVER)
|
||||
add_executable(samplesshd samplesshd.c)
|
||||
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SERVER)
|
||||
endif (LINUX)
|
||||
|
||||
add_executable(exec exec.c ${examples_SRCS})
|
||||
target_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})
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* authentication.c
|
||||
* This file contains an example of how to do an authentication to a
|
||||
* SSH server using libssh
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
int authenticate_kbdint(ssh_session session, const char *password) {
|
||||
int err;
|
||||
|
||||
err = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
while (err == SSH_AUTH_INFO) {
|
||||
const char *instruction;
|
||||
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);
|
||||
}
|
||||
|
||||
if (instruction && strlen(instruction) > 0) {
|
||||
printf("%s\n", instruction);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (ssh_userauth_kbdint_setanswer(session, i, answer) < 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));
|
||||
}
|
||||
|
||||
int authenticate_console(ssh_session session){
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *banner;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
}
|
||||
|
||||
method = ssh_auth_list(session);
|
||||
while (rc != SSH_AUTH_SUCCESS) {
|
||||
// Try to authenticate with public key first
|
||||
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
|
||||
rc = ssh_userauth_autopubkey(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to authenticate with keyboard interactive";
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||
rc = authenticate_kbdint(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
// Try to authenticate with password
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD) {
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n",banner);
|
||||
ssh_string_free_char(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* connect_ssh.c
|
||||
* This file contains an example of how to connect to a
|
||||
* SSH server using libssh
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
#include <stdio.h>
|
||||
|
||||
ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
ssh_session session;
|
||||
int auth=0;
|
||||
|
||||
session=ssh_new();
|
||||
if (session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(user != NULL){
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
if(verify_knownhost(session)<0){
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
if(auth==SSH_AUTH_SUCCESS){
|
||||
return session;
|
||||
} else if(auth==SSH_AUTH_DENIED){
|
||||
fprintf(stderr,"Authentication failed\n");
|
||||
} else {
|
||||
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
Copyright 2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
#ifndef EXAMPLES_COMMON_H_
|
||||
#define EXAMPLES_COMMON_H_
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
int authenticate_console(ssh_session session);
|
||||
int authenticate_kbdint(ssh_session session, const char *password);
|
||||
int verify_knownhost(ssh_session session);
|
||||
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
|
||||
|
||||
#endif /* EXAMPLES_COMMON_H_ */
|
||||
@@ -1,66 +0,0 @@
|
||||
/* simple exec example */
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#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();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* knownhosts.c
|
||||
* This file contains an example of how verify the identity of a
|
||||
* SSH server using libssh
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.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;
|
||||
int hlen;
|
||||
|
||||
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 : server's one is now :\n");
|
||||
ssh_print_hexa("Public key hash",hash, hlen);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
return -1;
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
|
||||
fprintf(stderr,"An attacker might change the default server key to confuse your client"
|
||||
"into thinking the key does not exist\n"
|
||||
"We advise you to rerun the client with -d or -r for more safety.\n");
|
||||
return -1;
|
||||
case SSH_SERVER_FILE_NOT_FOUND:
|
||||
fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
|
||||
fprintf(stderr,"the file will be automatically created.\n");
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
case SSH_SERVER_NOT_KNOWN:
|
||||
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;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)!=0){
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)==0){
|
||||
if (ssh_write_knownhost(session) < 0) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr, "error %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSH_SERVER_ERROR:
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"%s",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
/* libssh_scp.c
|
||||
* Sample implementation of a SCP client
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
char **sources;
|
||||
int nsources;
|
||||
char *destination;
|
||||
int verbosity=0;
|
||||
|
||||
struct location {
|
||||
int is_ssh;
|
||||
char *user;
|
||||
char *host;
|
||||
char *path;
|
||||
ssh_session session;
|
||||
ssh_scp scp;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
enum {
|
||||
READ,
|
||||
WRITE
|
||||
};
|
||||
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [options] [[user@]host1:]file1 ... \n"
|
||||
" [[user@]host2:]destination\n"
|
||||
"sample scp client - libssh-%s\n",
|
||||
// "Options :\n",
|
||||
// " -r : use RSA to verify host public key\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
nsources=argc-optind-1;
|
||||
if(nsources < 1){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
sources=malloc((nsources + 1) * sizeof(char *));
|
||||
if(sources == NULL)
|
||||
return -1;
|
||||
for(i=0;i<nsources;++i){
|
||||
sources[i] = argv[optind];
|
||||
optind++;
|
||||
}
|
||||
sources[i]=NULL;
|
||||
destination=argv[optind];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct location *parse_location(char *loc){
|
||||
struct location *location=malloc(sizeof(struct location));
|
||||
char *ptr;
|
||||
|
||||
location->host=location->user=NULL;
|
||||
ptr=strchr(loc,':');
|
||||
if(ptr != NULL){
|
||||
location->is_ssh=1;
|
||||
location->path=strdup(ptr+1);
|
||||
*ptr='\0';
|
||||
ptr=strchr(loc,'@');
|
||||
if(ptr != NULL){
|
||||
location->host=strdup(ptr+1);
|
||||
*ptr='\0';
|
||||
location->user=strdup(loc);
|
||||
} else {
|
||||
location->host=strdup(loc);
|
||||
}
|
||||
} else {
|
||||
location->is_ssh=0;
|
||||
location->path=strdup(loc);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
static int open_location(struct location *loc, int flag){
|
||||
if(loc->is_ssh && flag==WRITE){
|
||||
loc->session=connect_ssh(loc->host,loc->user,verbosity);
|
||||
if(!loc->session){
|
||||
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
|
||||
return -1;
|
||||
}
|
||||
loc->scp=ssh_scp_new(loc->session,SSH_SCP_WRITE,loc->path);
|
||||
if(!loc->scp){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
return -1;
|
||||
}
|
||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else if(loc->is_ssh && flag==READ){
|
||||
loc->session=connect_ssh(loc->host, loc->user,verbosity);
|
||||
if(!loc->session){
|
||||
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
|
||||
return -1;
|
||||
}
|
||||
loc->scp=ssh_scp_new(loc->session,SSH_SCP_READ,loc->path);
|
||||
if(!loc->scp){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
return -1;
|
||||
}
|
||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
loc->file=fopen(loc->path,flag==READ ? "r":"w");
|
||||
if(!loc->file){
|
||||
if(errno==EISDIR){
|
||||
if(chdir(loc->path)){
|
||||
fprintf(stderr,"Error changing directory to %s: %s\n",loc->path,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr,"Error opening %s: %s\n",loc->path,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** @brief copies files from source location to destination
|
||||
* @param src source location
|
||||
* @param dest destination location
|
||||
* @param recursive Copy also directories
|
||||
*/
|
||||
static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
int size;
|
||||
socket_t fd;
|
||||
struct stat s;
|
||||
int w,r;
|
||||
char buffer[16384];
|
||||
int total=0;
|
||||
int mode;
|
||||
char *filename;
|
||||
/* recursive mode doesn't work yet */
|
||||
(void)recursive;
|
||||
/* Get the file name and size*/
|
||||
if(!src->is_ssh){
|
||||
fd=fileno(src->file);
|
||||
fstat(fd,&s);
|
||||
size=s.st_size;
|
||||
mode = s.st_mode & ~S_IFMT;
|
||||
filename=ssh_basename(src->path);
|
||||
} else {
|
||||
size=0;
|
||||
do {
|
||||
r=ssh_scp_pull_request(src->scp);
|
||||
if(r==SSH_SCP_REQUEST_NEWDIR){
|
||||
ssh_scp_deny_request(src->scp,"Not in recursive mode");
|
||||
continue;
|
||||
}
|
||||
if(r==SSH_SCP_REQUEST_NEWFILE){
|
||||
size=ssh_scp_request_get_size(src->scp);
|
||||
filename=strdup(ssh_scp_request_get_filename(src->scp));
|
||||
mode=ssh_scp_request_get_permissions(src->scp);
|
||||
//ssh_scp_accept_request(src->scp);
|
||||
break;
|
||||
}
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
|
||||
return -1;
|
||||
}
|
||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||
}
|
||||
|
||||
if(dest->is_ssh){
|
||||
r=ssh_scp_push_file(dest->scp,src->path, size, mode);
|
||||
// snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if(!dest->file){
|
||||
dest->file=fopen(filename,"w");
|
||||
if(!dest->file){
|
||||
fprintf(stderr,"Cannot open %s for writing: %s\n",filename,strerror(errno));
|
||||
if(src->is_ssh)
|
||||
ssh_scp_deny_request(src->scp,"Cannot open local file");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(src->is_ssh){
|
||||
ssh_scp_accept_request(src->scp);
|
||||
}
|
||||
}
|
||||
do {
|
||||
if(src->is_ssh){
|
||||
r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
|
||||
return -1;
|
||||
}
|
||||
if(r==0)
|
||||
break;
|
||||
} else {
|
||||
r=fread(buffer,1,sizeof(buffer),src->file);
|
||||
if(r==0)
|
||||
break;
|
||||
if(r<0){
|
||||
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(dest->is_ssh){
|
||||
w=ssh_scp_write(dest->scp,buffer,r);
|
||||
if(w == SSH_ERROR){
|
||||
fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp=NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
w=fwrite(buffer,r,1,dest->file);
|
||||
if(w<=0){
|
||||
fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
total+=r;
|
||||
|
||||
} while(total < size);
|
||||
printf("wrote %d bytes\n",total);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
struct location *dest, *src;
|
||||
int i;
|
||||
int r;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
dest=parse_location(destination);
|
||||
if(open_location(dest,WRITE)<0)
|
||||
return EXIT_FAILURE;
|
||||
for(i=0;i<nsources;++i){
|
||||
src=parse_location(sources[i]);
|
||||
if(open_location(src,READ)<0){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(do_copy(src,dest,0) < 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dest->is_ssh){
|
||||
r=ssh_scp_close(dest->scp);
|
||||
if(r == SSH_ERROR){
|
||||
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp=NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fclose(dest->file);
|
||||
dest->file=NULL;
|
||||
}
|
||||
ssh_disconnect(dest->session);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
@@ -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.userauthAutopubkey();
|
||||
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.userauthAutopubkey();
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
std::cout << "Error during connection : ";
|
||||
std::cout << session.getError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
@@ -1,538 +0,0 @@
|
||||
/* client.c */
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef HAVE_PTY_H
|
||||
#include <pty.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "examples_common.h"
|
||||
#define MAXCMD 10
|
||||
char *host;
|
||||
char *user;
|
||||
char *cmds[MAXCMD];
|
||||
struct termios terminal;
|
||||
|
||||
char *pcap_file=NULL;
|
||||
|
||||
char *proxycommand;
|
||||
|
||||
static int auth_callback(const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata) {
|
||||
char *answer = NULL;
|
||||
char *ptr;
|
||||
|
||||
(void) verify;
|
||||
(void) userdata;
|
||||
|
||||
if (echo) {
|
||||
while ((answer = fgets(buf, len, stdin)) == NULL);
|
||||
if ((ptr = strchr(buf, '\n'))) {
|
||||
*ptr = '\0';
|
||||
}
|
||||
} else {
|
||||
if (ssh_getpass(prompt, buf, len, 0, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (answer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(buf, answer, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ssh_callbacks_struct cb = {
|
||||
.auth_function=auth_callback,
|
||||
.userdata=NULL
|
||||
};
|
||||
|
||||
static void add_cmd(char *cmd){
|
||||
int n;
|
||||
for(n=0;cmds[n] && (n<MAXCMD);n++);
|
||||
if(n==MAXCMD)
|
||||
return;
|
||||
cmds[n]=strdup(cmd);
|
||||
}
|
||||
|
||||
static void usage(){
|
||||
fprintf(stderr,"Usage : ssh [options] [login@]hostname\n"
|
||||
"sample client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -l user : log in as user\n"
|
||||
" -p port : connect to port\n"
|
||||
" -d : use DSS to verify host public key\n"
|
||||
" -r : use RSA to verify host public key\n"
|
||||
#ifdef WITH_PCAP
|
||||
" -P file : create a pcap debugging file\n"
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
" -T proxycommand : command to execute as a socket proxy\n"
|
||||
#endif
|
||||
,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
// for(i=0;i<argc;i++)
|
||||
// printf("%d : %s\n",i,argv[i]);
|
||||
/* insert your own arguments here */
|
||||
while((i=getopt(argc,argv,"T:P:"))!=-1){
|
||||
switch(i){
|
||||
case 'P':
|
||||
pcap_file=optarg;
|
||||
break;
|
||||
#ifndef _WIN32
|
||||
case 'T':
|
||||
proxycommand=optarg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if(optind < argc)
|
||||
host=argv[optind++];
|
||||
while(optind < argc)
|
||||
add_cmd(argv[optind++]);
|
||||
if(host==NULL)
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_CFMAKERAW
|
||||
static void cfmakeraw(struct termios *termios_p){
|
||||
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
||||
termios_p->c_oflag &= ~OPOST;
|
||||
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
termios_p->c_cflag &= ~(CSIZE|PARENB);
|
||||
termios_p->c_cflag |= CS8;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void do_cleanup(int i) {
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
|
||||
tcsetattr(0,TCSANOW,&terminal);
|
||||
}
|
||||
|
||||
static void do_exit(int i) {
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
|
||||
do_cleanup(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ssh_channel chan;
|
||||
int signal_delayed=0;
|
||||
|
||||
static void sigwindowchanged(int i){
|
||||
(void) i;
|
||||
signal_delayed=1;
|
||||
}
|
||||
|
||||
static void setsignal(void){
|
||||
signal(SIGWINCH, sigwindowchanged);
|
||||
signal_delayed=0;
|
||||
}
|
||||
|
||||
static void sizechanged(void){
|
||||
struct winsize win = { 0, 0, 0, 0 };
|
||||
ioctl(1, TIOCGWINSZ, &win);
|
||||
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
|
||||
// printf("Changed pty size\n");
|
||||
setsignal();
|
||||
}
|
||||
|
||||
/* There are two flavors of select loop: the one based on
|
||||
* ssh_select and the one based on channel_select.
|
||||
* The ssh_select one permits you to give your own file descriptors to
|
||||
* follow. It is thus a complete select loop.
|
||||
* The second one only selects on channels. It is simplier to use
|
||||
* but doesn't permit you to fill in your own file descriptor. It is
|
||||
* more adapted if you can't use ssh_select as a main loop (because
|
||||
* you already have another main loop system).
|
||||
*/
|
||||
|
||||
#ifdef USE_CHANNEL_SELECT
|
||||
|
||||
/* channel_select base main loop, with a standard select(2)
|
||||
*/
|
||||
static void select_loop(ssh_session session,ssh_channel channel){
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[4096];
|
||||
ssh_buffer readbuf=ssh_buffer_new();
|
||||
ssh_channel channels[2];
|
||||
int lus;
|
||||
int eof=0;
|
||||
int maxfd;
|
||||
int ret;
|
||||
while(channel){
|
||||
/* when a signal is caught, ssh_select will return
|
||||
* with SSH_EINTR, which means it should be started
|
||||
* again. It lets you handle the signal the faster you
|
||||
* can, like in this window changed example. Of course, if
|
||||
* your signal handler doesn't call libssh at all, you're
|
||||
* free to handle signals directly in sighandler.
|
||||
*/
|
||||
do{
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
timeout.tv_usec=0;
|
||||
FD_SET(ssh_get_fd(session),&fds);
|
||||
maxfd=ssh_get_fd(session)+1;
|
||||
ret=select(maxfd,&fds,NULL,NULL,&timeout);
|
||||
if(ret==EINTR)
|
||||
continue;
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(FD_ISSET(ssh_get_fd(session),&fds)){
|
||||
ssh_set_fd_toread(session);
|
||||
}
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
|
||||
if(signal_delayed)
|
||||
sizechanged();
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
// we already looked for input from stdin. Now, we are looking for input from the channel
|
||||
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(channels[0]){
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)>0){
|
||||
lus=channel_read_buffer(channel,readbuf,0,0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(1,ssh_buffer_get_begin(readbuf),lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)>0){ /* stderr */
|
||||
lus=channel_read_buffer(channel,readbuf,0,1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(2,ssh_buffer_get_begin(readbuf),lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
}
|
||||
ssh_buffer_free(readbuf);
|
||||
}
|
||||
#else /* CHANNEL_SELECT */
|
||||
|
||||
static void select_loop(ssh_session session,ssh_channel channel){
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[4096];
|
||||
/* channels will be set to the channels to poll.
|
||||
* outchannels will contain the result of the poll
|
||||
*/
|
||||
ssh_channel channels[2], outchannels[2];
|
||||
int lus;
|
||||
int eof=0;
|
||||
int maxfd;
|
||||
int ret;
|
||||
while(channel){
|
||||
do{
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
timeout.tv_usec=0;
|
||||
FD_SET(ssh_get_fd(session),&fds);
|
||||
maxfd=ssh_get_fd(session)+1;
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||
if(signal_delayed)
|
||||
sizechanged();
|
||||
if(ret==EINTR)
|
||||
continue;
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(outchannels[0]){
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)!=0){
|
||||
lus=ssh_channel_read(channel,buffer,sizeof(buffer),0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(1,buffer,lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)!=0){ /* stderr */
|
||||
lus=ssh_channel_read(channel,buffer,sizeof(buffer),1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(2,buffer,lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void shell(ssh_session session){
|
||||
ssh_channel channel;
|
||||
struct termios terminal_local;
|
||||
int interactive=isatty(0);
|
||||
channel = ssh_channel_new(session);
|
||||
if(interactive){
|
||||
tcgetattr(0,&terminal_local);
|
||||
memcpy(&terminal,&terminal_local,sizeof(struct termios));
|
||||
}
|
||||
if(ssh_channel_open_session(channel)){
|
||||
printf("error opening channel : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
chan=channel;
|
||||
if(interactive){
|
||||
ssh_channel_request_pty(channel);
|
||||
sizechanged();
|
||||
}
|
||||
if(ssh_channel_request_shell(channel)){
|
||||
printf("Requesting shell : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(interactive){
|
||||
cfmakeraw(&terminal_local);
|
||||
tcsetattr(0,TCSANOW,&terminal_local);
|
||||
setsignal();
|
||||
}
|
||||
signal(SIGTERM,do_cleanup);
|
||||
select_loop(session,channel);
|
||||
if(interactive)
|
||||
do_cleanup(0);
|
||||
}
|
||||
|
||||
static void batch_shell(ssh_session session){
|
||||
ssh_channel channel;
|
||||
char buffer[1024];
|
||||
int i,s=0;
|
||||
for(i=0;i<MAXCMD && cmds[i];++i) {
|
||||
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
|
||||
free(cmds[i]);
|
||||
cmds[i] = NULL;
|
||||
}
|
||||
channel=ssh_channel_new(session);
|
||||
ssh_channel_open_session(channel);
|
||||
if(ssh_channel_request_exec(channel,buffer)){
|
||||
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
select_loop(session,channel);
|
||||
}
|
||||
|
||||
static int client(ssh_session session){
|
||||
int auth=0;
|
||||
char *banner;
|
||||
int state;
|
||||
if (user)
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0)
|
||||
return -1;
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
|
||||
return -1;
|
||||
if (proxycommand != NULL){
|
||||
if(ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand))
|
||||
return -1;
|
||||
}
|
||||
ssh_options_parse_config(session, NULL);
|
||||
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
state=verify_knownhost(session);
|
||||
if (state != 0)
|
||||
return -1;
|
||||
ssh_userauth_none(session, NULL);
|
||||
banner=ssh_get_issue_banner(session);
|
||||
if(banner){
|
||||
printf("%s\n",banner);
|
||||
free(banner);
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
if(auth != SSH_AUTH_SUCCESS){
|
||||
return -1;
|
||||
}
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
|
||||
if(!cmds[0])
|
||||
shell(session);
|
||||
else
|
||||
batch_shell(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssh_pcap_file pcap;
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(!pcap)
|
||||
return;
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
if(pcap)
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
|
||||
session = ssh_new();
|
||||
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_callbacks(session,&cb);
|
||||
|
||||
if(ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr, "error parsing command line :%s\n",
|
||||
ssh_get_error(session));
|
||||
usage();
|
||||
}
|
||||
opts(argc,argv);
|
||||
signal(SIGTERM, do_exit);
|
||||
|
||||
set_pcap(session);
|
||||
client(session);
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
cleanup_pcap();
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
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 <sys/statvfs.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
|
||||
#include "examples_common.h"
|
||||
#ifdef WITH_SFTP
|
||||
|
||||
int verbosity;
|
||||
char *destination;
|
||||
#define DATALEN 65536
|
||||
static void do_sftp(ssh_session session){
|
||||
sftp_session sftp=sftp_new(session);
|
||||
sftp_dir dir;
|
||||
sftp_attributes file;
|
||||
sftp_statvfs_t sftpstatvfs;
|
||||
struct statvfs sysstatvfs;
|
||||
sftp_file fichier;
|
||||
sftp_file to;
|
||||
int len=1;
|
||||
unsigned int i;
|
||||
char data[DATALEN]={0};
|
||||
char *lnk;
|
||||
|
||||
unsigned int count;
|
||||
|
||||
if(!sftp){
|
||||
fprintf(stderr, "sftp error initialising channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(sftp_init(sftp)){
|
||||
fprintf(stderr, "error initialising sftp: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Additional SFTP extensions provided by the server:\n");
|
||||
count = sftp_extensions_get_count(sftp);
|
||||
for (i = 0; i < count; i++) {
|
||||
printf("\t%s, version: %s\n",
|
||||
sftp_extensions_get_name(sftp, i),
|
||||
sftp_extensions_get_data(sftp, i));
|
||||
}
|
||||
|
||||
/* test symlink and readlink */
|
||||
if (sftp_symlink(sftp, "/tmp/this_is_the_link",
|
||||
"/tmp/sftp_symlink_test") < 0) {
|
||||
fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
||||
if (lnk == NULL) {
|
||||
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
|
||||
|
||||
sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
||||
|
||||
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
|
||||
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
||||
if (sftpstatvfs == NULL) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
printf("sftp statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sftpstatvfs->f_bsize,
|
||||
(unsigned long long) sftpstatvfs->f_frsize,
|
||||
(unsigned long long) sftpstatvfs->f_blocks,
|
||||
(unsigned long long) sftpstatvfs->f_bfree,
|
||||
(unsigned long long) sftpstatvfs->f_bavail,
|
||||
(unsigned long long) sftpstatvfs->f_files,
|
||||
(unsigned long long) sftpstatvfs->f_ffree,
|
||||
(unsigned long long) sftpstatvfs->f_favail,
|
||||
(unsigned long long) sftpstatvfs->f_fsid,
|
||||
(unsigned long long) sftpstatvfs->f_flag,
|
||||
(unsigned long long) sftpstatvfs->f_namemax);
|
||||
|
||||
sftp_statvfs_free(sftpstatvfs);
|
||||
|
||||
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
printf("sys statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sysstatvfs.f_bsize,
|
||||
(unsigned long long) sysstatvfs.f_frsize,
|
||||
(unsigned long long) sysstatvfs.f_blocks,
|
||||
(unsigned long long) sysstatvfs.f_bfree,
|
||||
(unsigned long long) sysstatvfs.f_bavail,
|
||||
(unsigned long long) sysstatvfs.f_files,
|
||||
(unsigned long long) sysstatvfs.f_ffree,
|
||||
(unsigned long long) sysstatvfs.f_favail,
|
||||
(unsigned long long) sysstatvfs.f_fsid,
|
||||
(unsigned long long) sysstatvfs.f_flag,
|
||||
(unsigned long long) sysstatvfs.f_namemax);
|
||||
}
|
||||
|
||||
/* the connection is made */
|
||||
/* opening a directory */
|
||||
dir=sftp_opendir(sftp,"./");
|
||||
if(!dir) {
|
||||
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
|
||||
return ;
|
||||
}
|
||||
/* reading the whole directory, file by file */
|
||||
while((file=sftp_readdir(sftp,dir))){
|
||||
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
|
||||
file->name,
|
||||
file->permissions,
|
||||
file->owner,
|
||||
file->uid,
|
||||
file->group,
|
||||
file->gid,
|
||||
(long long unsigned int) file->size);
|
||||
sftp_attributes_free(file);
|
||||
}
|
||||
/* when file=NULL, an error has occured OR the directory listing is end of file */
|
||||
if(!sftp_dir_eof(dir)){
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(sftp_closedir(dir)){
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
/* this will open a file and copy it into your /home directory */
|
||||
/* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */
|
||||
|
||||
fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0);
|
||||
if(!fichier){
|
||||
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
/* open a file for writing... */
|
||||
to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700);
|
||||
if(!to){
|
||||
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
while((len=sftp_read(fichier,data,4096)) > 0){
|
||||
if(sftp_write(to,data,len)!=len){
|
||||
fprintf(stderr, "Error writing %d bytes: %s\n",
|
||||
len, ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("finished\n");
|
||||
if(len<0)
|
||||
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
|
||||
sftp_close(fichier);
|
||||
sftp_close(to);
|
||||
printf("fichiers ferm\n");
|
||||
to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
|
||||
for(i=0;i<1000;++i){
|
||||
len=sftp_write(to,data,DATALEN);
|
||||
printf("wrote %d bytes\n",len);
|
||||
if(len != DATALEN){
|
||||
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
|
||||
}
|
||||
}
|
||||
sftp_close(to);
|
||||
|
||||
/* close the sftp session */
|
||||
sftp_free(sftp);
|
||||
printf("sftp session terminated\n");
|
||||
}
|
||||
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [-v] remotehost\n"
|
||||
"sample sftp test client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -v : increase log verbosity\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
destination=argv[optind];
|
||||
if(destination == NULL){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
session=connect_ssh(destination,NULL,verbosity);
|
||||
if(session == NULL)
|
||||
return EXIT_FAILURE;
|
||||
do_sftp(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,308 +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>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
const char *pcap_file="debug.server.pcap";
|
||||
ssh_pcap_file pcap;
|
||||
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int auth_password(char *user, char *password){
|
||||
if(strcmp(user,"aris"))
|
||||
return 0;
|
||||
if(strcmp(password,"lala"))
|
||||
return 0;
|
||||
return 1; // authenticated
|
||||
}
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh server example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_message message;
|
||||
ssh_channel chan=0;
|
||||
char buf[2048];
|
||||
int auth=0;
|
||||
int sftp=0;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
#ifdef WITH_PCAP
|
||||
set_pcap(session);
|
||||
#endif
|
||||
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
r=ssh_bind_accept(sshbind,session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(!message)
|
||||
break;
|
||||
switch(ssh_message_type(message)){
|
||||
case SSH_REQUEST_AUTH:
|
||||
switch(ssh_message_subtype(message)){
|
||||
case SSH_AUTH_METHOD_PASSWORD:
|
||||
printf("User %s wants to auth with pass %s\n",
|
||||
ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message));
|
||||
if(auth_password(ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message))){
|
||||
auth=1;
|
||||
ssh_message_auth_reply_success(message,0);
|
||||
break;
|
||||
}
|
||||
// not authenticated, send default message
|
||||
case SSH_AUTH_METHOD_NONE:
|
||||
default:
|
||||
ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD);
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while (!auth);
|
||||
if(!auth){
|
||||
printf("auth error: %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(message){
|
||||
switch(ssh_message_type(message)){
|
||||
case SSH_REQUEST_CHANNEL_OPEN:
|
||||
if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){
|
||||
chan=ssh_message_channel_request_open_reply_accept(message);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
}
|
||||
} while(message && !chan);
|
||||
if(!chan){
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL &&
|
||||
ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){
|
||||
// if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){
|
||||
sftp=1;
|
||||
ssh_message_channel_request_reply_success(message);
|
||||
break;
|
||||
// }
|
||||
}
|
||||
if(!sftp){
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while (message && !sftp);
|
||||
if(!sftp){
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
printf("it works !\n");
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, 2048, 0);
|
||||
if(i>0) {
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if (write(1,buf,i) < 0) {
|
||||
printf("error writing to buffer\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (i>0);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
#ifdef WITH_PCAP
|
||||
cleanup_pcap();
|
||||
#endif
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/* scp_download.c
|
||||
* Sample implementation of a tiny SCP downloader client
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
int verbosity=0;
|
||||
const char *createcommand="rm -fr /tmp/libssh_tests && mkdir /tmp/libssh_tests && cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
|
||||
char *host=NULL;
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [options] host\n"
|
||||
"sample tiny scp downloader client - libssh-%s\n"
|
||||
"This program will create files in /tmp and try to fetch them\n",
|
||||
// "Options :\n",
|
||||
// " -r : use RSA to verify host public key\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
host = argv[optind];
|
||||
if(host == NULL)
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create_files(ssh_session session){
|
||||
ssh_channel channel=ssh_channel_new(session);
|
||||
char buffer[1];
|
||||
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){
|
||||
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){
|
||||
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)){
|
||||
ssh_channel_read(channel,buffer,1,1);
|
||||
if (write(1,buffer,1) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
|
||||
static int fetch_files(ssh_session session){
|
||||
int size;
|
||||
char buffer[16384];
|
||||
int mode;
|
||||
char *filename;
|
||||
int r;
|
||||
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");
|
||||
do {
|
||||
|
||||
r=ssh_scp_pull_request(scp);
|
||||
switch(r){
|
||||
case SSH_SCP_REQUEST_NEWFILE:
|
||||
size=ssh_scp_request_get_size(scp);
|
||||
filename=strdup(ssh_scp_request_get_filename(scp));
|
||||
mode=ssh_scp_request_get_permissions(scp);
|
||||
printf("downloading file %s, size %d, perms 0%o\n",filename,size,mode);
|
||||
free(filename);
|
||||
ssh_scp_accept_request(scp);
|
||||
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));
|
||||
break;
|
||||
case SSH_SCP_REQUEST_NEWDIR:
|
||||
filename=strdup(ssh_scp_request_get_filename(scp));
|
||||
mode=ssh_scp_request_get_permissions(scp);
|
||||
printf("downloading directory %s, perms 0%o\n",filename,mode);
|
||||
free(filename);
|
||||
ssh_scp_accept_request(scp);
|
||||
break;
|
||||
case SSH_SCP_REQUEST_ENDDIR:
|
||||
printf("End of directory\n");
|
||||
break;
|
||||
case SSH_SCP_REQUEST_EOF:
|
||||
printf("End of requests\n");
|
||||
goto end;
|
||||
}
|
||||
} while (1);
|
||||
end:
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
session=connect_ssh(host,NULL,verbosity);
|
||||
if(session == NULL)
|
||||
return EXIT_FAILURE;
|
||||
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,258 +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 <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#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{
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
timeout.tv_usec=0;
|
||||
FD_SET(ssh_get_fd(session),&fds);
|
||||
maxfd=ssh_get_fd(session)+1;
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||
if(ret==EINTR)
|
||||
continue;
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
channel_send_eof(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 && 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_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 {
|
||||
ret = write(1, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to stdin: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
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_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
|
||||
ret = write(2, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to stderr: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && channel_is_closed(channel)){
|
||||
channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void forwarding(ssh_session session){
|
||||
ssh_channel channel;
|
||||
int r;
|
||||
channel=channel_new(session);
|
||||
r=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;
|
||||
}
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
|
||||
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,10 +1,9 @@
|
||||
project(libssh-headers C)
|
||||
|
||||
set(libssh_HDRS
|
||||
callbacks.h
|
||||
libssh.h
|
||||
crypto.h
|
||||
ssh2.h
|
||||
legacy.h
|
||||
)
|
||||
|
||||
if (WITH_SFTP)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#ifndef __AGENT_H
|
||||
#define __AGENT_H
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
|
||||
/* Messages for the authentication agent connection. */
|
||||
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
||||
@@ -47,51 +45,5 @@
|
||||
|
||||
#define SSH_AGENT_OLD_SIGNATURE 0x01
|
||||
|
||||
struct ssh_agent_struct {
|
||||
struct ssh_socket_struct *sock;
|
||||
ssh_buffer ident;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
/* agent.c */
|
||||
/**
|
||||
* @brief Create a new ssh agent structure.
|
||||
*
|
||||
* @return An allocated ssh agent structure or NULL on error.
|
||||
*/
|
||||
struct ssh_agent_struct *agent_new(struct ssh_session_struct *session);
|
||||
|
||||
void agent_close(struct ssh_agent_struct *agent);
|
||||
|
||||
/**
|
||||
* @brief Free an allocated ssh agent structure.
|
||||
*
|
||||
* @param agent The ssh agent structure to free.
|
||||
*/
|
||||
void agent_free(struct ssh_agent_struct *agent);
|
||||
|
||||
/**
|
||||
* @brief Check if the ssh agent is running.
|
||||
*
|
||||
* @param session The ssh session to check for the agent.
|
||||
*
|
||||
* @return 1 if it is running, 0 if not.
|
||||
*/
|
||||
int agent_is_running(struct ssh_session_struct *session);
|
||||
|
||||
int agent_get_ident_count(struct ssh_session_struct *session);
|
||||
|
||||
struct ssh_public_key_struct *agent_get_next_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 agent_sign_data(struct ssh_session_struct *session,
|
||||
struct ssh_buffer_struct *data,
|
||||
struct ssh_public_key_struct *pubkey);
|
||||
#endif
|
||||
|
||||
#endif /* __AGENT_H */
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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 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);
|
||||
|
||||
#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
|
||||
|
||||
};
|
||||
|
||||
/** @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,53 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 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 BIND_H_
|
||||
#define BIND_H_
|
||||
|
||||
#include "libssh/priv.h"
|
||||
|
||||
struct ssh_bind_struct {
|
||||
struct error_struct error;
|
||||
|
||||
ssh_callbacks callbacks; /* Callbacks to user functions */
|
||||
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 *dsakey;
|
||||
char *rsakey;
|
||||
char *bindaddr;
|
||||
socket_t bindfd;
|
||||
unsigned int bindport;
|
||||
unsigned int log_verbosity;
|
||||
|
||||
int blocking;
|
||||
int toaccept;
|
||||
};
|
||||
|
||||
struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct
|
||||
*sshbind);
|
||||
|
||||
|
||||
#endif /* BIND_H_ */
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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 BUFFER_H_
|
||||
#define BUFFER_H_
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
/*
|
||||
* Describes a buffer state
|
||||
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
|
||||
* ^ ^ ^ ^]
|
||||
* \_data points\_pos points here \_used points here | /
|
||||
* here Allocated
|
||||
*/
|
||||
struct ssh_buffer_struct {
|
||||
char *data;
|
||||
uint32_t used;
|
||||
uint32_t allocated;
|
||||
uint32_t pos;
|
||||
};
|
||||
|
||||
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);
|
||||
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 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 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);
|
||||
/* buffer_get_rest_len returns the number of bytes which can be read */
|
||||
uint32_t buffer_get_rest_len(ssh_buffer buffer);
|
||||
|
||||
/* buffer_read_*() returns the number of bytes read, except for ssh strings */
|
||||
int buffer_get_u8(ssh_buffer buffer, uint8_t *data);
|
||||
int buffer_get_u32(ssh_buffer buffer, uint32_t *data);
|
||||
int buffer_get_u64(ssh_buffer buffer, uint64_t *data);
|
||||
|
||||
uint32_t buffer_get_data(ssh_buffer buffer, void *data, uint32_t requestedlen);
|
||||
/* buffer_get_ssh_string() is an exception. if the String read is too large or invalid, it will answer NULL. */
|
||||
ssh_string buffer_get_ssh_string(ssh_buffer buffer);
|
||||
/* gets a string out of a SSH-1 mpint */
|
||||
ssh_string buffer_get_mpint(ssh_buffer buffer);
|
||||
/* buffer_pass_bytes acts as if len bytes have been read (used for padding) */
|
||||
uint32_t buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len);
|
||||
uint32_t buffer_pass_bytes(ssh_buffer buffer, uint32_t len);
|
||||
|
||||
#endif /* BUFFER_H_ */
|
||||
@@ -1,463 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 Aris Adamantiadis <aris@0xbadc0de.be>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* callback.h
|
||||
* This file includes the public declarations for the libssh callback mechanism
|
||||
*/
|
||||
|
||||
#ifndef _SSH_CALLBACK_H
|
||||
#define _SSH_CALLBACK_H
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup libssh_callbacks The libssh callbacks
|
||||
* @ingroup libssh
|
||||
*
|
||||
* Callback which can be replaced in libssh.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @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 authentication callback.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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);
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
typedef void (*ssh_log_callback) (ssh_session session, int priority,
|
||||
const char *message, 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.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
typedef struct ssh_callbacks_struct *ssh_callbacks;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
};
|
||||
typedef struct ssh_socket_callbacks_struct *ssh_socket_callbacks;
|
||||
|
||||
#define SSH_SOCKET_FLOW_WRITEWILLBLOCK 1
|
||||
#define SSH_SOCKET_FLOW_WRITEWONTBLOCK 2
|
||||
|
||||
#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
|
||||
* 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
|
||||
* evolves with time.
|
||||
*/
|
||||
#define ssh_callbacks_init(p) do {\
|
||||
(p)->size=sizeof(*(p)); \
|
||||
} 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.
|
||||
*
|
||||
* 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
|
||||
* };
|
||||
* 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.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR 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.
|
||||
*/
|
||||
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);
|
||||
|
||||
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;
|
||||
};
|
||||
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 sets the thread callbacks 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() for instance), before
|
||||
* ssh_init().
|
||||
* @param cb pointer to a ssh_threads_callbacks_struct structure, which contains
|
||||
* the different callbacks to be set.
|
||||
* @see ssh_threads_callbacks_struct
|
||||
* @see SSH_THREADS_PTHREAD
|
||||
*/
|
||||
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 returns a pointer on the noop threads callbacks, to be used with
|
||||
* ssh_threads_set_callbacks. These callbacks do nothing and are being used by
|
||||
* default.
|
||||
* @see ssh_threads_set_callbacks
|
||||
*/
|
||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_SSH_CALLBACK_H */
|
||||
|
||||
/* @} */
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* 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 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_OPEN_DENIED,
|
||||
SSH_CHANNEL_STATE_OPEN,
|
||||
SSH_CHANNEL_STATE_CLOSED
|
||||
};
|
||||
|
||||
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;
|
||||
int local_eof;
|
||||
uint32_t local_maxpacket;
|
||||
|
||||
uint32_t remote_channel;
|
||||
uint32_t remote_window;
|
||||
int remote_eof; /* end of file received */
|
||||
uint32_t remote_maxpacket;
|
||||
enum ssh_channel_state_e state;
|
||||
int delayed_close;
|
||||
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;
|
||||
};
|
||||
|
||||
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);
|
||||
int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
int is_stderr);
|
||||
uint32_t ssh_channel_new_id(ssh_session session);
|
||||
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
|
||||
int channel_write_common(ssh_channel channel, const void *data,
|
||||
uint32_t len, int is_stderr);
|
||||
#ifdef WITH_SSH1
|
||||
SSH_PACKET_CALLBACK(ssh_packet_data1);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_close1);
|
||||
|
||||
/* 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);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CHANNELS_H_ */
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003,2009 by Aris Adamantiadis
|
||||
* Copyright (c) 2003 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
|
||||
@@ -20,19 +20,11 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* crypto.h is an include file for internal cryptographic structures of libssh
|
||||
* crypto.h is an include file for internal structures of libssh
|
||||
* It hasn't to be into the final development set of files (and btw
|
||||
* the filename would cause problems on most systems).
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_H_
|
||||
#define _CRYPTO_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#include <gcrypt.h>
|
||||
#endif
|
||||
#include "libssh/wrapper.h"
|
||||
|
||||
#ifdef cbc_encrypt
|
||||
#undef cbc_encrypt
|
||||
#endif
|
||||
@@ -40,29 +32,9 @@
|
||||
#undef cbc_decrypt
|
||||
#endif
|
||||
|
||||
struct ssh_crypto_struct {
|
||||
bignum e,f,x,k,y;
|
||||
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 */
|
||||
};
|
||||
#ifdef GCRYPT
|
||||
#include <gcrypt.h>
|
||||
#endif
|
||||
|
||||
struct crypto_struct {
|
||||
const char *name; /* ssh name of the algorithm */
|
||||
@@ -94,4 +66,3 @@ struct crypto_struct {
|
||||
};
|
||||
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
#endif /* _CRYPTO_H_ */
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* 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 DH_H_
|
||||
#define DH_H_
|
||||
#include "config.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);
|
||||
int dh_generate_y(ssh_session session);
|
||||
|
||||
int ssh_crypto_init(void);
|
||||
void ssh_crypto_finalize(void);
|
||||
|
||||
ssh_string dh_get_e(ssh_session session);
|
||||
ssh_string dh_get_f(ssh_session session);
|
||||
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 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,33 +0,0 @@
|
||||
/*
|
||||
* 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 KEX_H_
|
||||
#define KEX_H_
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/callbacks.h"
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
|
||||
#ifdef WITH_SSH1
|
||||
SSH_PACKET_CALLBACK(ssh_packet_publickey1);
|
||||
#endif
|
||||
|
||||
#endif /* KEX_H_ */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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_ */
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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 KEYS_H_
|
||||
#define KEYS_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/wrapper.h"
|
||||
|
||||
struct ssh_public_key_struct {
|
||||
int type;
|
||||
const char *type_c; /* Don't free it ! it is static */
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa_pub;
|
||||
gcry_sexp_t rsa_pub;
|
||||
#elif HAVE_LIBCRYPTO
|
||||
DSA *dsa_pub;
|
||||
RSA *rsa_pub;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ssh_private_key_struct {
|
||||
int type;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa_priv;
|
||||
gcry_sexp_t rsa_priv;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
DSA *dsa_priv;
|
||||
RSA *rsa_priv;
|
||||
#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,100 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 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.
|
||||
*/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
|
||||
#ifndef LEGACY_H_
|
||||
#define LEGACY_H_
|
||||
LIBSSH_API void buffer_free(ssh_buffer buffer);
|
||||
LIBSSH_API void *buffer_get(ssh_buffer buffer);
|
||||
LIBSSH_API uint32_t buffer_get_len(ssh_buffer buffer);
|
||||
LIBSSH_API ssh_buffer buffer_new(void);
|
||||
|
||||
LIBSSH_API ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||
LIBSSH_API int channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||
LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms);
|
||||
LIBSSH_API int channel_close(ssh_channel channel);
|
||||
LIBSSH_API int channel_forward_cancel(ssh_session session, const char *address, int port);
|
||||
LIBSSH_API int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
||||
LIBSSH_API void channel_free(ssh_channel channel);
|
||||
LIBSSH_API int channel_get_exit_status(ssh_channel channel);
|
||||
LIBSSH_API ssh_session channel_get_session(ssh_channel channel);
|
||||
LIBSSH_API int channel_is_closed(ssh_channel channel);
|
||||
LIBSSH_API int channel_is_eof(ssh_channel channel);
|
||||
LIBSSH_API int channel_is_open(ssh_channel channel);
|
||||
LIBSSH_API ssh_channel channel_new(ssh_session session);
|
||||
LIBSSH_API int channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||
int remoteport, const char *sourcehost, int localport);
|
||||
LIBSSH_API int channel_open_session(ssh_channel channel);
|
||||
LIBSSH_API int channel_poll(ssh_channel channel, int is_stderr);
|
||||
LIBSSH_API int channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
||||
|
||||
LIBSSH_API int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
||||
int is_stderr);
|
||||
|
||||
LIBSSH_API int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr);
|
||||
LIBSSH_API int channel_request_env(ssh_channel channel, const char *name, const char *value);
|
||||
LIBSSH_API int channel_request_exec(ssh_channel channel, const char *cmd);
|
||||
LIBSSH_API int channel_request_pty(ssh_channel channel);
|
||||
LIBSSH_API int channel_request_pty_size(ssh_channel channel, const char *term,
|
||||
int cols, int rows);
|
||||
LIBSSH_API int channel_request_shell(ssh_channel channel);
|
||||
LIBSSH_API int channel_request_send_signal(ssh_channel channel, const char *signum);
|
||||
LIBSSH_API int channel_request_sftp(ssh_channel channel);
|
||||
LIBSSH_API int channel_request_subsystem(ssh_channel channel, const char *subsystem);
|
||||
LIBSSH_API int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
|
||||
const char *cookie, int screen_number);
|
||||
LIBSSH_API int channel_send_eof(ssh_channel channel);
|
||||
LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
||||
timeval * timeout);
|
||||
LIBSSH_API void channel_set_blocking(ssh_channel channel, int blocking);
|
||||
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 ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
|
||||
LIBSSH_API void string_burn(ssh_string str);
|
||||
LIBSSH_API ssh_string string_copy(ssh_string str);
|
||||
LIBSSH_API void *string_data(ssh_string str);
|
||||
LIBSSH_API int string_fill(ssh_string str, const void *data, size_t len);
|
||||
LIBSSH_API void string_free(ssh_string str);
|
||||
LIBSSH_API ssh_string string_from_char(const char *what);
|
||||
LIBSSH_API size_t string_len(ssh_string str);
|
||||
LIBSSH_API ssh_string string_new(size_t size);
|
||||
LIBSSH_API char *string_to_char(ssh_string str);
|
||||
|
||||
#endif /* LEGACY_H_ */
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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 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>
|
||||
typedef SHA_CTX* SHACTX;
|
||||
typedef MD5_CTX* MD5CTX;
|
||||
typedef HMAC_CTX* HMACCTX;
|
||||
|
||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||
#ifdef MD5_DIGEST_LEN
|
||||
#undef MD5_DIGEST_LEN
|
||||
#endif
|
||||
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
|
||||
|
||||
#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)
|
||||
|
||||
struct crypto_struct *ssh_get_ciphertab(void);
|
||||
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
#endif /* LIBCRYPTO_H_ */
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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 LIBGCRYPT_H_
|
||||
#define LIBGCRYPT_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
|
||||
#include <gcrypt.h>
|
||||
typedef gcry_md_hd_t SHACTX;
|
||||
typedef gcry_md_hd_t MD5CTX;
|
||||
typedef gcry_md_hd_t HMACCTX;
|
||||
#define SHA_DIGEST_LEN 20
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#define EVP_MAX_MD_SIZE 36
|
||||
|
||||
typedef gcry_mpi_t bignum;
|
||||
|
||||
#define bignum_new() gcry_mpi_new(0)
|
||||
#define bignum_free(num) gcry_mpi_release(num)
|
||||
#define bignum_set_word(bn,n) gcry_mpi_set_ui(bn,n)
|
||||
#define bignum_bin2bn(bn,datalen,data) gcry_mpi_scan(data,GCRYMPI_FMT_USG,bn,datalen,NULL)
|
||||
#define bignum_bn2dec(num) my_gcry_bn2dec(num)
|
||||
#define bignum_dec2bn(num, data) my_gcry_dec2bn(data, num)
|
||||
#define bignum_bn2hex(num,data) gcry_mpi_aprint(GCRYMPI_FMT_HEX,data,NULL,num)
|
||||
#define bignum_hex2bn(num,datalen,data) gcry_mpi_scan(num,GCRYMPI_FMT_HEX,data,datalen,NULL)
|
||||
#define bignum_rand(num,bits) gcry_mpi_randomize(num,bits,GCRY_STRONG_RANDOM),gcry_mpi_set_bit(num,bits-1),gcry_mpi_set_bit(num,0)
|
||||
#define bignum_mod_exp(dest,generator,exp,modulo) gcry_mpi_powm(dest,generator,exp,modulo)
|
||||
#define bignum_num_bits(num) gcry_mpi_get_nbits(num)
|
||||
#define bignum_num_bytes(num) ((gcry_mpi_get_nbits(num)+7)/8)
|
||||
#define bignum_is_bit_set(num,bit) gcry_mpi_test_bit(num,bit)
|
||||
#define bignum_bn2bin(num,datalen,data) gcry_mpi_print(GCRYMPI_FMT_USG,data,datalen,NULL,num)
|
||||
#define bignum_cmp(num1,num2) gcry_mpi_cmp(num1,num2)
|
||||
|
||||
|
||||
#endif /* HAVE_LIBGCRYPT */
|
||||
|
||||
struct crypto_struct *ssh_get_ciphertab(void);
|
||||
|
||||
#endif /* LIBGCRYPT_H_ */
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-2009 by Aris Adamantiadis
|
||||
* Copyright (c) 2003-2008 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
|
||||
@@ -22,50 +22,22 @@
|
||||
#ifndef _LIBSSH_H
|
||||
#define _LIBSSH_H
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef LIBSSH_STATIC
|
||||
#define LIBSSH_API
|
||||
#else
|
||||
#ifdef LIBSSH_EXPORTS
|
||||
#ifdef __GNUC__
|
||||
#define LIBSSH_API __attribute__((dllexport))
|
||||
#else
|
||||
#define LIBSSH_API __declspec(dllexport)
|
||||
#endif
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define LIBSSH_API __attribute__((dllimport))
|
||||
#else
|
||||
#define LIBSSH_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#if __GNUC__ >= 4 && !defined(__OS2__)
|
||||
#define LIBSSH_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define LIBSSH_API
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* Visual Studio hasn't inttypes.h so it doesn't know uint32_t */
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef int mode_t;
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#else /* _MSC_VER */
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
//visual studio hasn't inttypes.h so it doesn't know uint32_t
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#else /* _WIN32 */
|
||||
#include <sys/select.h> /* for fd_set * */
|
||||
#include <netdb.h>
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/select.h> /* for fd_set * */
|
||||
#include <netdb.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#define SSH_STRINGIFY(s) SSH_TOSTRING(s)
|
||||
@@ -78,7 +50,7 @@
|
||||
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 5
|
||||
#define LIBSSH_VERSION_MINOR 3
|
||||
#define LIBSSH_VERSION_MICRO 1
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
@@ -95,151 +67,83 @@
|
||||
#define PRINTF_ATTRIBUTE(a,b)
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define SSH_DEPRECATED __attribute__ ((deprecated))
|
||||
#else
|
||||
#define SSH_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct string_struct STRING;
|
||||
typedef struct buffer_struct BUFFER;
|
||||
typedef struct public_key_struct PUBLIC_KEY;
|
||||
typedef struct private_key_struct PRIVATE_KEY;
|
||||
typedef struct ssh_options_struct SSH_OPTIONS;
|
||||
typedef struct channel_struct CHANNEL;
|
||||
typedef struct agent_struct AGENT;
|
||||
typedef struct ssh_session SSH_SESSION;
|
||||
typedef struct ssh_kbdint SSH_KBDINT;
|
||||
|
||||
typedef struct ssh_agent_struct* ssh_agent;
|
||||
typedef struct ssh_buffer_struct* ssh_buffer;
|
||||
typedef struct ssh_channel_struct* ssh_channel;
|
||||
typedef struct ssh_message_struct* ssh_message;
|
||||
typedef struct ssh_pcap_file_struct* ssh_pcap_file;
|
||||
typedef struct ssh_private_key_struct* ssh_private_key;
|
||||
typedef struct ssh_public_key_struct* ssh_public_key;
|
||||
typedef struct ssh_key_struct* ssh_key;
|
||||
typedef struct ssh_scp_struct* ssh_scp;
|
||||
typedef struct ssh_session_struct* ssh_session;
|
||||
typedef struct ssh_string_struct* ssh_string;
|
||||
/* integer values */
|
||||
typedef uint32_t u32;
|
||||
typedef uint16_t u16;
|
||||
typedef uint64_t u64;
|
||||
typedef uint8_t u8;
|
||||
|
||||
/* Socket type */
|
||||
#ifdef _WIN32
|
||||
#ifndef socket_t
|
||||
typedef SOCKET socket_t;
|
||||
#endif /* socket_t */
|
||||
#else /* _WIN32 */
|
||||
#ifndef socket_t
|
||||
#define socket_t SOCKET
|
||||
#else
|
||||
typedef int socket_t;
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#define SSH_INVALID_SOCKET ((socket_t) -1)
|
||||
|
||||
/* the offsets of methods */
|
||||
enum ssh_kex_types_e {
|
||||
SSH_KEX=0,
|
||||
SSH_HOSTKEYS,
|
||||
SSH_CRYPT_C_S,
|
||||
SSH_CRYPT_S_C,
|
||||
SSH_MAC_C_S,
|
||||
SSH_MAC_S_C,
|
||||
SSH_COMP_C_S,
|
||||
SSH_COMP_S_C,
|
||||
SSH_LANG_C_S,
|
||||
SSH_LANG_S_C
|
||||
};
|
||||
#define SSH_KEX 0
|
||||
#define SSH_HOSTKEYS 1
|
||||
#define SSH_CRYPT_C_S 2
|
||||
#define SSH_CRYPT_S_C 3
|
||||
#define SSH_MAC_C_S 4
|
||||
#define SSH_MAC_S_C 5
|
||||
#define SSH_COMP_C_S 6
|
||||
#define SSH_COMP_S_C 7
|
||||
#define SSH_LANG_C_S 8
|
||||
#define SSH_LANG_S_C 9
|
||||
|
||||
#define SSH_CRYPT 2
|
||||
#define SSH_MAC 3
|
||||
#define SSH_COMP 4
|
||||
#define SSH_LANG 5
|
||||
|
||||
enum ssh_auth_e {
|
||||
SSH_AUTH_SUCCESS=0,
|
||||
SSH_AUTH_DENIED,
|
||||
SSH_AUTH_PARTIAL,
|
||||
SSH_AUTH_INFO,
|
||||
SSH_AUTH_AGAIN,
|
||||
SSH_AUTH_ERROR=-1
|
||||
};
|
||||
#define SSH_AUTH_SUCCESS 0
|
||||
#define SSH_AUTH_DENIED 1
|
||||
#define SSH_AUTH_PARTIAL 2
|
||||
#define SSH_AUTH_INFO 3
|
||||
#define SSH_AUTH_ERROR -1
|
||||
|
||||
/* auth flags */
|
||||
#define SSH_AUTH_METHOD_UNKNOWN 0
|
||||
#define SSH_AUTH_METHOD_NONE 0x0001
|
||||
#define SSH_AUTH_METHOD_PASSWORD 0x0002
|
||||
#define SSH_AUTH_METHOD_PUBLICKEY 0x0004
|
||||
#define SSH_AUTH_METHOD_HOSTBASED 0x0008
|
||||
#define SSH_AUTH_METHOD_INTERACTIVE 0x0010
|
||||
|
||||
/* messages */
|
||||
enum ssh_requests_e {
|
||||
SSH_REQUEST_AUTH=1,
|
||||
SSH_REQUEST_CHANNEL_OPEN,
|
||||
SSH_REQUEST_CHANNEL,
|
||||
SSH_REQUEST_SERVICE,
|
||||
SSH_REQUEST_GLOBAL
|
||||
};
|
||||
|
||||
enum ssh_channel_type_e {
|
||||
SSH_CHANNEL_UNKNOWN=0,
|
||||
SSH_CHANNEL_SESSION,
|
||||
SSH_CHANNEL_DIRECT_TCPIP,
|
||||
SSH_CHANNEL_FORWARDED_TCPIP,
|
||||
SSH_CHANNEL_X11
|
||||
};
|
||||
|
||||
enum ssh_channel_requests_e {
|
||||
SSH_CHANNEL_REQUEST_UNKNOWN=0,
|
||||
SSH_CHANNEL_REQUEST_PTY,
|
||||
SSH_CHANNEL_REQUEST_EXEC,
|
||||
SSH_CHANNEL_REQUEST_SHELL,
|
||||
SSH_CHANNEL_REQUEST_ENV,
|
||||
SSH_CHANNEL_REQUEST_SUBSYSTEM,
|
||||
SSH_CHANNEL_REQUEST_WINDOW_CHANGE
|
||||
};
|
||||
|
||||
enum ssh_global_requests_e {
|
||||
SSH_GLOBAL_REQUEST_UNKNOWN=0,
|
||||
SSH_GLOBAL_REQUEST_TCPIP_FORWARD,
|
||||
SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD,
|
||||
};
|
||||
|
||||
enum ssh_publickey_state_e {
|
||||
SSH_PUBLICKEY_STATE_ERROR=-1,
|
||||
SSH_PUBLICKEY_STATE_NONE=0,
|
||||
SSH_PUBLICKEY_STATE_VALID=1,
|
||||
SSH_PUBLICKEY_STATE_WRONG=2
|
||||
};
|
||||
#define SSH_AUTH_METHOD_PASSWORD 0x0001
|
||||
#define SSH_AUTH_METHOD_PUBLICKEY 0x0002
|
||||
#define SSH_AUTH_METHOD_HOSTBASED 0x0004
|
||||
#define SSH_AUTH_METHOD_INTERACTIVE 0x0008
|
||||
|
||||
/* status flags */
|
||||
#define SSH_CLOSED 0x01
|
||||
#define SSH_READ_PENDING 0x02
|
||||
#define SSH_CLOSED_ERROR 0x04
|
||||
|
||||
enum ssh_server_known_e {
|
||||
SSH_SERVER_ERROR=-1,
|
||||
SSH_SERVER_NOT_KNOWN=0,
|
||||
SSH_SERVER_KNOWN_OK,
|
||||
SSH_SERVER_KNOWN_CHANGED,
|
||||
SSH_SERVER_FOUND_OTHER,
|
||||
SSH_SERVER_FILE_NOT_FOUND
|
||||
};
|
||||
#define SSH_CLOSED (1<<0)
|
||||
#define SSH_READ_PENDING (1<<1)
|
||||
#define SSH_CLOSED_ERROR (1<<2)
|
||||
|
||||
#define SSH_SERVER_ERROR -1
|
||||
#define SSH_SERVER_NOT_KNOWN 0
|
||||
#define SSH_SERVER_KNOWN_OK 1
|
||||
#define SSH_SERVER_KNOWN_CHANGED 2
|
||||
#define SSH_SERVER_FOUND_OTHER 3
|
||||
#define SSH_SERVER_FILE_NOT_FOUND 4
|
||||
|
||||
#ifndef MD5_DIGEST_LEN
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#endif
|
||||
/* errors */
|
||||
|
||||
enum ssh_error_types_e {
|
||||
SSH_NO_ERROR=0,
|
||||
SSH_REQUEST_DENIED,
|
||||
SSH_FATAL,
|
||||
SSH_EINTR
|
||||
};
|
||||
|
||||
/* some types for keys */
|
||||
enum ssh_keytypes_e{
|
||||
SSH_KEYTYPE_UNKNOWN=0,
|
||||
SSH_KEYTYPE_DSS=1,
|
||||
SSH_KEYTYPE_RSA,
|
||||
SSH_KEYTYPE_RSA1
|
||||
};
|
||||
#define SSH_NO_ERROR 0
|
||||
#define SSH_REQUEST_DENIED 1
|
||||
#define SSH_FATAL 2
|
||||
#define SSH_EINTR 3
|
||||
|
||||
/* Error return codes */
|
||||
#define SSH_OK 0 /* No error */
|
||||
@@ -247,15 +151,18 @@ enum ssh_keytypes_e{
|
||||
#define SSH_AGAIN -2 /* The nonblocking call must be repeated */
|
||||
#define SSH_EOF -127 /* We have already a eof */
|
||||
|
||||
/**
|
||||
* @addtogroup libssh_log
|
||||
*
|
||||
const char *ssh_get_error(void *error);
|
||||
int ssh_get_error_code(void *error);
|
||||
|
||||
/* version checks */
|
||||
const char *ssh_version(int req_version);
|
||||
|
||||
/** \addtogroup ssh_log
|
||||
* @{
|
||||
*/
|
||||
/** \brief Verbosity level for logging and help to debugging
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Verbosity level for logging and help to debugging
|
||||
*/
|
||||
enum {
|
||||
/** No logging at all
|
||||
*/
|
||||
@@ -263,220 +170,213 @@ enum {
|
||||
/** Only rare and noteworthy events
|
||||
*/
|
||||
SSH_LOG_RARE,
|
||||
/** High level protocol information
|
||||
/** High level protocol informations
|
||||
*/
|
||||
SSH_LOG_PROTOCOL,
|
||||
/** Lower level protocol infomations, packet level
|
||||
*/
|
||||
SSH_LOG_PACKET,
|
||||
SSH_LOG_PACKET,
|
||||
/** Every function path
|
||||
*/
|
||||
SSH_LOG_FUNCTIONS
|
||||
SSH_LOG_FUNCTIONS
|
||||
};
|
||||
/** @} */
|
||||
/** @}
|
||||
*/
|
||||
/*#define SSH_LOG_NOLOG 0 // no log
|
||||
#define SSH_LOG_RARE 1 // rare conditions
|
||||
#define SSH_LOG_ENTRY 2 // user-accessible entrypoints
|
||||
#define SSH_LOG_PACKET 3 // packet id and size
|
||||
#define SSH_LOG_FUNCTIONS 4 // every function in and return
|
||||
*/
|
||||
/* log.c */
|
||||
void ssh_log(SSH_SESSION *session, int prioriry, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
|
||||
|
||||
enum ssh_options_e {
|
||||
SSH_OPTIONS_HOST,
|
||||
SSH_OPTIONS_PORT,
|
||||
SSH_OPTIONS_PORT_STR,
|
||||
SSH_OPTIONS_FD,
|
||||
SSH_OPTIONS_USER,
|
||||
SSH_OPTIONS_SSH_DIR,
|
||||
SSH_OPTIONS_IDENTITY,
|
||||
SSH_OPTIONS_ADD_IDENTITY,
|
||||
SSH_OPTIONS_KNOWNHOSTS,
|
||||
SSH_OPTIONS_TIMEOUT,
|
||||
SSH_OPTIONS_TIMEOUT_USEC,
|
||||
SSH_OPTIONS_SSH1,
|
||||
SSH_OPTIONS_SSH2,
|
||||
SSH_OPTIONS_LOG_VERBOSITY,
|
||||
SSH_OPTIONS_LOG_VERBOSITY_STR,
|
||||
SSH_OPTIONS_CIPHERS_C_S,
|
||||
SSH_OPTIONS_CIPHERS_S_C,
|
||||
SSH_OPTIONS_COMPRESSION_C_S,
|
||||
SSH_OPTIONS_COMPRESSION_S_C,
|
||||
SSH_OPTIONS_PROXYCOMMAND,
|
||||
SSH_OPTIONS_BINDADDR,
|
||||
SSH_OPTIONS_STRICTHOSTKEYCHECK,
|
||||
SSH_OPTIONS_COMPRESSION,
|
||||
SSH_OPTIONS_COMPRESSION_LEVEL
|
||||
};
|
||||
/* session.c */
|
||||
SSH_SESSION *ssh_new(void);
|
||||
socket_t ssh_get_fd(SSH_SESSION *session);
|
||||
int ssh_get_version(SSH_SESSION *session);
|
||||
int ssh_get_status(SSH_SESSION *session);
|
||||
const char *ssh_get_disconnect_message(SSH_SESSION *session);
|
||||
void ssh_set_options(SSH_SESSION *session, SSH_OPTIONS *options);
|
||||
void ssh_set_fd_toread(SSH_SESSION *session);
|
||||
void ssh_set_fd_towrite(SSH_SESSION *session);
|
||||
void ssh_set_fd_except(SSH_SESSION *session);
|
||||
void ssh_set_blocking(SSH_SESSION *session, int blocking);
|
||||
void ssh_silent_disconnect(SSH_SESSION *session);
|
||||
|
||||
enum {
|
||||
/** Code is going to write/create remote files */
|
||||
SSH_SCP_WRITE,
|
||||
/** Code is going to read remote files */
|
||||
SSH_SCP_READ,
|
||||
SSH_SCP_RECURSIVE=0x10
|
||||
};
|
||||
|
||||
enum ssh_scp_request_types {
|
||||
/** A new directory is going to be pulled */
|
||||
SSH_SCP_REQUEST_NEWDIR=1,
|
||||
/** A new file is going to be pulled */
|
||||
SSH_SCP_REQUEST_NEWFILE,
|
||||
/** End of requests */
|
||||
SSH_SCP_REQUEST_EOF,
|
||||
/** End of directory */
|
||||
SSH_SCP_REQUEST_ENDDIR,
|
||||
/** Warning received */
|
||||
SSH_SCP_REQUEST_WARNING
|
||||
};
|
||||
/* client.c */
|
||||
int ssh_connect(SSH_SESSION *session);
|
||||
void ssh_disconnect(SSH_SESSION *session);
|
||||
int ssh_service_request(SSH_SESSION *session, const char *service);
|
||||
char *ssh_get_issue_banner(SSH_SESSION *session);
|
||||
int ssh_get_openssh_version(SSH_SESSION *session);
|
||||
/* get copyright informations */
|
||||
const char *ssh_copyright(void);
|
||||
|
||||
LIBSSH_API int ssh_blocking_flush(ssh_session session, int timeout);
|
||||
LIBSSH_API ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||
LIBSSH_API int ssh_channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||
LIBSSH_API int ssh_channel_close(ssh_channel channel);
|
||||
LIBSSH_API void ssh_channel_free(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_get_exit_status(ssh_channel channel);
|
||||
LIBSSH_API ssh_session ssh_channel_get_session(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_is_closed(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_is_eof(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_is_open(ssh_channel channel);
|
||||
LIBSSH_API ssh_channel ssh_channel_new(ssh_session session);
|
||||
LIBSSH_API int ssh_channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||
int remoteport, const char *sourcehost, int localport);
|
||||
LIBSSH_API int ssh_channel_open_session(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_poll(ssh_channel channel, int is_stderr);
|
||||
LIBSSH_API int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
||||
LIBSSH_API int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr);
|
||||
LIBSSH_API int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value);
|
||||
LIBSSH_API int ssh_channel_request_exec(ssh_channel channel, const char *cmd);
|
||||
LIBSSH_API int ssh_channel_request_pty(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_request_pty_size(ssh_channel channel, const char *term,
|
||||
int cols, int rows);
|
||||
LIBSSH_API int ssh_channel_request_shell(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_request_send_signal(ssh_channel channel, const char *signum);
|
||||
LIBSSH_API int ssh_channel_request_sftp(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_request_subsystem(ssh_channel channel, const char *subsystem);
|
||||
LIBSSH_API int ssh_channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
|
||||
const char *cookie, int screen_number);
|
||||
LIBSSH_API int ssh_channel_send_eof(ssh_channel channel);
|
||||
LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
||||
timeval * timeout);
|
||||
LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking);
|
||||
LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len);
|
||||
LIBSSH_API uint32_t ssh_channel_window_size(ssh_channel channel);
|
||||
/* string.h */
|
||||
|
||||
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
||||
ssh_string *publickey, int *type);
|
||||
/* You can use these functions, they won't change */
|
||||
/* string_from_char returns a newly allocated string from a char *ptr */
|
||||
STRING *string_from_char(const char *what);
|
||||
/* it returns the string len in host byte orders. str->size is big endian warning ! */
|
||||
size_t string_len(STRING *str);
|
||||
STRING *string_new(size_t size);
|
||||
/* string_fill copies the data in the string. */
|
||||
int string_fill(STRING *str, const void *data, size_t len);
|
||||
/* returns a newly allocated char array with the str string and a final nul caracter */
|
||||
char *string_to_char(STRING *str);
|
||||
STRING *string_copy(STRING *str);
|
||||
/* burns the data inside a string */
|
||||
void string_burn(STRING *str);
|
||||
void *string_data(STRING *str);
|
||||
void string_free(STRING *str);
|
||||
|
||||
LIBSSH_API int ssh_auth_list(ssh_session session);
|
||||
LIBSSH_API char *ssh_basename (const char *path);
|
||||
LIBSSH_API void ssh_clean_pubkey_hash(unsigned char **hash);
|
||||
LIBSSH_API int ssh_connect(ssh_session session);
|
||||
LIBSSH_API const char *ssh_copyright(void);
|
||||
LIBSSH_API void ssh_disconnect(ssh_session session);
|
||||
LIBSSH_API char *ssh_dirname (const char *path);
|
||||
LIBSSH_API int ssh_finalize(void);
|
||||
LIBSSH_API ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms);
|
||||
LIBSSH_API int ssh_forward_cancel(ssh_session session, const char *address, int port);
|
||||
LIBSSH_API int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
||||
LIBSSH_API void ssh_free(ssh_session session);
|
||||
LIBSSH_API const char *ssh_get_disconnect_message(ssh_session session);
|
||||
LIBSSH_API const char *ssh_get_error(void *error);
|
||||
LIBSSH_API int ssh_get_error_code(void *error);
|
||||
LIBSSH_API socket_t ssh_get_fd(ssh_session session);
|
||||
LIBSSH_API char *ssh_get_hexa(const unsigned char *what, size_t len);
|
||||
LIBSSH_API char *ssh_get_issue_banner(ssh_session session);
|
||||
LIBSSH_API int ssh_get_openssh_version(ssh_session session);
|
||||
LIBSSH_API ssh_string ssh_get_pubkey(ssh_session session);
|
||||
LIBSSH_API int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash);
|
||||
LIBSSH_API int ssh_get_random(void *where,int len,int strong);
|
||||
LIBSSH_API int ssh_get_version(ssh_session session);
|
||||
LIBSSH_API int ssh_get_status(ssh_session session);
|
||||
LIBSSH_API int ssh_init(void);
|
||||
LIBSSH_API int ssh_is_blocking(ssh_session session);
|
||||
LIBSSH_API int ssh_is_connected(ssh_session session);
|
||||
LIBSSH_API int ssh_is_server_known(ssh_session session);
|
||||
LIBSSH_API void ssh_log(ssh_session session, int prioriry, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
|
||||
LIBSSH_API ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_reply_success(ssh_message msg);
|
||||
LIBSSH_API void ssh_message_free(ssh_message msg);
|
||||
LIBSSH_API ssh_message ssh_message_get(ssh_session session);
|
||||
LIBSSH_API int ssh_message_subtype(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_type(ssh_message msg);
|
||||
LIBSSH_API int ssh_mkdir (const char *pathname, mode_t mode);
|
||||
LIBSSH_API ssh_session ssh_new(void);
|
||||
/* useful for debug */
|
||||
char *ssh_get_hexa(const unsigned char *what, size_t len);
|
||||
void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
|
||||
int ssh_get_random(void *where,int len,int strong);
|
||||
|
||||
LIBSSH_API int ssh_options_copy(ssh_session src, ssh_session *dest);
|
||||
LIBSSH_API int ssh_options_getopt(ssh_session session, int *argcptr, char **argv);
|
||||
LIBSSH_API int ssh_options_parse_config(ssh_session session, const char *filename);
|
||||
LIBSSH_API int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
const void *value);
|
||||
LIBSSH_API int ssh_pcap_file_close(ssh_pcap_file pcap);
|
||||
LIBSSH_API void ssh_pcap_file_free(ssh_pcap_file pcap);
|
||||
LIBSSH_API ssh_pcap_file ssh_pcap_file_new(void);
|
||||
LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
||||
/* this one can be called by the client to see the hash of the public key before accepting it */
|
||||
int ssh_get_pubkey_hash(SSH_SESSION *session, unsigned char **hash);
|
||||
STRING *ssh_get_pubkey(SSH_SESSION *session);
|
||||
|
||||
LIBSSH_API enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey);
|
||||
|
||||
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
|
||||
LIBSSH_API int ssh_scp_accept_request(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_close(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_deny_request(ssh_scp scp, const char *reason);
|
||||
LIBSSH_API void ssh_scp_free(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_init(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_leave_directory(ssh_scp scp);
|
||||
LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location);
|
||||
LIBSSH_API int ssh_scp_pull_request(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode);
|
||||
LIBSSH_API int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int perms);
|
||||
LIBSSH_API int ssh_scp_read(ssh_scp scp, void *buffer, size_t size);
|
||||
LIBSSH_API const char *ssh_scp_request_get_filename(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_request_get_permissions(ssh_scp scp);
|
||||
LIBSSH_API size_t ssh_scp_request_get_size(ssh_scp scp);
|
||||
LIBSSH_API const char *ssh_scp_request_get_warning(ssh_scp scp);
|
||||
LIBSSH_API int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len);
|
||||
LIBSSH_API int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
||||
/* in connect.c */
|
||||
int ssh_fd_poll(SSH_SESSION *session,int *write, int *except);
|
||||
int ssh_select(CHANNEL **channels, CHANNEL **outchannels, socket_t maxfd,
|
||||
fd_set *readfds, struct timeval *timeout);
|
||||
LIBSSH_API int ssh_service_request(ssh_session session, const char *service);
|
||||
LIBSSH_API void ssh_set_blocking(ssh_session session, int blocking);
|
||||
LIBSSH_API void ssh_set_fd_except(ssh_session session);
|
||||
LIBSSH_API void ssh_set_fd_toread(ssh_session session);
|
||||
LIBSSH_API void ssh_set_fd_towrite(ssh_session session);
|
||||
LIBSSH_API void ssh_silent_disconnect(ssh_session session);
|
||||
LIBSSH_API int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcapfile);
|
||||
#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_kbdint(ssh_session session, const char *user, const char *submethods);
|
||||
LIBSSH_API const char *ssh_userauth_kbdint_getinstruction(ssh_session session);
|
||||
LIBSSH_API const char *ssh_userauth_kbdint_getname(ssh_session session);
|
||||
LIBSSH_API int ssh_userauth_kbdint_getnprompts(ssh_session session);
|
||||
LIBSSH_API const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i, char *echo);
|
||||
LIBSSH_API int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
|
||||
|
||||
void publickey_free(PUBLIC_KEY *key);
|
||||
|
||||
/* in keyfiles.c */
|
||||
|
||||
PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session, const char *filename,
|
||||
int type, const char *passphrase);
|
||||
STRING *publickey_to_string(PUBLIC_KEY *key);
|
||||
PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv);
|
||||
void privatekey_free(PRIVATE_KEY *prv);
|
||||
STRING *publickey_from_file(SSH_SESSION *session, const char *filename,
|
||||
int *type);
|
||||
int ssh_is_server_known(SSH_SESSION *session);
|
||||
int ssh_write_knownhost(SSH_SESSION *session);
|
||||
|
||||
/* in channels.c */
|
||||
|
||||
CHANNEL *channel_new(SSH_SESSION *session);
|
||||
int channel_open_forward(CHANNEL *channel, const char *remotehost,
|
||||
int remoteport, const char *sourcehost, int localport);
|
||||
int channel_open_session(CHANNEL *channel);
|
||||
void channel_free(CHANNEL *channel);
|
||||
int channel_request_pty(CHANNEL *channel);
|
||||
int channel_request_pty_size(CHANNEL *channel, const char *term,
|
||||
int cols, int rows);
|
||||
int channel_change_pty_size(CHANNEL *channel,int cols,int rows);
|
||||
int channel_request_shell(CHANNEL *channel);
|
||||
int channel_request_subsystem(CHANNEL *channel, const char *system);
|
||||
int channel_request_env(CHANNEL *channel, const char *name, const char *value);
|
||||
int channel_request_exec(CHANNEL *channel, const char *cmd);
|
||||
int channel_request_sftp(CHANNEL *channel);
|
||||
int channel_write(CHANNEL *channel, const void *data, u32 len);
|
||||
int channel_send_eof(CHANNEL *channel);
|
||||
int channel_is_eof(CHANNEL *channel);
|
||||
int channel_read(CHANNEL *channel, void *dest, u32 count, int is_stderr);
|
||||
int channel_read_buffer(CHANNEL *channel, BUFFER *buffer, u32 count,
|
||||
int is_stderr);
|
||||
int channel_poll(CHANNEL *channel, int is_stderr);
|
||||
int channel_close(CHANNEL *channel);
|
||||
void channel_set_blocking(CHANNEL *channel, int blocking);
|
||||
int channel_read_nonblocking(CHANNEL *channel, void *dest, u32 count,
|
||||
int is_stderr);
|
||||
int channel_is_open(CHANNEL *channel);
|
||||
int channel_is_closed(CHANNEL *channel);
|
||||
int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptchans, struct
|
||||
timeval * timeout);
|
||||
SSH_SESSION *channel_get_session(CHANNEL *channel);
|
||||
int channel_get_exit_status(CHANNEL *channel);
|
||||
/* in options.c */
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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);
|
||||
|
||||
SSH_OPTIONS *ssh_options_new(void);
|
||||
SSH_OPTIONS *ssh_options_copy(SSH_OPTIONS *opt);
|
||||
void ssh_options_free(SSH_OPTIONS *opt);
|
||||
int ssh_options_set_wanted_algos(SSH_OPTIONS *opt, int algo, const char *list);
|
||||
int ssh_options_set_username(SSH_OPTIONS *opt, const char *username);
|
||||
int ssh_options_set_port(SSH_OPTIONS *opt, unsigned int port);
|
||||
int ssh_options_getopt(SSH_OPTIONS *options, int *argcptr, char **argv);
|
||||
int ssh_options_set_host(SSH_OPTIONS *opt, const char *host);
|
||||
int ssh_options_set_fd(SSH_OPTIONS *opt, socket_t fd);
|
||||
int ssh_options_set_bind(SSH_OPTIONS *opt, const char *bindaddr, int port);
|
||||
int ssh_options_set_ssh_dir(SSH_OPTIONS *opt, const char *dir);
|
||||
int ssh_options_set_known_hosts_file(SSH_OPTIONS *opt, const char *dir);
|
||||
int ssh_options_set_identity(SSH_OPTIONS *opt, const char *identity);
|
||||
int ssh_options_set_banner(SSH_OPTIONS *opt, const char *banner);
|
||||
int ssh_options_set_status_callback(SSH_OPTIONS *opt, void (*callback)
|
||||
(void *arg, float status), void *arg);
|
||||
int ssh_options_set_timeout(SSH_OPTIONS *opt, long seconds, long usec);
|
||||
int ssh_options_allow_ssh1(SSH_OPTIONS *opt, int allow);
|
||||
int ssh_options_allow_ssh2(SSH_OPTIONS *opt, int allow);
|
||||
int ssh_options_set_log_function(SSH_OPTIONS *opt,
|
||||
void (*callback)(const char *message, SSH_SESSION *session, int verbosity));
|
||||
int ssh_options_set_log_verbosity(SSH_OPTIONS *opt, int verbosity);
|
||||
int ssh_options_set_dsa_server_key(SSH_OPTIONS *opt, const char *dsakey);
|
||||
int ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, const char *rsakey);
|
||||
int ssh_options_set_auth_callback(SSH_OPTIONS *opt, ssh_auth_callback cb,
|
||||
void *userdata);
|
||||
|
||||
|
||||
/* buffer.c */
|
||||
|
||||
/** creates a new buffer
|
||||
*/
|
||||
BUFFER *buffer_new(void);
|
||||
void buffer_free(BUFFER *buffer);
|
||||
/* buffer_get returns a pointer to the begining of the buffer. no position is taken into account */
|
||||
void *buffer_get(BUFFER *buffer);
|
||||
/* same here */
|
||||
u32 buffer_get_len(BUFFER *buffer);
|
||||
|
||||
|
||||
/* in auth.c */
|
||||
int ssh_auth_list(SSH_SESSION *session);
|
||||
/* these functions returns AUTH_ERROR is some serious error has happened,
|
||||
AUTH_SUCCESS if success,
|
||||
AUTH_PARTIAL if partial success,
|
||||
AUTH_DENIED if refused */
|
||||
int ssh_userauth_list(SSH_SESSION *session, const char *username);
|
||||
int ssh_userauth_none(SSH_SESSION *session, const char *username);
|
||||
int ssh_userauth_password(SSH_SESSION *session, const char *username, const char *password);
|
||||
int ssh_userauth_offer_pubkey(SSH_SESSION *session, const char *username, int type, STRING *publickey);
|
||||
int ssh_userauth_pubkey(SSH_SESSION *session, const char *username, STRING *publickey, PRIVATE_KEY *privatekey);
|
||||
int ssh_userauth_agent_pubkey(SSH_SESSION *session, const char *username,
|
||||
PUBLIC_KEY *publickey);
|
||||
int ssh_userauth_autopubkey(SSH_SESSION *session, const char *passphrase);
|
||||
int ssh_userauth_kbdint(SSH_SESSION *session, const char *user, const char *submethods);
|
||||
int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session);
|
||||
const char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
|
||||
const char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
|
||||
const char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i, char *echo);
|
||||
int ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i,
|
||||
const char *answer);
|
||||
LIBSSH_API int ssh_userauth_list(ssh_session session, const char *username);
|
||||
LIBSSH_API int ssh_userauth_none(ssh_session session, const char *username);
|
||||
LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey);
|
||||
LIBSSH_API int ssh_userauth_password(ssh_session session, const char *username, const char *password);
|
||||
LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey);
|
||||
LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username,
|
||||
const char *filename, const char *passphrase);
|
||||
LIBSSH_API const char *ssh_version(int req_version);
|
||||
LIBSSH_API int ssh_write_knownhost(ssh_session session);
|
||||
|
||||
LIBSSH_API void ssh_string_burn(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_copy(ssh_string str);
|
||||
LIBSSH_API void *ssh_string_data(ssh_string str);
|
||||
LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len);
|
||||
LIBSSH_API void ssh_string_free(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_from_char(const char *what);
|
||||
LIBSSH_API size_t ssh_string_len(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_new(size_t size);
|
||||
LIBSSH_API char *ssh_string_to_char(ssh_string str);
|
||||
LIBSSH_API void ssh_string_free_char(char *s);
|
||||
|
||||
LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo,
|
||||
int verify);
|
||||
|
||||
#ifndef LIBSSH_LEGACY_0_4
|
||||
#include "libssh/legacy.h"
|
||||
#endif
|
||||
/* init.c */
|
||||
int ssh_init(void);
|
||||
int ssh_finalize(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,604 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 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 LIBSSHPP_HPP_
|
||||
#define LIBSSHPP_HPP_
|
||||
|
||||
/**
|
||||
* @defgroup ssh_cpp The libssh C++ wrapper
|
||||
*
|
||||
* The C++ bindings for libssh are completely embedded in a single .hpp file, and
|
||||
* this for two reasons:
|
||||
* - C++ is hard to keep binary compatible, C is easy. We try to keep libssh C version
|
||||
* as much as possible binary compatible between releases, while this would be hard for
|
||||
* C++. If you compile your program with these headers, you will only link to the C version
|
||||
* of libssh which will be kept ABI compatible. No need to recompile your C++ program
|
||||
* each time a new binary-compatible version of libssh is out
|
||||
* - Most of the functions in this file are really short and are probably worth the "inline"
|
||||
* linking mode, which the compiler can decide to do in some case. There would be nearly no
|
||||
* performance penalty of using the wrapper rather than native calls.
|
||||
*
|
||||
* Please visit the documentation of ssh::Session and ssh::Channel
|
||||
* @see ssh::Session
|
||||
* @see ssh::Channel
|
||||
*
|
||||
* If you wish not to use C++ exceptions, please define SSH_NO_CPP_EXCEPTIONS:
|
||||
* @code
|
||||
* #define SSH_NO_CPP_EXCEPTIONS
|
||||
* #include <libssh/libsshpp.hpp>
|
||||
* @endcode
|
||||
* All functions will then return SSH_ERROR in case of error.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* do not use deprecated functions */
|
||||
#define LIBSSH_LEGACY_0_4
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace ssh {
|
||||
|
||||
class Channel;
|
||||
/** Some people do not like C++ exceptions. With this define, we give
|
||||
* the choice to use or not exceptions.
|
||||
* @brief if defined, disable C++ exceptions for libssh c++ wrapper
|
||||
*/
|
||||
#ifndef SSH_NO_CPP_EXCEPTIONS
|
||||
|
||||
/** @brief This class describes a SSH Exception object. This object can be thrown
|
||||
* by several SSH functions that interact with the network, and may fail because of
|
||||
* socket, protocol or memory errors.
|
||||
*/
|
||||
class SshException{
|
||||
public:
|
||||
SshException(ssh_session csession){
|
||||
code=ssh_get_error_code(csession);
|
||||
description=std::string(ssh_get_error(csession));
|
||||
}
|
||||
SshException(const SshException &e){
|
||||
code=e.code;
|
||||
description=e.description;
|
||||
}
|
||||
/** @brief returns the Error code
|
||||
* @returns SSH_FATAL Fatal error happened (not recoverable)
|
||||
* @returns SSH_REQUEST_DENIED Request was denied by remote host
|
||||
* @see ssh_get_error_code
|
||||
*/
|
||||
int getCode(){
|
||||
return code;
|
||||
}
|
||||
/** @brief returns the error message of the last exception
|
||||
* @returns pointer to a c string containing the description of error
|
||||
* @see ssh_get_error
|
||||
*/
|
||||
std::string getError(){
|
||||
return description;
|
||||
}
|
||||
private:
|
||||
int code;
|
||||
std::string description;
|
||||
};
|
||||
|
||||
/** @internal
|
||||
* @brief Macro to throw exception if there was an error
|
||||
*/
|
||||
#define ssh_throw(x) if((x)==SSH_ERROR) throw SshException(getCSession())
|
||||
#define ssh_throw_null(CSession,x) if((x)==NULL) throw SshException(CSession)
|
||||
#define void_throwable void
|
||||
#define return_throwable return
|
||||
|
||||
#else
|
||||
|
||||
/* No exception at all. All functions will return an error code instead
|
||||
* of an exception
|
||||
*/
|
||||
#define ssh_throw(x) if((x)==SSH_ERROR) return SSH_ERROR
|
||||
#define ssh_throw_null(CSession,x) if((x)==NULL) return NULL
|
||||
#define void_throwable int
|
||||
#define return_throwable return SSH_OK
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The ssh::Session class contains the state of a SSH connection.
|
||||
*/
|
||||
class Session {
|
||||
friend class Channel;
|
||||
public:
|
||||
Session(){
|
||||
c_session=ssh_new();
|
||||
}
|
||||
~Session(){
|
||||
ssh_free(c_session);
|
||||
c_session=NULL;
|
||||
}
|
||||
/** @brief sets an SSH session options
|
||||
* @param type Type of option
|
||||
* @param option cstring containing the value of option
|
||||
* @throws SshException on error
|
||||
* @see ssh_options_set
|
||||
*/
|
||||
void_throwable setOption(enum ssh_options_e type, const char *option){
|
||||
ssh_throw(ssh_options_set(c_session,type,option));
|
||||
return_throwable;
|
||||
}
|
||||
/** @brief sets an SSH session options
|
||||
* @param type Type of option
|
||||
* @param option long integer containing the value of option
|
||||
* @throws SshException on error
|
||||
* @see ssh_options_set
|
||||
*/
|
||||
void_throwable setOption(enum ssh_options_e type, long int option){
|
||||
ssh_throw(ssh_options_set(c_session,type,&option));
|
||||
return_throwable;
|
||||
}
|
||||
/** @brief sets an SSH session options
|
||||
* @param type Type of option
|
||||
* @param option void pointer containing the value of option
|
||||
* @throws SshException on error
|
||||
* @see ssh_options_set
|
||||
*/
|
||||
void_throwable setOption(enum ssh_options_e type, void *option){
|
||||
ssh_throw(ssh_options_set(c_session,type,option));
|
||||
return_throwable;
|
||||
}
|
||||
/** @brief connects to the remote host
|
||||
* @throws SshException on error
|
||||
* @see ssh_connect
|
||||
*/
|
||||
void_throwable connect(){
|
||||
int ret=ssh_connect(c_session);
|
||||
ssh_throw(ret);
|
||||
return_throwable;
|
||||
}
|
||||
/** @brief Authenticates automatically using public key
|
||||
* @throws SshException on error
|
||||
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED
|
||||
* @see ssh_userauth_autopubkey
|
||||
*/
|
||||
int userauthAutopubkey(void){
|
||||
int ret=ssh_userauth_autopubkey(c_session,NULL);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
/** @brief Authenticates using the "none" method. Prefer using autopubkey if
|
||||
* possible.
|
||||
* @throws SshException on error
|
||||
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED
|
||||
* @see ssh_userauth_none
|
||||
* @see Session::userauthAutoPubkey
|
||||
*/
|
||||
int userauthNone(){
|
||||
int ret=ssh_userauth_none(c_session,NULL);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
/** @brief Authenticates using the password method.
|
||||
* @param[in] password password to use for authentication
|
||||
* @throws SshException on error
|
||||
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED
|
||||
* @see ssh_userauth_password
|
||||
*/
|
||||
int userauthPassword(const char *password){
|
||||
int ret=ssh_userauth_password(c_session,NULL,password);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
/** @brief Try to authenticate using the publickey method.
|
||||
* @param[in] type public key type
|
||||
* @param[in] pubkey public key to use for authentication
|
||||
* @throws SshException on error
|
||||
* @returns SSH_AUTH_SUCCESS if the pubkey is accepted,
|
||||
* @returns SSH_AUTH_DENIED if the pubkey is denied
|
||||
* @see ssh_userauth_offer_pubkey
|
||||
*/
|
||||
int userauthOfferPubkey(int type, ssh_string pubkey){
|
||||
int ret=ssh_userauth_offer_pubkey(c_session,NULL,type,pubkey);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
/** @brief Authenticates using the publickey method.
|
||||
* @param[in] pubkey public key to use for authentication
|
||||
* @param[in] privkey private key to use for authentication
|
||||
* @throws SshException on error
|
||||
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED
|
||||
* @see ssh_userauth_pubkey
|
||||
*/
|
||||
int userauthPubkey(ssh_string pubkey, ssh_private_key privkey){
|
||||
int ret=ssh_userauth_pubkey(c_session,NULL,pubkey,privkey);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
int userauthPubkey(ssh_private_key privkey){
|
||||
int ret=ssh_userauth_pubkey(c_session,NULL,NULL,privkey);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
int userauthPrivatekeyFile(const char *filename,
|
||||
const char *passphrase);
|
||||
/** @brief Returns the available authentication methods from the server
|
||||
* @throws SshException on error
|
||||
* @returns Bitfield of available methods.
|
||||
* @see ssh_userauth_list
|
||||
*/
|
||||
int getAuthList(){
|
||||
int ret=ssh_userauth_list(c_session, NULL);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
/** @brief Disconnects from the SSH server and closes connection
|
||||
* @see ssh_disconnect
|
||||
*/
|
||||
void disconnect(){
|
||||
ssh_disconnect(c_session);
|
||||
}
|
||||
/** @brief Returns the disconnect message from the server, if any
|
||||
* @returns pointer to the message, or NULL. Do not attempt to free
|
||||
* the pointer.
|
||||
*/
|
||||
const char *getDisconnectMessage(){
|
||||
const char *msg=ssh_get_disconnect_message(c_session);
|
||||
return msg;
|
||||
}
|
||||
/** @internal
|
||||
* @brief gets error message
|
||||
*/
|
||||
const char *getError(){
|
||||
return ssh_get_error(c_session);
|
||||
}
|
||||
/** @internal
|
||||
* @brief returns error code
|
||||
*/
|
||||
int getErrorCode(){
|
||||
return ssh_get_error_code(c_session);
|
||||
}
|
||||
/** @brief returns the file descriptor used for the communication
|
||||
* @returns the file descriptor
|
||||
* @warning if a proxycommand is used, this function will only return
|
||||
* one of the two file descriptors being used
|
||||
* @see ssh_get_fd
|
||||
*/
|
||||
socket_t getSocket(){
|
||||
return ssh_get_fd(c_session);
|
||||
}
|
||||
/** @brief gets the Issue banner from the ssh server
|
||||
* @returns the issue banner. This is generally a MOTD from server
|
||||
* @see ssh_get_issue_banner
|
||||
*/
|
||||
std::string getIssueBanner(){
|
||||
char *banner=ssh_get_issue_banner(c_session);
|
||||
std::string ret= std::string(banner);
|
||||
::free(banner);
|
||||
return ret;
|
||||
}
|
||||
/** @brief returns the OpenSSH version (server) if possible
|
||||
* @returns openssh version code
|
||||
* @see ssh_get_openssh_version
|
||||
*/
|
||||
int getOpensshVersion(){
|
||||
return ssh_get_openssh_version(c_session);
|
||||
}
|
||||
/** @brief returns the version of the SSH protocol being used
|
||||
* @returns the SSH protocol version
|
||||
* @see ssh_get_version
|
||||
*/
|
||||
int getVersion(){
|
||||
return ssh_get_version(c_session);
|
||||
}
|
||||
/** @brief verifies that the server is known
|
||||
* @throws SshException on error
|
||||
* @returns Integer value depending on the knowledge of the
|
||||
* server key
|
||||
* @see ssh_is_server_known
|
||||
*/
|
||||
int isServerKnown(){
|
||||
int ret=ssh_is_server_known(c_session);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
void log(int priority, const char *format, ...){
|
||||
char buffer[1024];
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, va);
|
||||
va_end(va);
|
||||
ssh_log(c_session,priority, "%s", buffer);
|
||||
}
|
||||
|
||||
/** @brief copies options from a session to another
|
||||
* @throws SshException on error
|
||||
* @see ssh_options_copy
|
||||
*/
|
||||
void_throwable optionsCopy(const Session &source){
|
||||
ssh_throw(ssh_options_copy(source.c_session,&c_session));
|
||||
return_throwable;
|
||||
}
|
||||
/** @brief parses a configuration file for options
|
||||
* @throws SshException on error
|
||||
* @param[in] file configuration file name
|
||||
* @see ssh_options_parse_config
|
||||
*/
|
||||
void_throwable optionsParseConfig(const char *file){
|
||||
ssh_throw(ssh_options_parse_config(c_session,file));
|
||||
return_throwable;
|
||||
}
|
||||
/** @brief silently disconnect from remote host
|
||||
* @see ssh_silent_disconnect
|
||||
*/
|
||||
void silentDisconnect(){
|
||||
ssh_silent_disconnect(c_session);
|
||||
}
|
||||
/** @brief Writes the known host file with current
|
||||
* host key
|
||||
* @throws SshException on error
|
||||
* @see ssh_write_knownhost
|
||||
*/
|
||||
int writeKnownhost(){
|
||||
int ret = ssh_write_knownhost(c_session);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief accept an incoming forward connection
|
||||
* @param[in] timeout_ms timeout for waiting, in ms
|
||||
* @returns new Channel pointer on the forward connection
|
||||
* @returns NULL in case of error
|
||||
* @warning you have to delete this pointer after use
|
||||
* @see ssh_channel_forward_accept
|
||||
* @see Session::listenForward
|
||||
*/
|
||||
Channel *acceptForward(int timeout_ms);
|
||||
/* acceptForward is implemented later in this file */
|
||||
|
||||
void_throwable cancelForward(const char *address, int port){
|
||||
int err=ssh_forward_cancel(c_session, address, port);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
|
||||
void_throwable listenForward(const char *address, int port,
|
||||
int &boundport){
|
||||
int err=ssh_forward_listen(c_session, address, port, &boundport);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
|
||||
private:
|
||||
ssh_session c_session;
|
||||
ssh_session getCSession(){
|
||||
return c_session;
|
||||
}
|
||||
/* No copy constructor, no = operator */
|
||||
Session(const Session &);
|
||||
Session& operator=(const Session &);
|
||||
};
|
||||
|
||||
/** @brief the ssh::Channel class describes the state of an SSH
|
||||
* channel.
|
||||
* @see ssh_channel
|
||||
*/
|
||||
class Channel {
|
||||
friend class Session;
|
||||
public:
|
||||
Channel(Session &session){
|
||||
channel=ssh_channel_new(session.getCSession());
|
||||
this->session=&session;
|
||||
}
|
||||
~Channel(){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
|
||||
/** @brief accept an incoming X11 connection
|
||||
* @param[in] timeout_ms timeout for waiting, in ms
|
||||
* @returns new Channel pointer on the X11 connection
|
||||
* @returns NULL in case of error
|
||||
* @warning you have to delete this pointer after use
|
||||
* @see ssh_channel_accept_x11
|
||||
* @see Channel::requestX11
|
||||
*/
|
||||
Channel *acceptX11(int timeout_ms){
|
||||
ssh_channel x11chan = ssh_channel_accept_x11(channel,timeout_ms);
|
||||
ssh_throw_null(getCSession(),x11chan);
|
||||
Channel *newchan = new Channel(getSession(),x11chan);
|
||||
return newchan;
|
||||
}
|
||||
/** @brief change the size of a pseudoterminal
|
||||
* @param[in] cols number of columns
|
||||
* @param[in] rows number of rows
|
||||
* @throws SshException on error
|
||||
* @see ssh_channel_change_pty_size
|
||||
*/
|
||||
void_throwable changePtySize(int cols, int rows){
|
||||
int err=ssh_channel_change_pty_size(channel,cols,rows);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
|
||||
/** @brief closes a channel
|
||||
* @throws SshException on error
|
||||
* @see ssh_channel_close
|
||||
*/
|
||||
void_throwable close(){
|
||||
ssh_throw(ssh_channel_close(channel));
|
||||
return_throwable;
|
||||
}
|
||||
|
||||
int getExitStatus(){
|
||||
return ssh_channel_get_exit_status(channel);
|
||||
}
|
||||
Session &getSession(){
|
||||
return *session;
|
||||
}
|
||||
/** @brief returns true if channel is in closed state
|
||||
* @see ssh_channel_is_closed
|
||||
*/
|
||||
bool isClosed(){
|
||||
return ssh_channel_is_closed(channel) != 0;
|
||||
}
|
||||
/** @brief returns true if channel is in EOF state
|
||||
* @see ssh_channel_is_eof
|
||||
*/
|
||||
bool isEof(){
|
||||
return ssh_channel_is_eof(channel) != 0;
|
||||
}
|
||||
/** @brief returns true if channel is in open state
|
||||
* @see ssh_channel_is_open
|
||||
*/
|
||||
bool isOpen(){
|
||||
return ssh_channel_is_open(channel) != 0;
|
||||
}
|
||||
int openForward(const char *remotehost, int remoteport,
|
||||
const char *sourcehost=NULL, int localport=0){
|
||||
int err=ssh_channel_open_forward(channel,remotehost,remoteport,
|
||||
sourcehost, localport);
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
/* TODO: completely remove this ? */
|
||||
void_throwable openSession(){
|
||||
int err=ssh_channel_open_session(channel);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
int poll(bool is_stderr=false){
|
||||
int err=ssh_channel_poll(channel,is_stderr);
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
int read(void *dest, size_t count, bool is_stderr=false){
|
||||
int err;
|
||||
/* handle int overflow */
|
||||
if(count > 0x7fffffff)
|
||||
count = 0x7fffffff;
|
||||
err=ssh_channel_read(channel,dest,count,is_stderr);
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
int readNonblocking(void *dest, size_t count, bool is_stderr=false){
|
||||
int err;
|
||||
/* handle int overflow */
|
||||
if(count > 0x7fffffff)
|
||||
count = 0x7fffffff;
|
||||
err=ssh_channel_read_nonblocking(channel,dest,count,is_stderr);
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
void_throwable requestEnv(const char *name, const char *value){
|
||||
int err=ssh_channel_request_env(channel,name,value);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
|
||||
void_throwable requestExec(const char *cmd){
|
||||
int err=ssh_channel_request_exec(channel,cmd);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0){
|
||||
int err;
|
||||
if(term != NULL && cols != 0 && rows != 0)
|
||||
err=ssh_channel_request_pty_size(channel,term,cols,rows);
|
||||
else
|
||||
err=ssh_channel_request_pty(channel);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
|
||||
void_throwable requestShell(){
|
||||
int err=ssh_channel_request_shell(channel);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
void_throwable requestSendSignal(const char *signum){
|
||||
int err=ssh_channel_request_send_signal(channel, signum);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
void_throwable requestSubsystem(const char *subsystem){
|
||||
int err=ssh_channel_request_subsystem(channel,subsystem);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
int requestX11(bool single_connection,
|
||||
const char *protocol, const char *cookie, int screen_number){
|
||||
int err=ssh_channel_request_x11(channel,single_connection,
|
||||
protocol, cookie, screen_number);
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
void_throwable sendEof(){
|
||||
int err=ssh_channel_send_eof(channel);
|
||||
ssh_throw(err);
|
||||
return_throwable;
|
||||
}
|
||||
/** @brief Writes on a channel
|
||||
* @param data data to write.
|
||||
* @param len number of bytes to write.
|
||||
* @param is_stderr write should be done on the stderr channel (server only)
|
||||
* @returns number of bytes written
|
||||
* @throws SshException in case of error
|
||||
* @see channel_write
|
||||
* @see channel_write_stderr
|
||||
*/
|
||||
int write(const void *data, size_t len, bool is_stderr=false){
|
||||
int ret;
|
||||
if(is_stderr){
|
||||
ret=ssh_channel_write_stderr(channel,data,len);
|
||||
} else {
|
||||
ret=ssh_channel_write(channel,data,len);
|
||||
}
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
ssh_session getCSession(){
|
||||
return session->getCSession();
|
||||
}
|
||||
Channel (Session &session, ssh_channel c_channel){
|
||||
this->channel=c_channel;
|
||||
this->session=&session;
|
||||
}
|
||||
Session *session;
|
||||
ssh_channel channel;
|
||||
/* No copy and no = operator */
|
||||
Channel(const Channel &);
|
||||
Channel &operator=(const Channel &);
|
||||
};
|
||||
|
||||
|
||||
/* This code cannot be put inline due to references to Channel */
|
||||
Channel *Session::acceptForward(int timeout_ms){
|
||||
ssh_channel forward = ssh_forward_accept(c_session,
|
||||
timeout_ms);
|
||||
ssh_throw_null(c_session,forward);
|
||||
Channel *newchan = new Channel(*this,forward);
|
||||
return newchan;
|
||||
}
|
||||
|
||||
} // namespace ssh
|
||||
|
||||
/** @} */
|
||||
#endif /* LIBSSHPP_HPP_ */
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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 MESSAGES_H_
|
||||
#define MESSAGES_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
struct ssh_auth_request {
|
||||
char *username;
|
||||
int method;
|
||||
char *password;
|
||||
struct ssh_public_key_struct *public_key;
|
||||
char signature_state;
|
||||
};
|
||||
|
||||
struct ssh_channel_request_open {
|
||||
int type;
|
||||
uint32_t sender;
|
||||
uint32_t window;
|
||||
uint32_t packet_size;
|
||||
char *originator;
|
||||
uint16_t originator_port;
|
||||
char *destination;
|
||||
uint16_t destination_port;
|
||||
};
|
||||
|
||||
struct ssh_service_request {
|
||||
char *service;
|
||||
};
|
||||
|
||||
struct ssh_global_request {
|
||||
int type;
|
||||
uint8_t want_reply;
|
||||
char *bind_address;
|
||||
uint16_t bind_port;
|
||||
};
|
||||
|
||||
struct ssh_channel_request {
|
||||
int type;
|
||||
ssh_channel channel;
|
||||
uint8_t want_reply;
|
||||
/* pty-req type specifics */
|
||||
char *TERM;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t pxwidth;
|
||||
uint32_t pxheight;
|
||||
ssh_string modes;
|
||||
|
||||
/* env type request */
|
||||
char *var_name;
|
||||
char *var_value;
|
||||
/* exec type request */
|
||||
char *command;
|
||||
/* subsystem */
|
||||
char *subsystem;
|
||||
};
|
||||
|
||||
struct ssh_message_struct {
|
||||
ssh_session session;
|
||||
int type;
|
||||
struct ssh_auth_request auth_request;
|
||||
struct ssh_channel_request_open channel_request_open;
|
||||
struct ssh_channel_request channel_request;
|
||||
struct ssh_service_request service_request;
|
||||
struct ssh_global_request global_request;
|
||||
};
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_open);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_service_request);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_request);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_global_request);
|
||||
|
||||
int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet,
|
||||
const char *request, uint8_t want_reply);
|
||||
void ssh_message_queue(ssh_session session, ssh_message message);
|
||||
ssh_message ssh_message_pop_head(ssh_session session);
|
||||
|
||||
#endif /* MESSAGES_H_ */
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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 MISC_H_
|
||||
#define MISC_H_
|
||||
|
||||
/* in misc.c */
|
||||
/* gets the user home dir. */
|
||||
char *ssh_get_user_home_dir(void);
|
||||
char *ssh_get_local_username(ssh_session session);
|
||||
int ssh_file_readaccess_ok(const char *file);
|
||||
|
||||
char *ssh_path_expand_tilde(const char *d);
|
||||
char *ssh_path_expand_escape(ssh_session session, const char *s);
|
||||
int ssh_analyze_banner(ssh_session session, int server, int *ssh1, int *ssh2);
|
||||
int ssh_is_ipaddr_v4(const char *str);
|
||||
int ssh_is_ipaddr(const char *str);
|
||||
|
||||
/* macro for byte ordering */
|
||||
uint64_t ntohll(uint64_t);
|
||||
#define htonll(x) ntohll(x)
|
||||
|
||||
/* list processing */
|
||||
|
||||
struct ssh_list {
|
||||
struct ssh_iterator *root;
|
||||
struct ssh_iterator *end;
|
||||
};
|
||||
|
||||
struct ssh_iterator {
|
||||
struct ssh_iterator *next;
|
||||
const void *data;
|
||||
};
|
||||
|
||||
struct ssh_timestamp {
|
||||
long seconds;
|
||||
long useconds;
|
||||
};
|
||||
|
||||
struct ssh_list *ssh_list_new(void);
|
||||
void ssh_list_free(struct ssh_list *list);
|
||||
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
|
||||
int ssh_list_append(struct ssh_list *list, const void *data);
|
||||
int ssh_list_prepend(struct ssh_list *list, const void *data);
|
||||
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator);
|
||||
char *ssh_lowercase(const char* str);
|
||||
char *ssh_hostport(const char *host, int port);
|
||||
|
||||
const void *_ssh_list_pop_head(struct ssh_list *list);
|
||||
|
||||
#define ssh_iterator_value(type, iterator)\
|
||||
((type)((iterator)->data))
|
||||
|
||||
/** @brief fetch the head element of a list and remove it from list
|
||||
* @param type type of the element to return
|
||||
* @param list the ssh_list to use
|
||||
* @return the first element of the list, or NULL if the list is empty
|
||||
*/
|
||||
#define ssh_list_pop_head(type, ssh_list)\
|
||||
((type)_ssh_list_pop_head(ssh_list))
|
||||
|
||||
void ssh_timestamp_init(struct ssh_timestamp *ts);
|
||||
int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout);
|
||||
int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
|
||||
|
||||
#endif /* MISC_H_ */
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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 PACKET_H_
|
||||
#define PACKET_H_
|
||||
|
||||
/* this structure should go someday */
|
||||
typedef struct packet_struct {
|
||||
int valid;
|
||||
uint32_t len;
|
||||
uint8_t type;
|
||||
} PACKET;
|
||||
|
||||
/** different state of packet reading. */
|
||||
enum ssh_packet_state_e {
|
||||
/** Packet not initialized, must read the size of packet */
|
||||
PACKET_STATE_INIT,
|
||||
/** Size was read, waiting for the rest of data */
|
||||
PACKET_STATE_SIZEREAD,
|
||||
/** Full packet was read and callbacks are being called. Future packets
|
||||
* should wait for the end of the callback. */
|
||||
PACKET_STATE_PROCESSING
|
||||
};
|
||||
|
||||
int packet_send(ssh_session session);
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
int packet_send1(ssh_session session) ;
|
||||
void ssh_packet_set_default_callbacks1(ssh_session session);
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_disconnect1);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_smsg_success1);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_smsg_failure1);
|
||||
int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user);
|
||||
|
||||
#endif
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_unimplemented);
|
||||
int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum);
|
||||
int ssh_packet_parse_type(ssh_session session);
|
||||
//int packet_flush(ssh_session session, int enforce_blocking);
|
||||
|
||||
|
||||
#endif /* PACKET_H_ */
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef PCAP_H_
|
||||
#define PCAP_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/libssh.h"
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
typedef struct ssh_pcap_context_struct* ssh_pcap_context;
|
||||
|
||||
int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len);
|
||||
|
||||
ssh_pcap_context ssh_pcap_context_new(ssh_session session);
|
||||
void ssh_pcap_context_free(ssh_pcap_context ctx);
|
||||
|
||||
enum ssh_pcap_direction{
|
||||
SSH_PCAP_DIR_IN,
|
||||
SSH_PCAP_DIR_OUT
|
||||
};
|
||||
void ssh_pcap_context_set_file(ssh_pcap_context, ssh_pcap_file);
|
||||
int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, void *data,
|
||||
uint32_t len, uint32_t origlen);
|
||||
|
||||
|
||||
#endif /* WITH_PCAP */
|
||||
#endif /* PCAP_H_ */
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 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 PKI_H_
|
||||
#define PKI_H_
|
||||
|
||||
#define SSH_KEY_FLAG_EMPTY 0
|
||||
#define SSH_KEY_FLAG_PUBLIC 1
|
||||
#define SSH_KEY_FLAG_PRIVATE 2
|
||||
|
||||
struct ssh_key_struct {
|
||||
enum ssh_keytypes_e type;
|
||||
int flags;
|
||||
const char *type_c; /* Don't free it ! it is static */
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa;
|
||||
gcry_sexp_t rsa;
|
||||
#elif HAVE_LIBCRYPTO
|
||||
DSA *dsa;
|
||||
RSA *rsa;
|
||||
#endif
|
||||
};
|
||||
|
||||
ssh_key ssh_key_new (void);
|
||||
void ssh_key_clean (ssh_key key);
|
||||
enum ssh_keytypes_e ssh_key_type(ssh_key key);
|
||||
int ssh_key_import_private(ssh_key key, ssh_session session,
|
||||
const char *filename, const char *passphrase);
|
||||
void ssh_key_free (ssh_key key);
|
||||
|
||||
#endif /* PKI_H_ */
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* 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 POLL_H_
|
||||
#define POLL_H_
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
|
||||
#include <poll.h>
|
||||
typedef struct pollfd ssh_pollfd_t;
|
||||
|
||||
#else /* HAVE_POLL */
|
||||
|
||||
/* poll emulation support */
|
||||
|
||||
typedef struct ssh_pollfd_struct {
|
||||
socket_t fd; /* file descriptor */
|
||||
short events; /* requested events */
|
||||
short revents; /* returned events */
|
||||
} ssh_pollfd_t;
|
||||
|
||||
typedef unsigned long int nfds_t;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef POLLRDNORM
|
||||
#define POLLRDNORM 0x0100
|
||||
#endif
|
||||
#ifndef POLLRDBAND
|
||||
#define POLLRDBAND 0x0200
|
||||
#endif
|
||||
#ifndef POLLIN
|
||||
#define POLLIN (POLLRDNORM | POLLRDBAND)
|
||||
#endif
|
||||
#ifndef POLLPRI
|
||||
#define POLLPRI 0x0400
|
||||
#endif
|
||||
|
||||
#ifndef POLLWRNORM
|
||||
#define POLLWRNORM 0x0010
|
||||
#endif
|
||||
#ifndef POLLOUT
|
||||
#define POLLOUT (POLLWRNORM)
|
||||
#endif
|
||||
#ifndef POLLWRBAND
|
||||
#define POLLWRBAND 0x0020
|
||||
#endif
|
||||
|
||||
#ifndef POLLERR
|
||||
#define POLLERR 0x0001
|
||||
#endif
|
||||
#ifndef POLLHUP
|
||||
#define POLLHUP 0x0002
|
||||
#endif
|
||||
#ifndef POLLNVAL
|
||||
#define POLLNVAL 0x0004
|
||||
#endif
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
/* poll.c */
|
||||
#ifndef POLLIN
|
||||
#define POLLIN 0x001 /* There is data to read. */
|
||||
#endif
|
||||
#ifndef POLLPRI
|
||||
#define POLLPRI 0x002 /* There is urgent data to read. */
|
||||
#endif
|
||||
#ifndef POLLOUT
|
||||
#define POLLOUT 0x004 /* Writing now will not block. */
|
||||
#endif
|
||||
|
||||
#ifndef POLLERR
|
||||
#define POLLERR 0x008 /* Error condition. */
|
||||
#endif
|
||||
#ifndef POLLHUP
|
||||
#define POLLHUP 0x010 /* Hung up. */
|
||||
#endif
|
||||
#ifndef POLLNVAL
|
||||
#define POLLNVAL 0x020 /* Invalid polling request. */
|
||||
#endif
|
||||
|
||||
#ifndef POLLRDNORM
|
||||
#define POLLRDNORM 0x040 /* mapped to read fds_set */
|
||||
#endif
|
||||
#ifndef POLLRDBAND
|
||||
#define POLLRDBAND 0x080 /* mapped to exception fds_set */
|
||||
#endif
|
||||
#ifndef POLLWRNORM
|
||||
#define POLLWRNORM 0x100 /* mapped to write fds_set */
|
||||
#endif
|
||||
#ifndef POLLWRBAND
|
||||
#define POLLWRBAND 0x200 /* mapped to write fds_set */
|
||||
#endif
|
||||
|
||||
#endif /* WIN32 */
|
||||
#endif /* HAVE_POLL */
|
||||
|
||||
void ssh_poll_init(void);
|
||||
void ssh_poll_cleanup(void);
|
||||
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout);
|
||||
typedef struct ssh_poll_ctx_struct *ssh_poll_ctx;
|
||||
typedef struct ssh_poll_handle_struct *ssh_poll_handle;
|
||||
|
||||
/**
|
||||
* @brief SSH poll callback. This callback will be used when an event
|
||||
* caught on the socket.
|
||||
*
|
||||
* @param p Poll object this callback belongs to.
|
||||
* @param fd The raw socket.
|
||||
* @param revents The current poll events on the socket.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*
|
||||
* @return 0 on success, < 0 if you removed the poll object from
|
||||
* its poll context.
|
||||
*/
|
||||
typedef int (*ssh_poll_callback)(ssh_poll_handle p, socket_t fd, int revents,
|
||||
void *userdata);
|
||||
|
||||
|
||||
ssh_poll_handle ssh_poll_new(socket_t fd, short events, ssh_poll_callback cb,
|
||||
void *userdata);
|
||||
void ssh_poll_free(ssh_poll_handle p);
|
||||
ssh_poll_ctx ssh_poll_get_ctx(ssh_poll_handle p);
|
||||
short ssh_poll_get_events(ssh_poll_handle p);
|
||||
void ssh_poll_set_events(ssh_poll_handle p, short events);
|
||||
void ssh_poll_add_events(ssh_poll_handle p, short events);
|
||||
void ssh_poll_remove_events(ssh_poll_handle p, short events);
|
||||
socket_t ssh_poll_get_fd(ssh_poll_handle p);
|
||||
void ssh_poll_set_fd(ssh_poll_handle p, socket_t fd);
|
||||
void ssh_poll_set_callback(ssh_poll_handle p, ssh_poll_callback cb, void *userdata);
|
||||
ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size);
|
||||
void ssh_poll_ctx_free(ssh_poll_ctx ctx);
|
||||
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p);
|
||||
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s);
|
||||
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p);
|
||||
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout);
|
||||
ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session);
|
||||
|
||||
#endif /* POLL_H_ */
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-2009 by Aris Adamantiadis
|
||||
* Copyright (c) 2003-2008 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
|
||||
@@ -29,73 +29,14 @@
|
||||
|
||||
#ifndef _LIBSSH_PRIV_H
|
||||
#define _LIBSSH_PRIV_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* Imitate define of inttypes.h */
|
||||
# ifndef PRIdS
|
||||
# define PRIdS "Id"
|
||||
# endif
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# include <stdio.h>
|
||||
|
||||
/* On Microsoft compilers define inline to __inline on all others use inline */
|
||||
# undef inline
|
||||
# define inline __inline
|
||||
|
||||
# define strcasecmp _stricmp
|
||||
# define strncasecmp _strnicmp
|
||||
# define strtoull _strtoui64
|
||||
# define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r')
|
||||
|
||||
# define usleep(X) Sleep(((X)+1000)/1000)
|
||||
|
||||
# undef strtok_r
|
||||
# define strtok_r strtok_s
|
||||
|
||||
# if defined(HAVE__SNPRINTF_S)
|
||||
# undef snprintf
|
||||
# define snprintf(d, n, ...) _snprintf_s((d), (n), _TRUNCATE, __VA_ARGS__)
|
||||
# else /* HAVE__SNPRINTF_S */
|
||||
# if defined(HAVE__SNPRINTF)
|
||||
# undef snprintf
|
||||
# define snprintf _snprintf
|
||||
# else /* HAVE__SNPRINTF */
|
||||
# if !defined(HAVE_SNPRINTF)
|
||||
# error "no snprintf compatible function found"
|
||||
# endif /* HAVE_SNPRINTF */
|
||||
# endif /* HAVE__SNPRINTF */
|
||||
# endif /* HAVE__SNPRINTF_S */
|
||||
|
||||
# if defined(HAVE__VSNPRINTF_S)
|
||||
# undef vsnprintf
|
||||
# define vsnprintf(s, n, f, v) _vsnprintf_s((s), (n), _TRUNCATE, (f), (v))
|
||||
# else /* HAVE__VSNPRINTF_S */
|
||||
# if defined(HAVE__VSNPRINTF)
|
||||
# undef vsnprintf
|
||||
# define vsnprintf _vsnprintf
|
||||
# else
|
||||
# if !defined(HAVE_VSNPRINTF)
|
||||
# error "No vsnprintf compatible function found"
|
||||
# endif /* HAVE_VSNPRINTF */
|
||||
# endif /* HAVE__VSNPRINTF */
|
||||
# endif /* HAVE__VSNPRINTF_S */
|
||||
|
||||
# endif /* _MSC_VER */
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
#include <unistd.h>
|
||||
#define PRIdS "zd"
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/callbacks.h"
|
||||
#include "libssh/crypto.h"
|
||||
|
||||
/* Debugging constants */
|
||||
|
||||
/* Define this if you want to debug crypto systems */
|
||||
/* it's usefull when you are debugging the lib */
|
||||
/*#define DEBUG_CRYPTO */
|
||||
|
||||
/* some constants */
|
||||
#define MAX_PACKET_LEN 262144
|
||||
@@ -103,122 +44,695 @@
|
||||
#define CLIENTBANNER1 "SSH-1.5-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
|
||||
#define CLIENTBANNER2 "SSH-2.0-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
|
||||
#define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
|
||||
/* some types for public keys */
|
||||
#define TYPE_DSS 1
|
||||
#define TYPE_RSA 2
|
||||
#define TYPE_RSA1 3
|
||||
|
||||
/* profiling constants. Don't touch them unless you know what you do */
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
#define OPENSSL_BIGNUMS
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* wrapper things */
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#include <gcrypt.h>
|
||||
typedef gcry_md_hd_t SHACTX;
|
||||
typedef gcry_md_hd_t MD5CTX;
|
||||
typedef gcry_md_hd_t HMACCTX;
|
||||
#ifdef MD5_DIGEST_LEN
|
||||
#undef MD5_DIGEST_LEN
|
||||
#endif
|
||||
#define SHA_DIGEST_LEN 20
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#define EVP_MAX_MD_SIZE 36
|
||||
|
||||
typedef gcry_mpi_t bignum;
|
||||
|
||||
#define bignum_new() gcry_mpi_new(0)
|
||||
#define bignum_free(num) gcry_mpi_release(num)
|
||||
#define bignum_set_word(bn,n) gcry_mpi_set_ui(bn,n)
|
||||
#define bignum_bin2bn(bn,datalen,data) gcry_mpi_scan(data,GCRYMPI_FMT_USG,bn,datalen,NULL)
|
||||
#define bignum_bn2dec(num) my_gcry_bn2dec(num)
|
||||
#define bignum_dec2bn(num, data) my_gcry_dec2bn(data, num)
|
||||
#define bignum_bn2hex(num,data) gcry_mpi_aprint(GCRYMPI_FMT_HEX,data,NULL,num)
|
||||
#define bignum_hex2bn(num,datalen,data) gcry_mpi_scan(num,GCRYMPI_FMT_HEX,data,datalen,NULL)
|
||||
#define bignum_rand(num,bits) gcry_mpi_randomize(num,bits,GCRY_STRONG_RANDOM),gcry_mpi_set_bit(num,bits-1),gcry_mpi_set_bit(num,0)
|
||||
#define bignum_mod_exp(dest,generator,exp,modulo) gcry_mpi_powm(dest,generator,exp,modulo)
|
||||
#define bignum_num_bits(num) gcry_mpi_get_nbits(num)
|
||||
#define bignum_num_bytes(num) ((gcry_mpi_get_nbits(num)+7)/8)
|
||||
#define bignum_is_bit_set(num,bit) gcry_mpi_test_bit(num,bit)
|
||||
#define bignum_bn2bin(num,datalen,data) gcry_mpi_print(GCRYMPI_FMT_USG,data,datalen,NULL,num)
|
||||
#define bignum_cmp(num1,num2) gcry_mpi_cmp(num1,num2)
|
||||
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/hmac.h>
|
||||
typedef SHA_CTX* SHACTX;
|
||||
typedef MD5_CTX* MD5CTX;
|
||||
typedef HMAC_CTX* HMACCTX;
|
||||
#ifdef MD5_DIGEST_LEN
|
||||
#undef MD5_DIGEST_LEN
|
||||
#endif
|
||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
|
||||
|
||||
#endif /* OPENSSL_CRYPTO */
|
||||
#ifdef OPENSSL_BIGNUMS
|
||||
#include <openssl/bn.h>
|
||||
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)
|
||||
|
||||
#endif /* OPENSSL_BIGNUMS */
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* poll support */
|
||||
#ifdef HAVE_POLL
|
||||
#include <poll.h>
|
||||
typedef struct pollfd pollfd_t;
|
||||
#else /* HAVE_POLL */
|
||||
typedef struct pollfd_s {
|
||||
socket_t fd; /* file descriptor */
|
||||
short events; /* requested events */
|
||||
short revents; /* returned events */
|
||||
} pollfd_t;
|
||||
|
||||
#define POLLIN 0x001 /* There is data to read. */
|
||||
#define POLLPRI 0x002 /* There is urgent data to read. */
|
||||
#define POLLOUT 0x004 /* Writing now will not block. */
|
||||
|
||||
#define POLLERR 0x008 /* Error condition. */
|
||||
#define POLLHUP 0x010 /* Hung up. */
|
||||
#define POLLNVAL 0x020 /* Invalid polling request. */
|
||||
|
||||
typedef unsigned long int nfds_t;
|
||||
#endif /* HAVE_POLL */
|
||||
|
||||
/* wrapper.c */
|
||||
MD5CTX md5_init(void);
|
||||
void md5_update(MD5CTX c, const void *data, unsigned long len);
|
||||
void md5_final(unsigned char *md,MD5CTX c);
|
||||
SHACTX sha1_init(void);
|
||||
void sha1_update(SHACTX c, const void *data, unsigned long len);
|
||||
void sha1_final(unsigned char *md,SHACTX c);
|
||||
void sha1(unsigned char *digest,int len,unsigned char *hash);
|
||||
#define HMAC_SHA1 1
|
||||
#define HMAC_MD5 2
|
||||
HMACCTX hmac_init(const void *key,int len,int type);
|
||||
void hmac_update(HMACCTX c, const void *data, unsigned long len);
|
||||
void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
|
||||
|
||||
/* strings and buffers */
|
||||
/* must be 32 bits number + immediatly our data */
|
||||
struct string_struct {
|
||||
u32 size;
|
||||
unsigned char string[MAX_PACKET_LEN];
|
||||
}
|
||||
#if !defined(__SUNPRO_C)
|
||||
__attribute__ ((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
/** Describes a buffer state at a moment
|
||||
*/
|
||||
struct buffer_struct {
|
||||
char *data;
|
||||
u32 used;
|
||||
u32 allocated;
|
||||
u32 pos;
|
||||
};
|
||||
|
||||
/* i should remove it one day */
|
||||
typedef struct packet_struct {
|
||||
int valid;
|
||||
u32 len;
|
||||
u8 type;
|
||||
} PACKET;
|
||||
|
||||
typedef struct kex_struct {
|
||||
unsigned char cookie[16];
|
||||
char **methods;
|
||||
} KEX;
|
||||
|
||||
struct public_key_struct {
|
||||
int type;
|
||||
const char *type_c; /* Don't free it ! it is static */
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa_pub;
|
||||
gcry_sexp_t rsa_pub;
|
||||
#elif HAVE_LIBCRYPTO
|
||||
DSA *dsa_pub;
|
||||
RSA *rsa_pub;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct private_key_struct {
|
||||
int type;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa_priv;
|
||||
gcry_sexp_t rsa_priv;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
DSA *dsa_priv;
|
||||
RSA *rsa_priv;
|
||||
#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;
|
||||
STRING *rsa_sign;
|
||||
#endif
|
||||
} SIGNATURE;
|
||||
|
||||
|
||||
struct error_struct {
|
||||
/* error handling */
|
||||
int error_code;
|
||||
char error_buffer[ERROR_BUFFERLEN];
|
||||
};
|
||||
|
||||
/* TODO: remove that include */
|
||||
#include "libssh/wrapper.h"
|
||||
struct ssh_options_struct {
|
||||
struct error_struct error;
|
||||
char *banner; /* explicit banner to send */
|
||||
char *username;
|
||||
char *host;
|
||||
char *bindaddr;
|
||||
int bindport;
|
||||
char *identity;
|
||||
char *ssh_dir;
|
||||
char *known_hosts_file;
|
||||
socket_t fd; /* specificaly wanted file descriptor, don't connect host */
|
||||
int port;
|
||||
int dont_verify_hostkey; /* Don't spare time, don't check host key ! unneeded to say it's dangerous and not safe */
|
||||
int use_nonexisting_algo; /* if user sets a not supported algorithm for kex, don't complain */
|
||||
char *wanted_methods[10]; /* the kex methods can be choosed. better use the kex fonctions to do that */
|
||||
void *wanted_cookie; /* wants a specific cookie to be sent ? if null, generate a new one */
|
||||
ssh_auth_callback auth_function; /* this functions will be called if e.g. a keyphrase is needed. */
|
||||
void *auth_userdata;
|
||||
void (*connect_status_function)(void *arg, float status); /* status callback function */
|
||||
void *connect_status_arg; /* arbitrary argument */
|
||||
long timeout; /* seconds */
|
||||
long timeout_usec;
|
||||
int ssh2allowed;
|
||||
int ssh1allowed;
|
||||
char *dsakey;
|
||||
char *rsakey; /* host key for server implementation */
|
||||
int log_verbosity;
|
||||
void (*log_function)(const char *message, SSH_SESSION *session, int verbosity); //log callback
|
||||
};
|
||||
|
||||
struct ssh_keys_struct {
|
||||
typedef struct ssh_crypto_struct {
|
||||
bignum e,f,x,k,y;
|
||||
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 */
|
||||
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 */
|
||||
void *compress_out_ctx; /* don't touch it */
|
||||
void *compress_in_ctx; /* really, don't */
|
||||
} CRYPTO;
|
||||
|
||||
struct channel_struct {
|
||||
struct channel_struct *prev;
|
||||
struct channel_struct *next;
|
||||
SSH_SESSION *session; /* SSH_SESSION pointer */
|
||||
u32 local_channel;
|
||||
u32 local_window;
|
||||
int local_eof;
|
||||
u32 local_maxpacket;
|
||||
|
||||
u32 remote_channel;
|
||||
u32 remote_window;
|
||||
int remote_eof; /* end of file received */
|
||||
u32 remote_maxpacket;
|
||||
int open; /* shows if the channel is still opened */
|
||||
int delayed_close;
|
||||
BUFFER *stdout_buffer;
|
||||
BUFFER *stderr_buffer;
|
||||
void *userarg;
|
||||
int version;
|
||||
int blocking;
|
||||
int exit_status;
|
||||
};
|
||||
|
||||
struct agent_struct {
|
||||
struct socket *sock;
|
||||
BUFFER *ident;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
struct keys_struct {
|
||||
const char *privatekey;
|
||||
const char *publickey;
|
||||
};
|
||||
|
||||
struct ssh_message_struct;
|
||||
struct ssh_session {
|
||||
struct error_struct error;
|
||||
struct socket *socket;
|
||||
SSH_OPTIONS *options;
|
||||
char *serverbanner;
|
||||
char *clientbanner;
|
||||
int protoversion;
|
||||
int server;
|
||||
int client;
|
||||
int openssh;
|
||||
u32 send_seq;
|
||||
u32 recv_seq;
|
||||
/* status flags */
|
||||
int closed;
|
||||
int closed_by_except;
|
||||
|
||||
int connected;
|
||||
/* !=0 when the user got a session handle */
|
||||
int alive;
|
||||
/* two previous are deprecated */
|
||||
int auth_service_asked;
|
||||
|
||||
/* socket status */
|
||||
int blocking; // functions should block
|
||||
|
||||
STRING *banner; /* that's the issue banner from
|
||||
the server */
|
||||
char *remotebanner; /* that's the SSH- banner from
|
||||
remote host. */
|
||||
char *discon_msg; /* disconnect message from
|
||||
the remote host */
|
||||
BUFFER *in_buffer;
|
||||
PACKET in_packet;
|
||||
BUFFER *out_buffer;
|
||||
|
||||
/* the states are used by the nonblocking stuff to remember */
|
||||
/* where it was before being interrupted */
|
||||
int packet_state;
|
||||
int dh_handshake_state;
|
||||
STRING *dh_server_signature; //information used by dh_handshake.
|
||||
|
||||
KEX server_kex;
|
||||
KEX client_kex;
|
||||
BUFFER *in_hashbuf;
|
||||
BUFFER *out_hashbuf;
|
||||
CRYPTO *current_crypto;
|
||||
CRYPTO *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
|
||||
|
||||
CHANNEL *channels; /* linked list of channels */
|
||||
int maxchannel;
|
||||
int exec_channel_opened; /* version 1 only. more
|
||||
info in channels1.c */
|
||||
AGENT *agent; /* ssh agent */
|
||||
|
||||
/* keyb interactive data */
|
||||
struct ssh_kbdint *kbdint;
|
||||
int version; /* 1 or 2 */
|
||||
/* server host keys */
|
||||
PRIVATE_KEY *rsa_key;
|
||||
PRIVATE_KEY *dsa_key;
|
||||
/* auths accepted by server */
|
||||
int auth_methods;
|
||||
int hostkeys; /* contains type of host key wanted by client, in server impl */
|
||||
struct ssh_message *ssh_message; /* ssh message */
|
||||
int log_verbosity; /*cached copy of the option structure */
|
||||
int log_indent; /* indentation level in enter_function logs */
|
||||
};
|
||||
|
||||
struct ssh_kbdint {
|
||||
u32 nprompts;
|
||||
char *name;
|
||||
char *instruction;
|
||||
char **prompts;
|
||||
unsigned char *echo; /* bool array */
|
||||
char **answers;
|
||||
};
|
||||
|
||||
/* server data */
|
||||
|
||||
struct ssh_bind_struct {
|
||||
struct error_struct error;
|
||||
socket_t bindfd;
|
||||
SSH_OPTIONS *options;
|
||||
int blocking;
|
||||
int toaccept;
|
||||
};
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_ignore_callback);
|
||||
struct ssh_auth_request {
|
||||
char *username;
|
||||
int method;
|
||||
char *password;
|
||||
};
|
||||
|
||||
struct ssh_channel_request_open {
|
||||
int type;
|
||||
u32 sender;
|
||||
u32 window;
|
||||
u32 packet_size;
|
||||
char *originator;
|
||||
u16 orignator_port;
|
||||
char *destination;
|
||||
u16 destination_port;
|
||||
};
|
||||
|
||||
struct ssh_channel_request {
|
||||
int type;
|
||||
CHANNEL *channel;
|
||||
u8 want_reply;
|
||||
/* pty-req type specifics */
|
||||
char *TERM;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 pxwidth;
|
||||
u32 pxheight;
|
||||
STRING *modes;
|
||||
|
||||
/* env type request */
|
||||
char *var_name;
|
||||
char *var_value;
|
||||
/* exec type request */
|
||||
char *command;
|
||||
/* subsystem */
|
||||
char *subsystem;
|
||||
};
|
||||
|
||||
struct ssh_message {
|
||||
SSH_SESSION *session;
|
||||
int type;
|
||||
struct ssh_auth_request auth_request;
|
||||
struct ssh_channel_request_open channel_request_open;
|
||||
struct ssh_channel_request channel_request;
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
/* agent.c */
|
||||
/**
|
||||
* @brief Create a new ssh agent structure.
|
||||
*
|
||||
* @return An allocated ssh agent structure or NULL on error.
|
||||
*/
|
||||
struct agent_struct *agent_new(struct ssh_session *session);
|
||||
|
||||
void agent_close(struct agent_struct *agent);
|
||||
|
||||
/**
|
||||
* @brief Free an allocated ssh agent structure.
|
||||
*
|
||||
* @param agent The ssh agent structure to free.
|
||||
*/
|
||||
void agent_free(struct agent_struct *agent);
|
||||
|
||||
/**
|
||||
* @brief Check if the ssh agent is running.
|
||||
*
|
||||
* @param session The ssh session to check for the agent.
|
||||
*
|
||||
* @return 1 if it is running, 0 if not.
|
||||
*/
|
||||
int agent_is_running(struct ssh_session *session);
|
||||
|
||||
int agent_get_ident_count(struct ssh_session *session);
|
||||
|
||||
struct public_key_struct *agent_get_next_ident(struct ssh_session *session,
|
||||
char **comment);
|
||||
|
||||
struct public_key_struct *agent_get_first_ident(struct ssh_session *session,
|
||||
char **comment);
|
||||
|
||||
STRING *agent_sign_data(struct ssh_session *session,
|
||||
struct buffer_struct *data,
|
||||
struct public_key_struct *pubkey);
|
||||
#endif
|
||||
|
||||
/* poll.c */
|
||||
int ssh_poll(pollfd_t *fds, nfds_t nfds, int timeout);
|
||||
|
||||
/* socket.c */
|
||||
|
||||
struct socket;
|
||||
int ssh_socket_init(void);
|
||||
struct socket *ssh_socket_new(SSH_SESSION *session);
|
||||
void ssh_socket_free(struct socket *s);
|
||||
void ssh_socket_set_fd(struct socket *s, socket_t fd);
|
||||
socket_t ssh_socket_get_fd(struct socket *s);
|
||||
#ifndef _WIN32
|
||||
int ssh_socket_unix(struct socket *s, const char *path);
|
||||
#endif
|
||||
void ssh_socket_close(struct socket *s);
|
||||
int ssh_socket_read(struct socket *s, void *buffer, int len);
|
||||
int ssh_socket_write(struct socket *s,const void *buffer, int len);
|
||||
int ssh_socket_is_open(struct socket *s);
|
||||
int ssh_socket_fd_isset(struct socket *s, fd_set *set);
|
||||
void ssh_socket_fd_set(struct socket *s, fd_set *set, int *fd_max);
|
||||
int ssh_socket_completeread(struct socket *s, void *buffer, u32 len);
|
||||
int ssh_socket_completewrite(struct socket *s, const void *buffer, u32 len);
|
||||
int ssh_socket_wait_for_data(struct socket *s, SSH_SESSION *session, u32 len);
|
||||
int ssh_socket_nonblocking_flush(struct socket *s);
|
||||
int ssh_socket_blocking_flush(struct socket *s);
|
||||
int ssh_socket_poll(struct socket *s, int *writeable, int *except);
|
||||
void ssh_socket_set_towrite(struct socket *s);
|
||||
void ssh_socket_set_toread(struct socket *s);
|
||||
void ssh_socket_set_except(struct socket *s);
|
||||
int ssh_socket_get_status(struct socket *s);
|
||||
int ssh_socket_data_available(struct socket *s);
|
||||
int ssh_socket_data_writable(struct socket *s);
|
||||
/* session.c */
|
||||
|
||||
void ssh_cleanup(SSH_SESSION *session);
|
||||
|
||||
/* client.c */
|
||||
|
||||
int ssh_send_banner(ssh_session session, int is_server);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_dh_reply);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_newkeys);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_service_accept);
|
||||
|
||||
/* config.c */
|
||||
int ssh_config_parse_file(ssh_session session, const char *filename);
|
||||
int ssh_send_banner(SSH_SESSION *session, int is_server);
|
||||
char *ssh_get_banner(SSH_SESSION *session);
|
||||
|
||||
/* errors.c */
|
||||
void ssh_set_error(void *error, int code, const char *descr, ...) PRINTF_ATTRIBUTE(3, 4);
|
||||
void ssh_set_error_oom(void *);
|
||||
void ssh_set_error_invalid(void *, const char *);
|
||||
|
||||
/* in dh.c */
|
||||
/* DH key generation */
|
||||
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);
|
||||
int dh_generate_y(SSH_SESSION *session);
|
||||
|
||||
int ssh_crypto_init(void);
|
||||
void ssh_crypto_finalize(void);
|
||||
|
||||
STRING *dh_get_e(SSH_SESSION *session);
|
||||
STRING *dh_get_f(SSH_SESSION *session);
|
||||
int dh_import_f(SSH_SESSION *session,STRING *f_string);
|
||||
int dh_import_e(SSH_SESSION *session, STRING *e_string);
|
||||
void dh_import_pubkey(SSH_SESSION *session,STRING *pubkey_string);
|
||||
int dh_build_k(SSH_SESSION *session);
|
||||
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);
|
||||
/* returns 1 if server signature ok, 0 otherwise. The NEXT crypto is checked, not the current one */
|
||||
int signature_verify(SSH_SESSION *session,STRING *signature);
|
||||
bignum make_string_bn(STRING *string);
|
||||
STRING *make_bignum_string(bignum num);
|
||||
|
||||
/* in crypt.c */
|
||||
uint32_t packet_decrypt_len(ssh_session session,char *crypted);
|
||||
int packet_decrypt(ssh_session session, void *packet,unsigned int len);
|
||||
unsigned char *packet_encrypt(ssh_session session,void *packet,unsigned int len);
|
||||
u32 packet_decrypt_len(SSH_SESSION *session,char *crypted);
|
||||
int packet_decrypt(SSH_SESSION *session, void *packet,unsigned int len);
|
||||
unsigned char *packet_encrypt(SSH_SESSION *session,void *packet,unsigned int len);
|
||||
/* it returns the hmac buffer if exists*/
|
||||
struct ssh_poll_handle_struct;
|
||||
int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,unsigned char *mac);
|
||||
|
||||
int packet_hmac_verify(ssh_session session,ssh_buffer buffer,unsigned char *mac);
|
||||
/* in packet.c */
|
||||
|
||||
struct ssh_socket_struct;
|
||||
void packet_parse(SSH_SESSION *session);
|
||||
int packet_send(SSH_SESSION *session);
|
||||
|
||||
int ssh_packet_socket_callback(const void *data, size_t len, void *user);
|
||||
void ssh_packet_register_socket_callback(ssh_session session, struct ssh_socket_struct *s);
|
||||
void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks);
|
||||
void ssh_packet_set_default_callbacks(ssh_session session);
|
||||
void ssh_packet_process(ssh_session session, uint8_t type);
|
||||
int packet_read(SSH_SESSION *session);
|
||||
int packet_translate(SSH_SESSION *session);
|
||||
int packet_wait(SSH_SESSION *session,int type,int blocking);
|
||||
int packet_flush(SSH_SESSION *session, int enforce_blocking);
|
||||
/* connect.c */
|
||||
socket_t ssh_connect_host(ssh_session session, const char *host,const char
|
||||
SSH_SESSION *ssh_session_new();
|
||||
socket_t ssh_connect_host(SSH_SESSION *session, const char *host,const char
|
||||
*bind_addr, int port, long timeout, long usec);
|
||||
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
const char *bind_addr, int port);
|
||||
void ssh_sock_set_nonblocking(socket_t sock);
|
||||
void ssh_sock_set_blocking(socket_t sock);
|
||||
|
||||
/* in kex.c */
|
||||
extern const char *ssh_kex_nums[];
|
||||
int ssh_send_kex(ssh_session session, int server_kex);
|
||||
void ssh_list_kex(ssh_session session, KEX *kex);
|
||||
int set_kex(ssh_session session);
|
||||
int ssh_send_kex(SSH_SESSION *session, int server_kex);
|
||||
void ssh_list_kex(SSH_SESSION *session, KEX *kex);
|
||||
int set_kex(SSH_SESSION *session);
|
||||
int ssh_get_kex(SSH_SESSION *session, int server_kex);
|
||||
int verify_existing_algo(int algo, const char *name);
|
||||
char **space_tokenize(const char *chain);
|
||||
int ssh_get_kex1(ssh_session session);
|
||||
int ssh_get_kex1(SSH_SESSION *session);
|
||||
char *ssh_find_matching(const char *in_d, const char *what_d);
|
||||
|
||||
/* in keyfiles.c */
|
||||
|
||||
PRIVATE_KEY *_privatekey_from_file(void *session, const char *filename,
|
||||
int type);
|
||||
STRING *try_publickey_from_file(SSH_SESSION *session,
|
||||
struct keys_struct keytab,
|
||||
char **privkeyfile, int *type);
|
||||
|
||||
/* in keys.c */
|
||||
const char *ssh_type_to_char(int type);
|
||||
int ssh_type_from_name(const char *name);
|
||||
|
||||
PRIVATE_KEY *privatekey_make_dss(SSH_SESSION *session, BUFFER *buffer);
|
||||
PRIVATE_KEY *privatekey_make_rsa(SSH_SESSION *session, BUFFER *buffer,
|
||||
const char *type);
|
||||
PRIVATE_KEY *privatekey_from_string(SSH_SESSION *session, STRING *privkey_s);
|
||||
|
||||
PUBLIC_KEY *publickey_make_dss(SSH_SESSION *session, BUFFER *buffer);
|
||||
PUBLIC_KEY *publickey_make_rsa(SSH_SESSION *session, BUFFER *buffer, int type);
|
||||
PUBLIC_KEY *publickey_from_string(SSH_SESSION *session, STRING *pubkey_s);
|
||||
SIGNATURE *signature_from_string(SSH_SESSION *session, STRING *signature,PUBLIC_KEY *pubkey,int needed_type);
|
||||
void signature_free(SIGNATURE *sign);
|
||||
STRING *ssh_do_sign_with_agent(struct ssh_session *session,
|
||||
struct buffer_struct *buf, struct public_key_struct *publickey);
|
||||
STRING *ssh_do_sign(SSH_SESSION *session,BUFFER *sigbuf,
|
||||
PRIVATE_KEY *privatekey);
|
||||
STRING *ssh_sign_session_id(SSH_SESSION *session, PRIVATE_KEY *privatekey);
|
||||
STRING *ssh_encrypt_rsa1(SSH_SESSION *session, STRING *data, PUBLIC_KEY *key);
|
||||
/* channel.c */
|
||||
void channel_handle(SSH_SESSION *session, int type);
|
||||
CHANNEL *channel_new(SSH_SESSION *session);
|
||||
int channel_default_bufferize(CHANNEL *channel, void *data, int len,
|
||||
int is_stderr);
|
||||
u32 ssh_channel_new_id(SSH_SESSION *session);
|
||||
CHANNEL *ssh_channel_from_local(SSH_SESSION *session, u32 id);
|
||||
|
||||
/* options.c */
|
||||
|
||||
/* this function must be called when no specific username has been asked. it has to guess it */
|
||||
int ssh_options_default_username(SSH_OPTIONS *opt);
|
||||
int ssh_options_default_ssh_dir(SSH_OPTIONS *opt);
|
||||
int ssh_options_default_known_hosts_file(SSH_OPTIONS *opt);
|
||||
|
||||
/* buffer.c */
|
||||
int buffer_add_ssh_string(BUFFER *buffer, STRING *string);
|
||||
int buffer_add_u8(BUFFER *buffer, u8 data);
|
||||
int buffer_add_u32(BUFFER *buffer, u32 data);
|
||||
int buffer_add_u64(BUFFER *buffer, u64 data);
|
||||
int buffer_add_data(BUFFER *buffer, const void *data, u32 len);
|
||||
int buffer_prepend_data(BUFFER *buffer, const void *data, u32 len);
|
||||
int buffer_add_buffer(BUFFER *buffer, BUFFER *source);
|
||||
int buffer_reinit(BUFFER *buffer);
|
||||
|
||||
/* buffer_get_rest returns a pointer to the current position into the buffer */
|
||||
void *buffer_get_rest(BUFFER *buffer);
|
||||
/* buffer_get_rest_len returns the number of bytes which can be read */
|
||||
u32 buffer_get_rest_len(BUFFER *buffer);
|
||||
|
||||
/* buffer_read_*() returns the number of bytes read, except for ssh strings */
|
||||
int buffer_get_u8(BUFFER *buffer, u8 *data);
|
||||
int buffer_get_u32(BUFFER *buffer, u32 *data);
|
||||
int buffer_get_u64(BUFFER *buffer, u64 *data);
|
||||
|
||||
u32 buffer_get_data(BUFFER *buffer, void *data, u32 requestedlen);
|
||||
/* buffer_get_ssh_string() is an exception. if the String read is too large or invalid, it will answer NULL. */
|
||||
STRING *buffer_get_ssh_string(BUFFER *buffer);
|
||||
/* gets a string out of a SSH-1 mpint */
|
||||
STRING *buffer_get_mpint(BUFFER *buffer);
|
||||
/* buffer_pass_bytes acts as if len bytes have been read (used for padding) */
|
||||
u32 buffer_pass_bytes_end(BUFFER *buffer, u32 len);
|
||||
u32 buffer_pass_bytes(BUFFER *buffer, u32 len);
|
||||
|
||||
/* in base64.c */
|
||||
ssh_buffer base64_to_bin(const char *source);
|
||||
BUFFER *base64_to_bin(const char *source);
|
||||
unsigned char *bin_to_base64(const unsigned char *source, int len);
|
||||
|
||||
/* gzip.c */
|
||||
int compress_buffer(ssh_session session,ssh_buffer buf);
|
||||
int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
|
||||
int compress_buffer(SSH_SESSION *session,BUFFER *buf);
|
||||
int decompress_buffer(SSH_SESSION *session,BUFFER *buf);
|
||||
|
||||
/* wrapper.c */
|
||||
int crypt_set_algorithms(SSH_SESSION *);
|
||||
int crypt_set_algorithms_server(SSH_SESSION *session);
|
||||
CRYPTO *crypto_new(void);
|
||||
void crypto_free(CRYPTO *crypto);
|
||||
|
||||
/* crc32.c */
|
||||
uint32_t ssh_crc32(const char *buf, uint32_t len);
|
||||
u32 ssh_crc32(const char *buf, u32 len);
|
||||
|
||||
/* 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, STRING *pubkey);
|
||||
int ssh_userauth1_password(SSH_SESSION *session, const char *username,
|
||||
const char *password);
|
||||
/* in misc.c */
|
||||
/* gets the user home dir. */
|
||||
char *ssh_get_user_home_dir(void);
|
||||
int ssh_file_readaccess_ok(const char *file);
|
||||
|
||||
/* macro for byte ordering */
|
||||
u64 ntohll(u64);
|
||||
#define htonll(x) ntohll(x)
|
||||
|
||||
/* channels1.c */
|
||||
int channel_open_session1(CHANNEL *channel);
|
||||
int channel_request_pty_size1(CHANNEL *channel, const char *terminal,
|
||||
int cols, int rows);
|
||||
int channel_change_pty_size1(CHANNEL *channel, int cols, int rows);
|
||||
int channel_request_shell1(CHANNEL *channel);
|
||||
int channel_request_exec1(CHANNEL *channel, const char *cmd);
|
||||
int channel_handle1(SSH_SESSION *session, int type);
|
||||
int channel_write1(CHANNEL *channel, const void *data, int len);
|
||||
|
||||
/* session.c */
|
||||
|
||||
int ssh_handle_packets(SSH_SESSION *session);
|
||||
|
||||
/* match.c */
|
||||
int match_hostname(const char *host, const char *pattern, unsigned int len);
|
||||
|
||||
int message_handle(ssh_session session, void *user, uint8_t type, ssh_buffer packet);
|
||||
/* log.c */
|
||||
|
||||
/* misc.c */
|
||||
#ifdef _WIN32
|
||||
int gettimeofday(struct timeval *__p, void *__t);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifndef __FUNCTION__
|
||||
#if defined(__SUNPRO_C)
|
||||
#define __FUNCTION__ __func__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#define _enter_function(sess) \
|
||||
do {\
|
||||
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \
|
||||
@@ -235,21 +749,8 @@ int gettimeofday(struct timeval *__p, void *__t);
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#ifdef DEBUG_CALLTRACE
|
||||
#define enter_function() _enter_function(session)
|
||||
#define leave_function() _leave_function(session)
|
||||
#else
|
||||
#define enter_function() (void)session
|
||||
#define leave_function() (void)session
|
||||
#endif
|
||||
|
||||
/* options.c */
|
||||
|
||||
int ssh_options_set_algo(ssh_session session, int algo, const char *list);
|
||||
int ssh_options_apply(ssh_session session);
|
||||
|
||||
/* server.c */
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init);
|
||||
|
||||
/** Free memory space */
|
||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-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 _SCP_H
|
||||
#define _SCP_H
|
||||
|
||||
enum ssh_scp_states {
|
||||
SSH_SCP_NEW, //Data structure just created
|
||||
SSH_SCP_WRITE_INITED, //Gave our intention to write
|
||||
SSH_SCP_WRITE_WRITING,//File was opened and currently writing
|
||||
SSH_SCP_READ_INITED, //Gave our intention to read
|
||||
SSH_SCP_READ_REQUESTED, //We got a read request
|
||||
SSH_SCP_READ_READING, //File is opened and reading
|
||||
SSH_SCP_ERROR, //Something bad happened
|
||||
SSH_SCP_TERMINATED //Transfer finished
|
||||
};
|
||||
|
||||
struct ssh_scp_struct {
|
||||
ssh_session session;
|
||||
int mode;
|
||||
int recursive;
|
||||
ssh_channel channel;
|
||||
char *location;
|
||||
enum ssh_scp_states state;
|
||||
size_t filelen;
|
||||
size_t processed;
|
||||
enum ssh_scp_request_types request_type;
|
||||
char *request_name;
|
||||
char *warning;
|
||||
int request_mode;
|
||||
};
|
||||
|
||||
int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len);
|
||||
int ssh_scp_integer_mode(const char *mode);
|
||||
char *ssh_scp_string_mode(int mode);
|
||||
int ssh_scp_response(ssh_scp scp, char **response);
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,3 @@
|
||||
/* Public include file for server support */
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
@@ -21,8 +20,8 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup libssh_server The libssh server API
|
||||
*
|
||||
* @defgroup ssh_server SSH Server
|
||||
* @addtogroup ssh_server
|
||||
* @{
|
||||
*/
|
||||
|
||||
@@ -36,275 +35,138 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum ssh_bind_options_e {
|
||||
SSH_BIND_OPTIONS_BINDADDR,
|
||||
SSH_BIND_OPTIONS_BINDPORT,
|
||||
SSH_BIND_OPTIONS_BINDPORT_STR,
|
||||
SSH_BIND_OPTIONS_HOSTKEY,
|
||||
SSH_BIND_OPTIONS_DSAKEY,
|
||||
SSH_BIND_OPTIONS_RSAKEY,
|
||||
SSH_BIND_OPTIONS_BANNER,
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY,
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
|
||||
};
|
||||
|
||||
typedef struct ssh_bind_struct* ssh_bind;
|
||||
|
||||
/* Callback functions */
|
||||
|
||||
/**
|
||||
* @brief Incoming connection callback. This callback is called when a ssh_bind
|
||||
* has a new incoming connection.
|
||||
* @param sshbind Current sshbind session handler
|
||||
* @param message the actual message
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_bind_incoming_connection_callback) (ssh_bind sshbind,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief These are the callbacks exported by the ssh_bind structure.
|
||||
*
|
||||
* They are called by the server module when events appear on the network.
|
||||
*/
|
||||
struct ssh_bind_callbacks_struct {
|
||||
/** DON'T SET THIS use ssh_callbacks_init() instead. */
|
||||
size_t size;
|
||||
/** A new connection is available. */
|
||||
ssh_bind_incoming_connection_callback incoming_connection;
|
||||
};
|
||||
typedef struct ssh_bind_callbacks_struct *ssh_bind_callbacks;
|
||||
typedef struct ssh_bind_struct SSH_BIND;
|
||||
|
||||
/**
|
||||
* @brief Creates a new SSH server bind.
|
||||
*
|
||||
* @return A newly allocated ssh_bind session pointer.
|
||||
*/
|
||||
LIBSSH_API ssh_bind ssh_bind_new(void);
|
||||
SSH_BIND *ssh_bind_new(void);
|
||||
|
||||
/**
|
||||
* @brief Set the options for the current SSH server bind.
|
||||
* @brief Set the opitons for the current SSH server bind.
|
||||
*
|
||||
* @param sshbind The ssh server bind to configure.
|
||||
* @param ssh_bind The ssh server bind to use.
|
||||
*
|
||||
* @param type The option type to set. This could be one of the
|
||||
* following:
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDADDR
|
||||
* The ip address to bind (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDPORT
|
||||
* The port to bind (unsigned int).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDPORT_STR
|
||||
* The port to bind (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_HOSTKEY
|
||||
* This specifies the file containing the private host key used
|
||||
* by SSHv1. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_DSAKEY
|
||||
* This specifies the file containing the private host dsa key
|
||||
* used by SSHv2. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_RSAKEY
|
||||
* This specifies the file containing the private host dsa key
|
||||
* used by SSHv2. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BANNER
|
||||
* That the server banner (version string) for SSH.
|
||||
* (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY
|
||||
* Set the session logging verbosity (int).\n
|
||||
* \n
|
||||
* The verbosity of the messages. Every log smaller or
|
||||
* equal to verbosity will be shown.
|
||||
* - SSH_LOG_NOLOG: No logging
|
||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* - SSH_LOG_PACKET: Packet id and size
|
||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
|
||||
* Set the session logging verbosity (const char *).\n
|
||||
* \n
|
||||
* The verbosity of the messages. Every log smaller or
|
||||
* equal to verbosity will be shown.
|
||||
* - SSH_LOG_NOLOG: No logging
|
||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* - SSH_LOG_PACKET: Packet id and size
|
||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
* \n
|
||||
* See the corresponding numbers in libssh.h.
|
||||
*
|
||||
* @param value The value to set. This is a generic pointer and the
|
||||
* datatype which is used should be set according to the
|
||||
* type set.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR on invalid option or parameter.
|
||||
* @param options The option structure to set.
|
||||
*/
|
||||
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
||||
enum ssh_bind_options_e type, const void *value);
|
||||
void ssh_bind_set_options(SSH_BIND *ssh_bind, SSH_OPTIONS *options);
|
||||
|
||||
/**
|
||||
* @brief Start listening to the socket.
|
||||
*
|
||||
* @param ssh_bind_o The ssh server bind to use.
|
||||
* @param ssh_bind The ssh server bind to use.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o);
|
||||
|
||||
/**
|
||||
* @brief Set the callback for this bind.
|
||||
*
|
||||
* @param[in] sshbind The bind to set the callback on.
|
||||
*
|
||||
* @param[in] callbacks An already set up ssh_bind_callbacks instance.
|
||||
*
|
||||
* @param[in] userdata A pointer to private data to pass to the callbacks.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR if an error occured.
|
||||
*
|
||||
* @code
|
||||
* struct ssh_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_function = my_auth_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_bind_set_callbacks(session, &cb);
|
||||
* @endcode
|
||||
*/
|
||||
LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
|
||||
void *userdata);
|
||||
int ssh_bind_listen(SSH_BIND *ssh_bind);
|
||||
|
||||
/**
|
||||
* @brief Set the session to blocking/nonblocking mode.
|
||||
*
|
||||
* @param ssh_bind_o The ssh server bind to use.
|
||||
* @param ssh_bind The ssh server bind to use.
|
||||
*
|
||||
* @param blocking Zero for nonblocking mode.
|
||||
*/
|
||||
LIBSSH_API void ssh_bind_set_blocking(ssh_bind ssh_bind_o, int blocking);
|
||||
void ssh_bind_set_blocking(SSH_BIND *ssh_bind, int blocking);
|
||||
|
||||
/**
|
||||
* @brief Recover the file descriptor from the session.
|
||||
*
|
||||
* @param ssh_bind_o The ssh server bind to get the fd from.
|
||||
* @param ssh_bind The ssh server bind to get the fd from.
|
||||
*
|
||||
* @return The file descriptor.
|
||||
*/
|
||||
LIBSSH_API socket_t ssh_bind_get_fd(ssh_bind ssh_bind_o);
|
||||
socket_t ssh_bind_get_fd(SSH_BIND *ssh_bind);
|
||||
|
||||
/**
|
||||
* @brief Set the file descriptor for a session.
|
||||
*
|
||||
* @param ssh_bind_o The ssh server bind to set the fd.
|
||||
* @param ssh_bind The ssh server bind to set the fd.
|
||||
*
|
||||
* @param fd The file descriptssh_bind B
|
||||
* @param fd The file descriptor.
|
||||
*/
|
||||
LIBSSH_API void ssh_bind_set_fd(ssh_bind ssh_bind_o, socket_t fd);
|
||||
void ssh_bind_set_fd(SSH_BIND *ssh_bind, socket_t fd);
|
||||
|
||||
/**
|
||||
* @brief Allow the file descriptor to accept new sessions.
|
||||
*
|
||||
* @param ssh_bind_o The ssh server bind to use.
|
||||
* @param ssh_bind The ssh server bind to use.
|
||||
*/
|
||||
LIBSSH_API void ssh_bind_fd_toaccept(ssh_bind ssh_bind_o);
|
||||
void ssh_bind_fd_toaccept(SSH_BIND *ssh_bind);
|
||||
|
||||
/**
|
||||
* @brief Accept an incoming ssh connection and initialize the session.
|
||||
*
|
||||
* @param ssh_bind_o The ssh server bind to accept a connection.
|
||||
* @param session A preallocated ssh session
|
||||
* @see ssh_new
|
||||
* @return SSH_OK when a connection is established
|
||||
*/
|
||||
LIBSSH_API int ssh_bind_accept(ssh_bind ssh_bind_o, ssh_session session);
|
||||
|
||||
/**
|
||||
* @brief Handles the key exchange and set up encryption
|
||||
* @param ssh_bind The ssh server bind to accept a connection.
|
||||
*
|
||||
* @param session A connected ssh session
|
||||
* @see ssh_bind_accept
|
||||
* @return SSH_OK if the key exchange was successful
|
||||
* @return A newly allocated ssh session, NULL on error.
|
||||
*/
|
||||
LIBSSH_API int ssh_handle_key_exchange(ssh_session session);
|
||||
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind);
|
||||
|
||||
/**
|
||||
* @brief Free a ssh servers bind.
|
||||
*
|
||||
* @param ssh_bind_o The ssh server bind to free.
|
||||
* @param ssh_bind The ssh server bind to free.
|
||||
*/
|
||||
LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o);
|
||||
void ssh_bind_free(SSH_BIND *ssh_bind);
|
||||
|
||||
/**
|
||||
* @brief Exchange the banner and cryptographic keys.
|
||||
*
|
||||
* @param session The ssh session to accept a connection.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
int ssh_accept(SSH_SESSION *session);
|
||||
|
||||
/* messages.c */
|
||||
LIBSSH_API int ssh_message_reply_default(ssh_message msg);
|
||||
|
||||
LIBSSH_API char *ssh_message_auth_user(ssh_message msg);
|
||||
LIBSSH_API char *ssh_message_auth_password(ssh_message msg);
|
||||
LIBSSH_API ssh_public_key ssh_message_auth_publickey(ssh_message msg);
|
||||
LIBSSH_API enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_auth_reply_success(ssh_message msg,int partial);
|
||||
LIBSSH_API int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey);
|
||||
LIBSSH_API int ssh_message_auth_reply_pk_ok_simple(ssh_message msg);
|
||||
#define SSH_AUTH_REQUEST 1
|
||||
#define SSH_CHANNEL_REQUEST_OPEN 2
|
||||
#define SSH_CHANNEL_REQUEST 3
|
||||
|
||||
LIBSSH_API int ssh_message_auth_set_methods(ssh_message msg, int methods);
|
||||
#define SSH_AUTH_NONE (1<<0)
|
||||
#define SSH_AUTH_PASSWORD (1<<1)
|
||||
#define SSH_AUTH_HOSTBASED (1<<2)
|
||||
#define SSH_AUTH_PUBLICKEY (1<<3)
|
||||
#define SSH_AUTH_KEYBINT (1<<4)
|
||||
#define SSH_AUTH_UNKNOWN 0
|
||||
|
||||
LIBSSH_API int ssh_message_service_reply_success(ssh_message msg);
|
||||
LIBSSH_API char *ssh_message_service_service(ssh_message msg);
|
||||
#define SSH_CHANNEL_SESSION 1
|
||||
#define SSH_CHANNEL_TCPIP 2
|
||||
#define SSH_CHANNEL_X11 3
|
||||
#define SSH_CHANNEL_UNKNOWN 4
|
||||
|
||||
LIBSSH_API int ssh_message_global_request_reply_success(ssh_message msg,
|
||||
uint16_t bound_port);
|
||||
#define SSH_CHANNEL_REQUEST_PTY 1
|
||||
#define SSH_CHANNEL_REQUEST_EXEC 2
|
||||
#define SSH_CHANNEL_REQUEST_SHELL 3
|
||||
#define SSH_CHANNEL_REQUEST_ENV 4
|
||||
#define SSH_CHANNEL_REQUEST_SUBSYSTEM 5
|
||||
#define SSH_CHANNEL_REQUEST_WINDOW_CHANGE 6
|
||||
#define SSH_CHANNEL_REQUEST_UNKNOWN 7
|
||||
|
||||
LIBSSH_API void ssh_set_message_callback(ssh_session session,
|
||||
int(*ssh_bind_message_callback)(ssh_session session, ssh_message msg, void *data),
|
||||
void *data);
|
||||
LIBSSH_API int ssh_execute_message_callbacks(ssh_session session);
|
||||
typedef struct ssh_message SSH_MESSAGE;
|
||||
|
||||
LIBSSH_API char *ssh_message_channel_request_open_originator(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_open_originator_port(ssh_message msg);
|
||||
LIBSSH_API char *ssh_message_channel_request_open_destination(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_open_destination_port(ssh_message msg);
|
||||
SSH_MESSAGE *ssh_message_get(SSH_SESSION *session);
|
||||
int ssh_message_type(SSH_MESSAGE *msg);
|
||||
int ssh_message_subtype(SSH_MESSAGE *msg);
|
||||
int ssh_message_reply_default(SSH_MESSAGE *msg);
|
||||
void ssh_message_free(SSH_MESSAGE *msg);
|
||||
|
||||
LIBSSH_API ssh_channel ssh_message_channel_request_channel(ssh_message msg);
|
||||
char *ssh_message_auth_user(SSH_MESSAGE *msg);
|
||||
char *ssh_message_auth_password(SSH_MESSAGE *msg);
|
||||
int ssh_message_auth_reply_success(SSH_MESSAGE *msg,int partial);
|
||||
int ssh_message_auth_set_methods(SSH_MESSAGE *msg, int methods);
|
||||
|
||||
LIBSSH_API char *ssh_message_channel_request_pty_term(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_pty_width(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_pty_height(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_pty_pxwidth(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_channel_request_pty_pxheight(ssh_message msg);
|
||||
CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg);
|
||||
|
||||
LIBSSH_API char *ssh_message_channel_request_env_name(ssh_message msg);
|
||||
LIBSSH_API char *ssh_message_channel_request_env_value(ssh_message msg);
|
||||
|
||||
LIBSSH_API char *ssh_message_channel_request_command(ssh_message msg);
|
||||
|
||||
LIBSSH_API char *ssh_message_channel_request_subsystem(ssh_message msg);
|
||||
|
||||
LIBSSH_API char *ssh_message_global_request_address(ssh_message msg);
|
||||
LIBSSH_API int ssh_message_global_request_port(ssh_message msg);
|
||||
|
||||
LIBSSH_API int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost,
|
||||
int remoteport, const char *sourcehost, int localport);
|
||||
|
||||
LIBSSH_API int ssh_channel_request_send_exit_status(ssh_channel channel,
|
||||
int exit_status);
|
||||
LIBSSH_API int ssh_channel_request_send_exit_signal(ssh_channel channel,
|
||||
const char *signum,
|
||||
int core,
|
||||
const char *errmsg,
|
||||
const char *lang);
|
||||
LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
|
||||
const void *data,
|
||||
uint32_t len);
|
||||
|
||||
/* deprecated functions */
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
|
||||
const void *data, uint32_t len);
|
||||
CHANNEL *ssh_message_channel_request_channel(SSH_MESSAGE *msg);
|
||||
// returns the TERM env variable
|
||||
char *ssh_message_channel_request_pty_term(SSH_MESSAGE *msg);
|
||||
char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg);
|
||||
int ssh_message_channel_request_reply_success(SSH_MESSAGE *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@@ -312,4 +174,7 @@ SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
|
||||
|
||||
#endif /* SERVER_H */
|
||||
|
||||
/** @} */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* 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 SESSION_H_
|
||||
#define SESSION_H_
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/packet.h"
|
||||
#include "libssh/pcap.h"
|
||||
#include "libssh/auth.h"
|
||||
#include "libssh/channels.h"
|
||||
#include "libssh/poll.h"
|
||||
typedef struct ssh_kbdint_struct* ssh_kbdint;
|
||||
|
||||
/* These are the different states a SSH session can be into its life */
|
||||
enum ssh_session_state_e {
|
||||
SSH_SESSION_STATE_NONE=0,
|
||||
SSH_SESSION_STATE_CONNECTING,
|
||||
SSH_SESSION_STATE_SOCKET_CONNECTED,
|
||||
SSH_SESSION_STATE_BANNER_RECEIVED,
|
||||
SSH_SESSION_STATE_INITIAL_KEX,
|
||||
SSH_SESSION_STATE_KEXINIT_RECEIVED,
|
||||
SSH_SESSION_STATE_DH,
|
||||
SSH_SESSION_STATE_AUTHENTICATING,
|
||||
SSH_SESSION_STATE_AUTHENTICATED,
|
||||
SSH_SESSION_STATE_ERROR,
|
||||
SSH_SESSION_STATE_DISCONNECTED
|
||||
};
|
||||
|
||||
enum ssh_dh_state_e {
|
||||
DH_STATE_INIT=0,
|
||||
DH_STATE_INIT_SENT,
|
||||
DH_STATE_NEWKEYS_SENT,
|
||||
DH_STATE_FINISHED
|
||||
};
|
||||
|
||||
enum ssh_pending_call_e {
|
||||
SSH_PENDING_CALL_NONE = 0,
|
||||
SSH_PENDING_CALL_CONNECT,
|
||||
SSH_PENDING_CALL_AUTH_NONE,
|
||||
SSH_PENDING_CALL_AUTH_PASSWORD
|
||||
};
|
||||
|
||||
/* libssh calls may block an undefined amount of time */
|
||||
#define SSH_SESSION_FLAG_BLOCKING 1
|
||||
|
||||
struct ssh_session_struct {
|
||||
struct error_struct error;
|
||||
struct ssh_socket_struct *socket;
|
||||
char *serverbanner;
|
||||
char *clientbanner;
|
||||
int protoversion;
|
||||
int server;
|
||||
int client;
|
||||
int openssh;
|
||||
uint32_t send_seq;
|
||||
uint32_t recv_seq;
|
||||
/* status flags */
|
||||
int closed;
|
||||
int closed_by_except;
|
||||
|
||||
int connected;
|
||||
/* !=0 when the user got a session handle */
|
||||
int alive;
|
||||
/* two previous are deprecated */
|
||||
/* int auth_service_asked; */
|
||||
|
||||
/* session flags (SSH_SESSION_FLAG_*) */
|
||||
int flags;
|
||||
|
||||
ssh_string banner; /* that's the issue banner from
|
||||
the server */
|
||||
char *discon_msg; /* disconnect message from
|
||||
the remote host */
|
||||
ssh_buffer in_buffer;
|
||||
PACKET in_packet;
|
||||
ssh_buffer out_buffer;
|
||||
|
||||
/* the states are used by the nonblocking stuff to remember */
|
||||
/* where it was before being interrupted */
|
||||
enum ssh_pending_call_e pending_call_state;
|
||||
enum ssh_session_state_e session_state;
|
||||
int packet_state;
|
||||
enum ssh_dh_state_e dh_handshake_state;
|
||||
enum ssh_auth_service_state_e auth_service_state;
|
||||
enum ssh_auth_state_e auth_state;
|
||||
enum ssh_channel_request_state_e global_req_state;
|
||||
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
||||
KEX server_kex;
|
||||
KEX client_kex;
|
||||
ssh_buffer in_hashbuf;
|
||||
ssh_buffer out_hashbuf;
|
||||
struct ssh_crypto_struct *current_crypto;
|
||||
struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */
|
||||
|
||||
ssh_channel channels; /* linked list of channels */
|
||||
int maxchannel;
|
||||
int exec_channel_opened; /* version 1 only. more
|
||||
info in channels1.c */
|
||||
ssh_agent agent; /* ssh agent */
|
||||
|
||||
/* keyb interactive data */
|
||||
struct ssh_kbdint_struct *kbdint;
|
||||
int version; /* 1 or 2 */
|
||||
/* server host keys */
|
||||
ssh_private_key rsa_key;
|
||||
ssh_private_key dsa_key;
|
||||
/* auths accepted by server */
|
||||
int auth_methods;
|
||||
int hostkeys; /* contains type of host key wanted by client, in server impl */
|
||||
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
|
||||
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata);
|
||||
void *ssh_message_callback_data;
|
||||
int log_verbosity; /*cached copy of the option structure */
|
||||
int log_indent; /* indentation level in enter_function logs */
|
||||
|
||||
void (*ssh_connection_callback)( struct ssh_session_struct *session);
|
||||
ssh_callbacks callbacks; /* Callbacks to user functions */
|
||||
struct ssh_packet_callbacks_struct default_packet_callbacks;
|
||||
struct ssh_list *packet_callbacks;
|
||||
struct ssh_socket_callbacks_struct socket_callbacks;
|
||||
ssh_poll_ctx default_poll_ctx;
|
||||
/* options */
|
||||
#ifdef WITH_PCAP
|
||||
ssh_pcap_context pcap_ctx; /* pcap debugging context */
|
||||
#endif
|
||||
char *username;
|
||||
char *host;
|
||||
char *bindaddr; /* bind the client to an ip addr */
|
||||
char *xbanner; /* TODO: looks like it is not needed */
|
||||
struct ssh_list *identity;
|
||||
char *sshdir;
|
||||
char *knownhosts;
|
||||
char *wanted_methods[10];
|
||||
char compressionlevel;
|
||||
unsigned long timeout; /* seconds */
|
||||
unsigned long timeout_usec;
|
||||
unsigned int port;
|
||||
socket_t fd;
|
||||
int ssh2;
|
||||
int ssh1;
|
||||
int StrictHostKeyChecking;
|
||||
char *ProxyCommand;
|
||||
};
|
||||
|
||||
/** @internal
|
||||
* @brief a termination function evaluates the status of an object
|
||||
* @param user[in] object to evaluate
|
||||
* @returns 1 if the polling routine should terminate, 0 instead
|
||||
*/
|
||||
typedef int (*ssh_termination_function)(void *user);
|
||||
int ssh_handle_packets(ssh_session session, int timeout);
|
||||
int ssh_handle_packets_termination(ssh_session session, int timeout,
|
||||
ssh_termination_function fct, void *user);
|
||||
void ssh_socket_exception_callback(int code, int errno_code, void *user);
|
||||
|
||||
#endif /* SESSION_H_ */
|
||||
@@ -25,168 +25,139 @@
|
||||
* @brief SFTP handling functions
|
||||
*
|
||||
* SFTP commands are channeled by the ssh sftp subsystem. Every packet is
|
||||
* sent/read using a sftp_packet type structure. Related to these packets,
|
||||
* sent/read using a SFTP_PACKET type structure. Related to these packets,
|
||||
* most of the server answers are messages having an ID and a message
|
||||
* specific part. It is described by sftp_message when reading a message,
|
||||
* specific part. It is described by SFTP_MESSAGE when reading a message,
|
||||
* the sftp system puts it into the queue, so the process having asked for
|
||||
* it can fetch it, while continuing to read for other messages (it is
|
||||
* unspecified in which order messages may be sent back to the client
|
||||
* inspecified in which order messages may be sent back to the client
|
||||
*
|
||||
* @defgroup libssh_sftp The libssh SFTP API
|
||||
* @defgroup ssh_sftp SFTP Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef SFTP_H
|
||||
#define SFTP_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "libssh.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define SFTP_DEPRECATED __attribute__ ((deprecated))
|
||||
#else
|
||||
#define SFTP_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef uid_t
|
||||
typedef uint32_t uid_t;
|
||||
typedef long uid_t;
|
||||
#endif /* uid_t */
|
||||
#ifndef gid_t
|
||||
typedef uint32_t gid_t;
|
||||
typedef long gid_t;
|
||||
#endif /* gid_t */
|
||||
#ifdef _MSC_VER
|
||||
#ifndef ssize_t
|
||||
typedef _W64 SSIZE_T ssize_t;
|
||||
#endif /* ssize_t */
|
||||
#endif /* _MSC_VER */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
typedef struct sftp_attributes_struct* sftp_attributes;
|
||||
typedef struct sftp_client_message_struct* sftp_client_message;
|
||||
typedef struct sftp_dir_struct* sftp_dir;
|
||||
typedef struct sftp_ext_struct *sftp_ext;
|
||||
typedef struct sftp_file_struct* sftp_file;
|
||||
typedef struct sftp_message_struct* sftp_message;
|
||||
typedef struct sftp_packet_struct* sftp_packet;
|
||||
typedef struct sftp_request_queue_struct* sftp_request_queue;
|
||||
typedef struct sftp_session_struct* sftp_session;
|
||||
typedef struct sftp_status_message_struct* sftp_status_message;
|
||||
typedef struct sftp_statvfs_struct* sftp_statvfs_t;
|
||||
|
||||
struct sftp_session_struct {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
typedef struct sftp_session_struct {
|
||||
SSH_SESSION *session;
|
||||
CHANNEL *channel;
|
||||
int server_version;
|
||||
int client_version;
|
||||
int version;
|
||||
sftp_request_queue queue;
|
||||
uint32_t id_counter;
|
||||
struct request_queue *queue;
|
||||
u32 id_counter;
|
||||
int errnum;
|
||||
void **handles;
|
||||
sftp_ext ext;
|
||||
};
|
||||
} SFTP_SESSION ;
|
||||
|
||||
struct sftp_packet_struct {
|
||||
sftp_session sftp;
|
||||
uint8_t type;
|
||||
ssh_buffer payload;
|
||||
};
|
||||
typedef struct {
|
||||
SFTP_SESSION *sftp;
|
||||
u8 type;
|
||||
BUFFER *payload;
|
||||
} SFTP_PACKET;
|
||||
|
||||
/* file handler */
|
||||
struct sftp_file_struct {
|
||||
sftp_session sftp;
|
||||
typedef struct sftp_file{
|
||||
SFTP_SESSION *sftp;
|
||||
char *name;
|
||||
uint64_t offset;
|
||||
ssh_string handle;
|
||||
u64 offset;
|
||||
STRING *handle;
|
||||
int eof;
|
||||
int nonblocking;
|
||||
};
|
||||
} SFTP_FILE ;
|
||||
|
||||
struct sftp_dir_struct {
|
||||
sftp_session sftp;
|
||||
typedef struct sftp_dir {
|
||||
SFTP_SESSION *sftp;
|
||||
char *name;
|
||||
ssh_string handle; /* handle to directory */
|
||||
ssh_buffer buffer; /* contains raw attributes from server which haven't been parsed */
|
||||
uint32_t count; /* counts the number of following attributes structures into buffer */
|
||||
STRING *handle; /* handle to directory */
|
||||
BUFFER *buffer; /* contains raw attributes from server which haven't been parsed */
|
||||
u32 count; /* counts the number of following attributes structures into buffer */
|
||||
int eof; /* end of directory listing */
|
||||
};
|
||||
} SFTP_DIR;
|
||||
|
||||
struct sftp_message_struct {
|
||||
sftp_session sftp;
|
||||
uint8_t packet_type;
|
||||
ssh_buffer payload;
|
||||
uint32_t id;
|
||||
};
|
||||
typedef struct {
|
||||
SFTP_SESSION *sftp;
|
||||
u8 packet_type;
|
||||
BUFFER *payload;
|
||||
u32 id;
|
||||
} SFTP_MESSAGE;
|
||||
|
||||
/* this is a bunch of all data that could be into a message */
|
||||
struct sftp_client_message_struct {
|
||||
sftp_session sftp;
|
||||
uint8_t type;
|
||||
uint32_t id;
|
||||
typedef struct sftp_client_message{
|
||||
SFTP_SESSION *sftp;
|
||||
u8 type;
|
||||
u32 id;
|
||||
char *filename; /* can be "path" */
|
||||
uint32_t flags;
|
||||
sftp_attributes attr;
|
||||
ssh_string handle;
|
||||
uint64_t offset;
|
||||
uint32_t len;
|
||||
u32 flags;
|
||||
struct sftp_attributes *attr;
|
||||
STRING *handle;
|
||||
u64 offset;
|
||||
u32 len;
|
||||
int attr_num;
|
||||
ssh_buffer attrbuf; /* used by sftp_reply_attrs */
|
||||
ssh_string data; /* can be newpath of rename() */
|
||||
};
|
||||
BUFFER *attrbuf; /* used by sftp_reply_attrs */
|
||||
STRING *data; /* can be newpath of rename() */
|
||||
} SFTP_CLIENT_MESSAGE;
|
||||
|
||||
struct sftp_request_queue_struct {
|
||||
sftp_request_queue next;
|
||||
sftp_message message;
|
||||
};
|
||||
typedef struct request_queue{
|
||||
struct request_queue *next;
|
||||
SFTP_MESSAGE *message;
|
||||
} REQUEST_QUEUE;
|
||||
|
||||
/* SSH_FXP_MESSAGE described into .7 page 26 */
|
||||
struct sftp_status_message_struct {
|
||||
uint32_t id;
|
||||
uint32_t status;
|
||||
ssh_string error;
|
||||
ssh_string lang;
|
||||
typedef struct {
|
||||
u32 id;
|
||||
u32 status;
|
||||
STRING *error;
|
||||
STRING *lang;
|
||||
char *errormsg;
|
||||
char *langmsg;
|
||||
};
|
||||
} STATUS_MESSAGE;
|
||||
|
||||
struct sftp_attributes_struct {
|
||||
/* don't worry much of these aren't really used */
|
||||
typedef struct sftp_attributes{
|
||||
char *name;
|
||||
char *longname; /* ls -l output on openssh, not reliable else */
|
||||
uint32_t flags;
|
||||
uint8_t type;
|
||||
uint64_t size;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
char *owner; /* set if openssh and version 4 */
|
||||
char *group; /* set if openssh and version 4 */
|
||||
uint32_t permissions;
|
||||
uint64_t atime64;
|
||||
uint32_t atime;
|
||||
uint32_t atime_nseconds;
|
||||
uint64_t createtime;
|
||||
uint32_t createtime_nseconds;
|
||||
uint64_t mtime64;
|
||||
uint32_t mtime;
|
||||
uint32_t mtime_nseconds;
|
||||
ssh_string acl;
|
||||
uint32_t extended_count;
|
||||
ssh_string extended_type;
|
||||
ssh_string extended_data;
|
||||
};
|
||||
|
||||
struct sftp_statvfs_struct {
|
||||
uint64_t f_bsize; /* file system block size */
|
||||
uint64_t f_frsize; /* fundamental fs block size */
|
||||
uint64_t f_blocks; /* number of blocks (unit f_frsize) */
|
||||
uint64_t f_bfree; /* free blocks in file system */
|
||||
uint64_t f_bavail; /* free blocks for non-root */
|
||||
uint64_t f_files; /* total file inodes */
|
||||
uint64_t f_ffree; /* free file inodes */
|
||||
uint64_t f_favail; /* free file inodes for to non-root */
|
||||
uint64_t f_fsid; /* file system id */
|
||||
uint64_t f_flag; /* bit mask of f_flag values */
|
||||
uint64_t f_namemax; /* maximum filename length */
|
||||
};
|
||||
char *longname; /* some weird stuff */
|
||||
u32 flags;
|
||||
u8 type;
|
||||
u64 size;
|
||||
u32 uid;
|
||||
u32 gid;
|
||||
char *owner;
|
||||
char *group;
|
||||
u32 permissions;
|
||||
u64 atime64;
|
||||
u32 atime;
|
||||
u32 atime_nseconds;
|
||||
u64 createtime;
|
||||
u32 createtime_nseconds;
|
||||
u64 mtime64;
|
||||
u32 mtime;
|
||||
u32 mtime_nseconds;
|
||||
STRING *acl;
|
||||
u32 extended_count;
|
||||
STRING *extended_type;
|
||||
STRING *extended_data;
|
||||
} SFTP_ATTRIBUTES;
|
||||
|
||||
#define LIBSFTP_VERSION 3
|
||||
|
||||
@@ -197,14 +168,14 @@ struct sftp_statvfs_struct {
|
||||
*
|
||||
* @return A new sftp session or NULL on error.
|
||||
*/
|
||||
LIBSSH_API sftp_session sftp_new(ssh_session session);
|
||||
SFTP_SESSION *sftp_new(SSH_SESSION *session);
|
||||
|
||||
/**
|
||||
* @brief Close and deallocate a sftp session.
|
||||
*
|
||||
* @param sftp The sftp session handle to free.
|
||||
*/
|
||||
LIBSSH_API void sftp_free(sftp_session sftp);
|
||||
void sftp_free(SFTP_SESSION *sftp);
|
||||
|
||||
/**
|
||||
* @brief Initialize the sftp session with the server.
|
||||
@@ -213,7 +184,7 @@ LIBSSH_API void sftp_free(sftp_session sftp);
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_init(sftp_session sftp);
|
||||
int sftp_init(SFTP_SESSION *sftp);
|
||||
|
||||
/**
|
||||
* @brief Get the last sftp error.
|
||||
@@ -225,65 +196,11 @@ LIBSSH_API int sftp_init(sftp_session sftp);
|
||||
* @return The saved error (see server responses), < 0 if an error
|
||||
* in the function occured.
|
||||
*/
|
||||
LIBSSH_API int sftp_get_error(sftp_session sftp);
|
||||
|
||||
/**
|
||||
* @brief Get the count of extensions provided by the server.
|
||||
*
|
||||
* @param sftp The sftp session to use.
|
||||
*
|
||||
* @return The count of extensions provided by the server, 0 on error or
|
||||
* not available.
|
||||
*/
|
||||
LIBSSH_API unsigned int sftp_extensions_get_count(sftp_session sftp);
|
||||
|
||||
/**
|
||||
* @brief Get the name of the extension provided by the server.
|
||||
*
|
||||
* @param sftp The sftp session to use.
|
||||
*
|
||||
* @param indexn The index number of the extension name you want.
|
||||
*
|
||||
* @return The name of the extension.
|
||||
*/
|
||||
LIBSSH_API const char *sftp_extensions_get_name(sftp_session sftp, unsigned int indexn);
|
||||
|
||||
/**
|
||||
* @brief Get the data of the extension provided by the server.
|
||||
*
|
||||
* This is normally the version number of the extension.
|
||||
*
|
||||
* @param sftp The sftp session to use.
|
||||
*
|
||||
* @param indexn The index number of the extension data you want.
|
||||
*
|
||||
* @return The data of the extension.
|
||||
*/
|
||||
LIBSSH_API const char *sftp_extensions_get_data(sftp_session sftp, unsigned int indexn);
|
||||
|
||||
/**
|
||||
* @brief Check if the given extension is supported.
|
||||
*
|
||||
* @param sftp The sftp session to use.
|
||||
*
|
||||
* @param name The name of the extension.
|
||||
*
|
||||
* @param data The data of the extension.
|
||||
*
|
||||
* @return 1 if supported, 0 if not.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @code
|
||||
* sftp_extension_supported(sftp, "statvfs@openssh.com", "2");
|
||||
* @endcode
|
||||
*/
|
||||
LIBSSH_API int sftp_extension_supported(sftp_session sftp, const char *name,
|
||||
const char *data);
|
||||
int sftp_get_error(SFTP_SESSION *sftp);
|
||||
|
||||
/**
|
||||
* @brief Open a directory used to obtain directory entries.
|
||||
|
||||
*
|
||||
* @param session The sftp session handle to open the directory.
|
||||
* @param path The path of the directory to open.
|
||||
*
|
||||
@@ -293,7 +210,7 @@ LIBSSH_API int sftp_extension_supported(sftp_session sftp, const char *name,
|
||||
* @see sftp_readdir
|
||||
* @see sftp_closedir
|
||||
*/
|
||||
LIBSSH_API sftp_dir sftp_opendir(sftp_session session, const char *path);
|
||||
SFTP_DIR *sftp_opendir(SFTP_SESSION *session, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Get a single file attributes structure of a directory.
|
||||
@@ -308,7 +225,7 @@ LIBSSH_API sftp_dir sftp_opendir(sftp_session session, const char *path);
|
||||
* @see sftp_attribute_free()
|
||||
* @see sftp_closedir()
|
||||
*/
|
||||
LIBSSH_API sftp_attributes sftp_readdir(sftp_session session, sftp_dir dir);
|
||||
SFTP_ATTRIBUTES *sftp_readdir(SFTP_SESSION *session, SFTP_DIR *dir);
|
||||
|
||||
/**
|
||||
* @brief Tell if the directory has reached EOF (End Of File).
|
||||
@@ -319,7 +236,7 @@ LIBSSH_API sftp_attributes sftp_readdir(sftp_session session, sftp_dir dir);
|
||||
*
|
||||
* @see sftp_readdir()
|
||||
*/
|
||||
LIBSSH_API int sftp_dir_eof(sftp_dir dir);
|
||||
int sftp_dir_eof(SFTP_DIR *dir);
|
||||
|
||||
/**
|
||||
* @brief Get information about a file or directory.
|
||||
@@ -331,7 +248,7 @@ LIBSSH_API int sftp_dir_eof(sftp_dir dir);
|
||||
* @return The sftp attributes structure of the file or directory,
|
||||
* NULL on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API sftp_attributes sftp_stat(sftp_session session, const char *path);
|
||||
SFTP_ATTRIBUTES *sftp_stat(SFTP_SESSION *session, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Get information about a file or directory.
|
||||
@@ -346,7 +263,7 @@ LIBSSH_API sftp_attributes sftp_stat(sftp_session session, const char *path);
|
||||
* @return The sftp attributes structure of the file or directory,
|
||||
* NULL on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API sftp_attributes sftp_lstat(sftp_session session, const char *path);
|
||||
SFTP_ATTRIBUTES *sftp_lstat(SFTP_SESSION *session, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Get information about a file or directory from a file handle.
|
||||
@@ -356,14 +273,14 @@ LIBSSH_API sftp_attributes sftp_lstat(sftp_session session, const char *path);
|
||||
* @return The sftp attributes structure of the file or directory,
|
||||
* NULL on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API sftp_attributes sftp_fstat(sftp_file file);
|
||||
SFTP_ATTRIBUTES *sftp_fstat(SFTP_FILE *file);
|
||||
|
||||
/**
|
||||
* @brief Free a sftp attribute structure.
|
||||
*
|
||||
* @param file The sftp attribute structure to free.
|
||||
*/
|
||||
LIBSSH_API void sftp_attributes_free(sftp_attributes file);
|
||||
void sftp_attributes_free(SFTP_ATTRIBUTES *file);
|
||||
|
||||
/**
|
||||
* @brief Close a directory handle opened by sftp_opendir().
|
||||
@@ -372,7 +289,12 @@ LIBSSH_API void sftp_attributes_free(sftp_attributes file);
|
||||
*
|
||||
* @return Returns SSH_NO_ERROR or SSH_ERROR if an error occured.
|
||||
*/
|
||||
LIBSSH_API int sftp_closedir(sftp_dir dir);
|
||||
int sftp_closedir(SFTP_DIR *dir);
|
||||
|
||||
/**
|
||||
* @deprecated Use sftp_closedir() instead.
|
||||
*/
|
||||
int sftp_dir_close(SFTP_DIR *dir) SFTP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* @brief Close an open file handle.
|
||||
@@ -383,7 +305,12 @@ LIBSSH_API int sftp_closedir(sftp_dir dir);
|
||||
*
|
||||
* @see sftp_open()
|
||||
*/
|
||||
LIBSSH_API int sftp_close(sftp_file file);
|
||||
int sftp_close(SFTP_FILE *file);
|
||||
|
||||
/**
|
||||
* @deprecated Use sftp_close() instead.
|
||||
*/
|
||||
int sftp_file_close(SFTP_FILE *file) SFTP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* @brief Open a file on the server.
|
||||
@@ -392,7 +319,7 @@ LIBSSH_API int sftp_close(sftp_file file);
|
||||
*
|
||||
* @param file The file to be opened.
|
||||
*
|
||||
* @param accesstype Is one of O_RDONLY, O_WRONLY or O_RDWR which request
|
||||
* @param access Is one of O_RDONLY, O_WRONLY or O_RDWR which request
|
||||
* opening the file read-only,write-only or read/write.
|
||||
* Acesss may also be bitwise-or'd with one or more of
|
||||
* the following:
|
||||
@@ -411,12 +338,12 @@ LIBSSH_API int sftp_close(sftp_file file);
|
||||
* @return A sftp file handle, NULL on error with ssh and sftp
|
||||
* error set.
|
||||
*/
|
||||
LIBSSH_API sftp_file sftp_open(sftp_session session, const char *file, int accesstype,
|
||||
SFTP_FILE *sftp_open(SFTP_SESSION *session, const char *file, int flags,
|
||||
mode_t mode);
|
||||
|
||||
LIBSSH_API void sftp_file_set_nonblocking(sftp_file handle);
|
||||
void sftp_file_set_nonblocking(SFTP_FILE *handle);
|
||||
|
||||
LIBSSH_API void sftp_file_set_blocking(sftp_file handle);
|
||||
void sftp_file_set_blocking(SFTP_FILE *handle);
|
||||
|
||||
/**
|
||||
* @brief Read from a file using an opened sftp file handle.
|
||||
@@ -430,7 +357,7 @@ LIBSSH_API void sftp_file_set_blocking(sftp_file handle);
|
||||
* @return Number of bytes written, < 0 on error with ssh and sftp
|
||||
* error set.
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_read(sftp_file file, void *buf, size_t count);
|
||||
ssize_t sftp_read(SFTP_FILE *file, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Start an asynchronous read from a file using an opened sftp file handle.
|
||||
@@ -463,7 +390,7 @@ LIBSSH_API ssize_t sftp_read(sftp_file file, void *buf, size_t count);
|
||||
* @see sftp_async_read()
|
||||
* @see sftp_open()
|
||||
*/
|
||||
LIBSSH_API int sftp_async_read_begin(sftp_file file, uint32_t len);
|
||||
int sftp_async_read_begin(SFTP_FILE *file, u32 len);
|
||||
|
||||
/**
|
||||
* @brief Wait for an asynchronous read to complete and save the data.
|
||||
@@ -488,7 +415,7 @@ LIBSSH_API int sftp_async_read_begin(sftp_file file, uint32_t len);
|
||||
*
|
||||
* @see sftp_async_read_begin()
|
||||
*/
|
||||
LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_t id);
|
||||
int sftp_async_read(SFTP_FILE *file, void *data, u32 len, u32 id);
|
||||
|
||||
/**
|
||||
* @brief Write to a file using an opened sftp file handle.
|
||||
@@ -506,7 +433,7 @@ LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_
|
||||
* @see sftp_read()
|
||||
* @see sftp_close()
|
||||
*/
|
||||
LIBSSH_API ssize_t sftp_write(sftp_file file, const void *buf, size_t count);
|
||||
ssize_t sftp_write(SFTP_FILE *file, const void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Seek to a specific location in a file.
|
||||
@@ -517,7 +444,7 @@ LIBSSH_API ssize_t sftp_write(sftp_file file, const void *buf, size_t count);
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
LIBSSH_API int sftp_seek(sftp_file file, uint32_t new_offset);
|
||||
int sftp_seek(SFTP_FILE *file, u32 new_offset);
|
||||
|
||||
/**
|
||||
* @brief Seek to a specific location in a file. This is the
|
||||
@@ -529,7 +456,7 @@ LIBSSH_API int sftp_seek(sftp_file file, uint32_t new_offset);
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
LIBSSH_API int sftp_seek64(sftp_file file, uint64_t new_offset);
|
||||
int sftp_seek64(SFTP_FILE *file, u64 new_offset);
|
||||
|
||||
/**
|
||||
* @brief Report current byte position in file.
|
||||
@@ -540,18 +467,7 @@ LIBSSH_API int sftp_seek64(sftp_file file, uint64_t new_offset);
|
||||
* of the file associated with the file descriptor. < 0 on
|
||||
* error.
|
||||
*/
|
||||
LIBSSH_API unsigned long sftp_tell(sftp_file file);
|
||||
|
||||
/**
|
||||
* @brief Report current byte position in file.
|
||||
*
|
||||
* @param file Open sftp file handle.
|
||||
*
|
||||
* @return The offset of the current byte relative to the beginning
|
||||
* of the file associated with the file descriptor. < 0 on
|
||||
* error.
|
||||
*/
|
||||
LIBSSH_API uint64_t sftp_tell64(sftp_file file);
|
||||
unsigned long sftp_tell(SFTP_FILE *file);
|
||||
|
||||
/**
|
||||
* @brief Rewinds the position of the file pointer to the beginning of the
|
||||
@@ -559,7 +475,12 @@ LIBSSH_API uint64_t sftp_tell64(sftp_file file);
|
||||
*
|
||||
* @param file Open sftp file handle.
|
||||
*/
|
||||
LIBSSH_API void sftp_rewind(sftp_file file);
|
||||
void sftp_rewind(SFTP_FILE *file);
|
||||
|
||||
/**
|
||||
* @deprecated Use sftp_unlink() instead.
|
||||
*/
|
||||
int sftp_rm(SFTP_SESSION *sftp, const char *file) SFTP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* @brief Unlink (delete) a file.
|
||||
@@ -570,7 +491,7 @@ LIBSSH_API void sftp_rewind(sftp_file file);
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_unlink(sftp_session sftp, const char *file);
|
||||
int sftp_unlink(SFTP_SESSION *sftp, const char *file);
|
||||
|
||||
/**
|
||||
* @brief Remove a directoy.
|
||||
@@ -581,7 +502,7 @@ LIBSSH_API int sftp_unlink(sftp_session sftp, const char *file);
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_rmdir(sftp_session sftp, const char *directory);
|
||||
int sftp_rmdir(SFTP_SESSION *sftp, const char *directory);
|
||||
|
||||
/**
|
||||
* @brief Create a directory.
|
||||
@@ -596,7 +517,7 @@ LIBSSH_API int sftp_rmdir(sftp_session sftp, const char *directory);
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode);
|
||||
int sftp_mkdir(SFTP_SESSION *sftp, const char *directory, mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Rename or move a file or directory.
|
||||
@@ -611,7 +532,7 @@ LIBSSH_API int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_rename(sftp_session sftp, const char *original, const char *newname);
|
||||
int sftp_rename(SFTP_SESSION *sftp, const char *original, const char *newname);
|
||||
|
||||
/**
|
||||
* @brief Set file attributes on a file, directory or symbolic link.
|
||||
@@ -625,7 +546,7 @@ LIBSSH_API int sftp_rename(sftp_session sftp, const char *original, const char
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr);
|
||||
int sftp_setstat(SFTP_SESSION *sftp, const char *file, SFTP_ATTRIBUTES *attr);
|
||||
|
||||
/**
|
||||
* @brief Change the file owner and group
|
||||
@@ -640,7 +561,7 @@ LIBSSH_API int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_chown(sftp_session sftp, const char *file, uid_t owner, gid_t group);
|
||||
int sftp_chown(SFTP_SESSION *sftp, const char *file, uid_t owner, gid_t group);
|
||||
|
||||
/**
|
||||
* @brief Change permissions of a file
|
||||
@@ -655,7 +576,7 @@ LIBSSH_API int sftp_chown(sftp_session sftp, const char *file, uid_t owner, gid_
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_chmod(sftp_session sftp, const char *file, mode_t mode);
|
||||
int sftp_chmod(SFTP_SESSION *sftp, const char *file, mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Change the last modification and access time of a file.
|
||||
@@ -669,7 +590,7 @@ LIBSSH_API int sftp_chmod(sftp_session sftp, const char *file, mode_t mode);
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_utimes(sftp_session sftp, const char *file, const struct timeval *times);
|
||||
int sftp_utimes(SFTP_SESSION *sftp, const char *file, const struct timeval *times);
|
||||
|
||||
/**
|
||||
* @brief Create a symbolic link.
|
||||
@@ -682,7 +603,7 @@ LIBSSH_API int sftp_utimes(sftp_session sftp, const char *file, const struct tim
|
||||
*
|
||||
* @return 0 on success, < 0 on error with ssh and sftp error set.
|
||||
*/
|
||||
LIBSSH_API int sftp_symlink(sftp_session sftp, const char *target, const char *dest);
|
||||
int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest);
|
||||
|
||||
/**
|
||||
* @brief Read the value of a symbolic link.
|
||||
@@ -693,34 +614,7 @@ LIBSSH_API int sftp_symlink(sftp_session sftp, const char *target, const char *d
|
||||
*
|
||||
* @return The target of the link, NULL on error.
|
||||
*/
|
||||
LIBSSH_API char *sftp_readlink(sftp_session sftp, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Get information about a mounted file system.
|
||||
*
|
||||
* @param sftp The sftp session handle.
|
||||
*
|
||||
* @param path The pathname of any file within the mounted file system.
|
||||
*
|
||||
* @return A statvfs structure or NULL on error.
|
||||
*/
|
||||
LIBSSH_API sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Get information about a mounted file system.
|
||||
*
|
||||
* @param file An opened file.
|
||||
*
|
||||
* @return A statvfs structure or NULL on error.
|
||||
*/
|
||||
LIBSSH_API sftp_statvfs_t sftp_fstatvfs(sftp_file file);
|
||||
|
||||
/**
|
||||
* @brief Free the memory of an allocated statvfs.
|
||||
*
|
||||
* @param statvfs_o The statvfs to free.
|
||||
*/
|
||||
LIBSSH_API void sftp_statvfs_free(sftp_statvfs_t statvfs_o);
|
||||
char *sftp_readlink(SFTP_SESSION *sftp, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Canonicalize a sftp path.
|
||||
@@ -731,7 +625,7 @@ LIBSSH_API void sftp_statvfs_free(sftp_statvfs_t statvfs_o);
|
||||
*
|
||||
* @return The canonicalize path, NULL on error.
|
||||
*/
|
||||
LIBSSH_API char *sftp_canonicalize_path(sftp_session sftp, const char *path);
|
||||
char *sftp_canonicalize_path(SFTP_SESSION *sftp, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Get the version of the SFTP protocol supported by the server
|
||||
@@ -740,7 +634,7 @@ LIBSSH_API char *sftp_canonicalize_path(sftp_session sftp, const char *path);
|
||||
*
|
||||
* @return The server version.
|
||||
*/
|
||||
LIBSSH_API int sftp_server_version(sftp_session sftp);
|
||||
int sftp_server_version(SFTP_SESSION *sftp);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
/**
|
||||
@@ -752,7 +646,7 @@ LIBSSH_API int sftp_server_version(sftp_session sftp);
|
||||
*
|
||||
* @return A new sftp server session.
|
||||
*/
|
||||
LIBSSH_API sftp_session sftp_server_new(ssh_session session, ssh_channel chan);
|
||||
SFTP_SESSION *sftp_server_new(SSH_SESSION *session, CHANNEL *chan);
|
||||
|
||||
/**
|
||||
* @brief Intialize the sftp server.
|
||||
@@ -761,32 +655,32 @@ LIBSSH_API sftp_session sftp_server_new(ssh_session session, ssh_channel chan);
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
LIBSSH_API int sftp_server_init(sftp_session sftp);
|
||||
int sftp_server_init(SFTP_SESSION *sftp);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
/* this is not a public interface */
|
||||
#define SFTP_HANDLES 256
|
||||
sftp_packet sftp_packet_read(sftp_session sftp);
|
||||
int sftp_packet_write(sftp_session sftp,uint8_t type, ssh_buffer payload);
|
||||
void sftp_packet_free(sftp_packet packet);
|
||||
int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr);
|
||||
sftp_attributes sftp_parse_attr(sftp_session session, ssh_buffer buf,int expectname);
|
||||
SFTP_PACKET *sftp_packet_read(SFTP_SESSION *sftp);
|
||||
int sftp_packet_write(SFTP_SESSION *sftp,u8 type, BUFFER *payload);
|
||||
void sftp_packet_free(SFTP_PACKET *packet);
|
||||
int buffer_add_attributes(BUFFER *buffer, SFTP_ATTRIBUTES *attr);
|
||||
SFTP_ATTRIBUTES *sftp_parse_attr(SFTP_SESSION *session, BUFFER *buf,int expectname);
|
||||
/* sftpserver.c */
|
||||
|
||||
sftp_client_message sftp_get_client_message(sftp_session sftp);
|
||||
void sftp_client_message_free(sftp_client_message msg);
|
||||
int sftp_reply_name(sftp_client_message msg, const char *name,
|
||||
sftp_attributes attr);
|
||||
int sftp_reply_handle(sftp_client_message msg, ssh_string handle);
|
||||
ssh_string sftp_handle_alloc(sftp_session sftp, void *info);
|
||||
int sftp_reply_attr(sftp_client_message msg, sftp_attributes attr);
|
||||
void *sftp_handle(sftp_session sftp, ssh_string handle);
|
||||
int sftp_reply_status(sftp_client_message msg, uint32_t status, const char *message);
|
||||
int sftp_reply_names_add(sftp_client_message msg, const char *file,
|
||||
const char *longname, sftp_attributes attr);
|
||||
int sftp_reply_names(sftp_client_message msg);
|
||||
int sftp_reply_data(sftp_client_message msg, const void *data, int len);
|
||||
void sftp_handle_remove(sftp_session sftp, void *handle);
|
||||
SFTP_CLIENT_MESSAGE *sftp_get_client_message(SFTP_SESSION *sftp);
|
||||
void sftp_client_message_free(SFTP_CLIENT_MESSAGE *msg);
|
||||
int sftp_reply_name(SFTP_CLIENT_MESSAGE *msg, const char *name,
|
||||
SFTP_ATTRIBUTES *attr);
|
||||
int sftp_reply_handle(SFTP_CLIENT_MESSAGE *msg, STRING *handle);
|
||||
STRING *sftp_handle_alloc(SFTP_SESSION *sftp, void *info);
|
||||
int sftp_reply_attr(SFTP_CLIENT_MESSAGE *msg, SFTP_ATTRIBUTES *attr);
|
||||
void *sftp_handle(SFTP_SESSION *sftp, STRING *handle);
|
||||
int sftp_reply_status(SFTP_CLIENT_MESSAGE *msg, u32 status, const char *message);
|
||||
int sftp_reply_names_add(SFTP_CLIENT_MESSAGE *msg, const char *file,
|
||||
const char *longname, SFTP_ATTRIBUTES *attr);
|
||||
int sftp_reply_names(SFTP_CLIENT_MESSAGE *msg);
|
||||
int sftp_reply_data(SFTP_CLIENT_MESSAGE *msg, const void *data, int len);
|
||||
void sftp_handle_remove(SFTP_SESSION *sftp, void *handle);
|
||||
|
||||
/* SFTP commands and constants */
|
||||
#define SSH_FXP_INIT 1
|
||||
@@ -843,44 +737,22 @@ void sftp_handle_remove(sftp_session sftp, void *handle);
|
||||
#define SSH_FILEXFER_TYPE_SPECIAL 4
|
||||
#define SSH_FILEXFER_TYPE_UNKNOWN 5
|
||||
|
||||
/**
|
||||
* @name Server responses
|
||||
*
|
||||
* @brief Responses returned by the sftp server.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** No error */
|
||||
/* server responses */
|
||||
#define SSH_FX_OK 0
|
||||
/** End-of-file encountered */
|
||||
#define SSH_FX_EOF 1
|
||||
/** File doesn't exist */
|
||||
#define SSH_FX_NO_SUCH_FILE 2
|
||||
/** Permission denied */
|
||||
#define SSH_FX_PERMISSION_DENIED 3
|
||||
/** Generic failure */
|
||||
#define SSH_FX_FAILURE 4
|
||||
/** Garbage received from server */
|
||||
#define SSH_FX_BAD_MESSAGE 5
|
||||
/** No connection has been set up */
|
||||
#define SSH_FX_NO_CONNECTION 6
|
||||
/** There was a connection, but we lost it */
|
||||
#define SSH_FX_CONNECTION_LOST 7
|
||||
/** Operation not supported by the server */
|
||||
#define SSH_FX_OP_UNSUPPORTED 8
|
||||
/** Invalid file handle */
|
||||
#define SSH_FX_INVALID_HANDLE 9
|
||||
/** No such file or directory path exists */
|
||||
#define SSH_FX_NO_SUCH_PATH 10
|
||||
/** An attempt to create an already existing file or directory has been made */
|
||||
#define SSH_FX_FILE_ALREADY_EXISTS 11
|
||||
/** We are trying to write on a write-protected filesystem */
|
||||
#define SSH_FX_WRITE_PROTECT 12
|
||||
/** No media in remote drive */
|
||||
#define SSH_FX_NO_MEDIA 13
|
||||
|
||||
/** @} */
|
||||
|
||||
/* file flags */
|
||||
#define SSH_FXF_READ 0x01
|
||||
#define SSH_FXF_WRITE 0x02
|
||||
@@ -914,9 +786,7 @@ void sftp_handle_remove(sftp_session sftp, void *handle);
|
||||
#define SFTP_READLINK SSH_FXP_READLINK
|
||||
#define SFTP_SYMLINK SSH_FXP_SYMLINK
|
||||
|
||||
/* openssh flags */
|
||||
#define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */
|
||||
#define SSH_FXE_STATVFS_ST_NOSUID 0x2 /* no setuid */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} ;
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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 SOCKET_H_
|
||||
#define SOCKET_H_
|
||||
|
||||
#include "libssh/callbacks.h"
|
||||
struct ssh_poll_handle_struct;
|
||||
/* socket.c */
|
||||
|
||||
struct ssh_socket_struct;
|
||||
typedef struct ssh_socket_struct* ssh_socket;
|
||||
|
||||
int ssh_socket_init(void);
|
||||
void ssh_socket_cleanup(void);
|
||||
ssh_socket ssh_socket_new(ssh_session session);
|
||||
void ssh_socket_reset(ssh_socket s);
|
||||
void ssh_socket_free(ssh_socket s);
|
||||
void ssh_socket_set_fd(ssh_socket s, socket_t fd);
|
||||
socket_t ssh_socket_get_fd_in(ssh_socket s);
|
||||
#ifndef _WIN32
|
||||
int ssh_socket_unix(ssh_socket s, const char *path);
|
||||
void ssh_execute_command(const char *command, socket_t in, socket_t out);
|
||||
int ssh_socket_connect_proxycommand(ssh_socket s, const char *command);
|
||||
#endif
|
||||
void ssh_socket_close(ssh_socket s);
|
||||
int ssh_socket_write(ssh_socket s,const void *buffer, int len);
|
||||
int ssh_socket_is_open(ssh_socket s);
|
||||
int ssh_socket_fd_isset(ssh_socket s, fd_set *set);
|
||||
void ssh_socket_fd_set(ssh_socket s, fd_set *set, socket_t *max_fd);
|
||||
void ssh_socket_set_fd_in(ssh_socket s, socket_t fd);
|
||||
void ssh_socket_set_fd_out(ssh_socket s, socket_t fd);
|
||||
int ssh_socket_nonblocking_flush(ssh_socket s);
|
||||
void ssh_socket_set_write_wontblock(ssh_socket s);
|
||||
void ssh_socket_set_read_wontblock(ssh_socket s);
|
||||
void ssh_socket_set_except(ssh_socket s);
|
||||
int ssh_socket_get_status(ssh_socket s);
|
||||
int ssh_socket_buffered_write_bytes(ssh_socket s);
|
||||
int ssh_socket_data_available(ssh_socket s);
|
||||
int ssh_socket_data_writable(ssh_socket s);
|
||||
|
||||
void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks);
|
||||
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s);
|
||||
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_in(ssh_socket s);
|
||||
struct ssh_poll_handle_struct * ssh_socket_get_poll_handle_out(ssh_socket s);
|
||||
|
||||
int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr);
|
||||
|
||||
#endif /* SOCKET_H_ */
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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 STRING_H_
|
||||
#define STRING_H_
|
||||
#include "libssh/priv.h"
|
||||
|
||||
/* must be 32 bits number + immediately our data */
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct ssh_string_struct {
|
||||
uint32_t size;
|
||||
unsigned char string[MAX_PACKET_LEN];
|
||||
}
|
||||
#if !defined(__SUNPRO_C) && !defined(_MSC_VER)
|
||||
__attribute__ ((packed))
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack()
|
||||
#endif
|
||||
;
|
||||
|
||||
#endif /* STRING_H_ */
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 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 THREADS_H_
|
||||
#define THREADS_H_
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/callbacks.h>
|
||||
|
||||
int ssh_threads_init(void);
|
||||
void ssh_threads_finalize(void);
|
||||
const char *ssh_threads_get_type(void);
|
||||
|
||||
#endif /* THREADS_H_ */
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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 WRAPPER_H_
|
||||
#define WRAPPER_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/libcrypto.h"
|
||||
#include "libssh/libgcrypt.h"
|
||||
|
||||
MD5CTX md5_init(void);
|
||||
void md5_update(MD5CTX c, const void *data, unsigned long len);
|
||||
void md5_final(unsigned char *md,MD5CTX c);
|
||||
SHACTX sha1_init(void);
|
||||
void sha1_update(SHACTX c, const void *data, unsigned long len);
|
||||
void sha1_final(unsigned char *md,SHACTX c);
|
||||
void sha1(unsigned char *digest,int len,unsigned char *hash);
|
||||
#define HMAC_SHA1 1
|
||||
#define HMAC_MD5 2
|
||||
HMACCTX hmac_init(const void *key,int len,int type);
|
||||
void hmac_update(HMACCTX c, const void *data, unsigned long len);
|
||||
void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
|
||||
|
||||
int crypt_set_algorithms(ssh_session );
|
||||
int crypt_set_algorithms_server(ssh_session session);
|
||||
struct ssh_crypto_struct *crypto_new(void);
|
||||
void crypto_free(struct ssh_crypto_struct *crypto);
|
||||
|
||||
|
||||
#endif /* WRAPPER_H_ */
|
||||
999
include/wspiapi.h
Executable file
999
include/wspiapi.h
Executable file
@@ -0,0 +1,999 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2000, Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
wspiapi.h
|
||||
|
||||
Abstract:
|
||||
The file contains protocol independent API functions.
|
||||
|
||||
Revision History:
|
||||
Wed Jul 12 10:50:31 2000, Created
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _WSPIAPI_H_
|
||||
#define _WSPIAPI_H_
|
||||
|
||||
#include <stdio.h> // sprintf()
|
||||
#include <stdlib.h> // calloc(), strtoul()
|
||||
#include <malloc.h> // calloc()
|
||||
#include <string.h> // strlen(), strcmp(), strstr()
|
||||
|
||||
#define WspiapiMalloc(tSize) calloc(1, (tSize))
|
||||
#define WspiapiFree(p) free(p)
|
||||
#define WspiapiSwap(a, b, c) { (c) = (a); (a) = (b); (b) = (c); }
|
||||
#define getaddrinfo WspiapiGetAddrInfo
|
||||
#define getnameinfo WspiapiGetNameInfo
|
||||
#define freeaddrinfo WspiapiFreeAddrInfo
|
||||
|
||||
typedef int (WINAPI *WSPIAPI_PGETADDRINFO) (
|
||||
IN const char *nodename,
|
||||
IN const char *servname,
|
||||
IN const struct addrinfo *hints,
|
||||
OUT struct addrinfo **res);
|
||||
|
||||
typedef int (WINAPI *WSPIAPI_PGETNAMEINFO) (
|
||||
IN const struct sockaddr *sa,
|
||||
IN socklen_t salen,
|
||||
OUT char *host,
|
||||
IN size_t hostlen,
|
||||
OUT char *serv,
|
||||
IN size_t servlen,
|
||||
IN int flags);
|
||||
|
||||
typedef void (WINAPI *WSPIAPI_PFREEADDRINFO) (
|
||||
IN struct addrinfo *ai);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// v4 only versions of getaddrinfo and friends.
|
||||
// NOTE: gai_strerror is inlined in ws2tcpip.h
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
__inline
|
||||
char *
|
||||
WINAPI
|
||||
WspiapiStrdup (
|
||||
IN const char * pszString)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
allocates enough storage via calloc() for a copy of the string,
|
||||
copies the string into the new memory, and returns a pointer to it.
|
||||
|
||||
Arguments
|
||||
pszString string to copy into new memory
|
||||
|
||||
Return Value
|
||||
a pointer to the newly allocated storage with the string in it.
|
||||
NULL if enough memory could not be allocated, or string was NULL.
|
||||
|
||||
--*/
|
||||
{
|
||||
char *pszMemory;
|
||||
|
||||
if (!pszString)
|
||||
return(NULL);
|
||||
|
||||
pszMemory = (char *) WspiapiMalloc(strlen(pszString) + 1);
|
||||
if (!pszMemory)
|
||||
return(NULL);
|
||||
|
||||
return(strcpy(pszMemory, pszString));
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
BOOL
|
||||
WINAPI
|
||||
WspiapiParseV4Address (
|
||||
IN const char * pszAddress,
|
||||
OUT PDWORD pdwAddress)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
get the IPv4 address (in network byte order) from its string
|
||||
representation. the syntax should be a.b.c.d.
|
||||
|
||||
Arguments
|
||||
pszArgument string representation of the IPv4 address
|
||||
ptAddress pointer to the resulting IPv4 address
|
||||
|
||||
Return Value
|
||||
Returns FALSE if there is an error, TRUE for success.
|
||||
|
||||
--*/
|
||||
{
|
||||
DWORD dwAddress = 0;
|
||||
const char *pcNext = NULL;
|
||||
int iCount = 0;
|
||||
|
||||
// ensure there are 3 '.' (periods)
|
||||
for (pcNext = pszAddress; *pcNext != '\0'; pcNext++)
|
||||
if (*pcNext == '.')
|
||||
iCount++;
|
||||
if (iCount != 3)
|
||||
return FALSE;
|
||||
|
||||
// return an error if dwAddress is INADDR_NONE (255.255.255.255)
|
||||
// since this is never a valid argument to getaddrinfo.
|
||||
dwAddress = inet_addr(pszAddress);
|
||||
if (dwAddress == INADDR_NONE)
|
||||
return FALSE;
|
||||
|
||||
*pdwAddress = dwAddress;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
struct addrinfo *
|
||||
WINAPI
|
||||
WspiapiNewAddrInfo (
|
||||
IN int iSocketType,
|
||||
IN int iProtocol,
|
||||
IN WORD wPort,
|
||||
IN DWORD dwAddress)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
allocate an addrinfo structure and populate fields.
|
||||
IPv4 specific internal function, not exported.
|
||||
|
||||
Arguments
|
||||
iSocketType SOCK_*. can be wildcarded (zero).
|
||||
iProtocol IPPROTO_*. can be wildcarded (zero).
|
||||
wPort port number of service (in network order).
|
||||
dwAddress IPv4 address (in network order).
|
||||
|
||||
Return Value
|
||||
returns an addrinfo struct, or NULL if out of memory.
|
||||
|
||||
--*/
|
||||
{
|
||||
struct addrinfo *ptNew;
|
||||
struct sockaddr_in *ptAddress;
|
||||
|
||||
// allocate a new addrinfo structure.
|
||||
ptNew =
|
||||
(struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo));
|
||||
if (!ptNew)
|
||||
return NULL;
|
||||
|
||||
ptAddress =
|
||||
(struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in));
|
||||
if (!ptAddress)
|
||||
{
|
||||
WspiapiFree(ptNew);
|
||||
return NULL;
|
||||
}
|
||||
ptAddress->sin_family = AF_INET;
|
||||
ptAddress->sin_port = wPort;
|
||||
ptAddress->sin_addr.s_addr = dwAddress;
|
||||
|
||||
// fill in the fields...
|
||||
ptNew->ai_family = PF_INET;
|
||||
ptNew->ai_socktype = iSocketType;
|
||||
ptNew->ai_protocol = iProtocol;
|
||||
ptNew->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
ptNew->ai_addr = (struct sockaddr *) ptAddress;
|
||||
|
||||
return ptNew;
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
int
|
||||
WINAPI
|
||||
WspiapiQueryDNS(
|
||||
IN const char *pszNodeName,
|
||||
IN int iSocketType,
|
||||
IN int iProtocol,
|
||||
IN WORD wPort,
|
||||
OUT char *pszAlias,
|
||||
OUT struct addrinfo **pptResult)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
helper routine for WspiapiLookupNode.
|
||||
performs name resolution by querying the DNS for A records.
|
||||
*pptResult would need to be freed if an error is returned.
|
||||
|
||||
Arguments
|
||||
pszNodeName name of node to resolve.
|
||||
iSocketType SOCK_*. can be wildcarded (zero).
|
||||
iProtocol IPPROTO_*. can be wildcarded (zero).
|
||||
wPort port number of service (in network order).
|
||||
pszAlias where to return the alias.
|
||||
pptResult where to return the result.
|
||||
|
||||
Return Value
|
||||
Returns 0 on success, an EAI_* style error value otherwise.
|
||||
|
||||
--*/
|
||||
{
|
||||
struct addrinfo **pptNext = pptResult;
|
||||
struct hostent *ptHost = NULL;
|
||||
char **ppAddresses;
|
||||
|
||||
*pptNext = NULL;
|
||||
pszAlias[0] = '\0';
|
||||
|
||||
ptHost = gethostbyname(pszNodeName);
|
||||
if (ptHost)
|
||||
{
|
||||
if ((ptHost->h_addrtype == AF_INET) &&
|
||||
(ptHost->h_length == sizeof(struct in_addr)))
|
||||
{
|
||||
for (ppAddresses = ptHost->h_addr_list;
|
||||
*ppAddresses != NULL;
|
||||
ppAddresses++)
|
||||
{
|
||||
// create an addrinfo structure...
|
||||
*pptNext = WspiapiNewAddrInfo(
|
||||
iSocketType,
|
||||
iProtocol,
|
||||
wPort,
|
||||
((struct in_addr *) *ppAddresses)->s_addr);
|
||||
if (!*pptNext)
|
||||
return EAI_MEMORY;
|
||||
|
||||
pptNext = &((*pptNext)->ai_next);
|
||||
}
|
||||
}
|
||||
|
||||
// pick up the canonical name.
|
||||
strcpy(pszAlias, ptHost->h_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (WSAGetLastError())
|
||||
{
|
||||
case WSAHOST_NOT_FOUND: return EAI_NONAME;
|
||||
case WSATRY_AGAIN: return EAI_AGAIN;
|
||||
case WSANO_RECOVERY: return EAI_FAIL;
|
||||
case WSANO_DATA: return EAI_NODATA;
|
||||
default: return EAI_NONAME;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
int
|
||||
WINAPI
|
||||
WspiapiLookupNode(
|
||||
IN const char *pszNodeName,
|
||||
IN int iSocketType,
|
||||
IN int iProtocol,
|
||||
IN WORD wPort,
|
||||
IN BOOL bAI_CANONNAME,
|
||||
OUT struct addrinfo **pptResult)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
resolve a nodename and return a list of addrinfo structures.
|
||||
IPv4 specific internal function, not exported.
|
||||
*pptResult would need to be freed if an error is returned.
|
||||
|
||||
NOTE: if bAI_CANONNAME is true, the canonical name should be
|
||||
returned in the first addrinfo structure.
|
||||
|
||||
Arguments
|
||||
pszNodeName name of node to resolve.
|
||||
iSocketType SOCK_*. can be wildcarded (zero).
|
||||
iProtocol IPPROTO_*. can be wildcarded (zero).
|
||||
wPort port number of service (in network order).
|
||||
bAI_CANONNAME whether the AI_CANONNAME flag is set.
|
||||
pptResult where to return result.
|
||||
|
||||
Return Value
|
||||
Returns 0 on success, an EAI_* style error value otherwise.
|
||||
|
||||
--*/
|
||||
{
|
||||
int iError = 0;
|
||||
int iAliasCount = 0;
|
||||
|
||||
char szFQDN1[NI_MAXHOST] = "";
|
||||
char szFQDN2[NI_MAXHOST] = "";
|
||||
char *pszName = szFQDN1;
|
||||
char *pszAlias = szFQDN2;
|
||||
char *pszScratch = NULL;
|
||||
strcpy(pszName, pszNodeName);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
iError = WspiapiQueryDNS(pszNodeName,
|
||||
iSocketType,
|
||||
iProtocol,
|
||||
wPort,
|
||||
pszAlias,
|
||||
pptResult);
|
||||
if (iError)
|
||||
break;
|
||||
|
||||
// if we found addresses, then we are done.
|
||||
if (*pptResult)
|
||||
break;
|
||||
|
||||
// stop infinite loops due to DNS misconfiguration. there appears
|
||||
// to be no particular recommended limit in RFCs 1034 and 1035.
|
||||
if ((!strlen(pszAlias)) ||
|
||||
(!strcmp(pszName, pszAlias)) ||
|
||||
(++iAliasCount == 16))
|
||||
{
|
||||
iError = EAI_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
// there was a new CNAME, look again.
|
||||
WspiapiSwap(pszName, pszAlias, pszScratch);
|
||||
}
|
||||
|
||||
if (!iError && bAI_CANONNAME)
|
||||
{
|
||||
(*pptResult)->ai_canonname = WspiapiStrdup(pszAlias);
|
||||
if (!(*pptResult)->ai_canonname)
|
||||
iError = EAI_MEMORY;
|
||||
}
|
||||
|
||||
return iError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
int
|
||||
WINAPI
|
||||
WspiapiClone (
|
||||
IN WORD wPort,
|
||||
IN struct addrinfo *ptResult)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
clone every addrinfo structure in ptResult for the UDP service.
|
||||
ptResult would need to be freed if an error is returned.
|
||||
|
||||
Arguments
|
||||
wPort port number of UDP service.
|
||||
ptResult list of addrinfo structures, each
|
||||
of whose node needs to be cloned.
|
||||
|
||||
Return Value
|
||||
Returns 0 on success, an EAI_MEMORY on allocation failure.
|
||||
|
||||
--*/
|
||||
{
|
||||
struct addrinfo *ptNext = NULL;
|
||||
struct addrinfo *ptNew = NULL;
|
||||
|
||||
for (ptNext = ptResult; ptNext != NULL; )
|
||||
{
|
||||
// create an addrinfo structure...
|
||||
ptNew = WspiapiNewAddrInfo(
|
||||
SOCK_DGRAM,
|
||||
ptNext->ai_protocol,
|
||||
wPort,
|
||||
((struct sockaddr_in *) ptNext->ai_addr)->sin_addr.s_addr);
|
||||
if (!ptNew)
|
||||
break;
|
||||
|
||||
// link the cloned addrinfo
|
||||
ptNew->ai_next = ptNext->ai_next;
|
||||
ptNext->ai_next = ptNew;
|
||||
ptNext = ptNew->ai_next;
|
||||
}
|
||||
|
||||
if (ptNext != NULL)
|
||||
return EAI_MEMORY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
void
|
||||
WINAPI
|
||||
WspiapiLegacyFreeAddrInfo (
|
||||
IN struct addrinfo *ptHead)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
Free an addrinfo structure (or chain of structures).
|
||||
As specified in RFC 2553, Section 6.4.
|
||||
|
||||
Arguments
|
||||
ptHead structure (chain) to free
|
||||
|
||||
--*/
|
||||
{
|
||||
struct addrinfo *ptNext; // next strcture to free
|
||||
|
||||
for (ptNext = ptHead; ptNext != NULL; ptNext = ptHead)
|
||||
{
|
||||
if (ptNext->ai_canonname)
|
||||
WspiapiFree(ptNext->ai_canonname);
|
||||
|
||||
if (ptNext->ai_addr)
|
||||
WspiapiFree(ptNext->ai_addr);
|
||||
|
||||
ptHead = ptNext->ai_next;
|
||||
WspiapiFree(ptNext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
int
|
||||
WINAPI
|
||||
WspiapiLegacyGetAddrInfo(
|
||||
IN const char *pszNodeName,
|
||||
IN const char *pszServiceName,
|
||||
IN const struct addrinfo *ptHints,
|
||||
OUT struct addrinfo **pptResult)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
Protocol-independent name-to-address translation.
|
||||
As specified in RFC 2553, Section 6.4.
|
||||
This is the hacked version that only supports IPv4.
|
||||
|
||||
Arguments
|
||||
pszNodeName node name to lookup.
|
||||
pszServiceName service name to lookup.
|
||||
ptHints hints about how to process request.
|
||||
pptResult where to return result.
|
||||
|
||||
Return Value
|
||||
returns zero if successful, an EAI_* error code if not.
|
||||
|
||||
--*/
|
||||
{
|
||||
int iError = 0;
|
||||
int iFlags = 0;
|
||||
int iFamily = PF_UNSPEC;
|
||||
int iSocketType = 0;
|
||||
int iProtocol = 0;
|
||||
WORD wPort = 0;
|
||||
DWORD dwAddress = 0;
|
||||
|
||||
struct servent *ptService = NULL;
|
||||
char *pc = NULL;
|
||||
BOOL bClone = FALSE;
|
||||
WORD wTcpPort = 0;
|
||||
WORD wUdpPort = 0;
|
||||
|
||||
|
||||
// initialize pptResult with default return value.
|
||||
*pptResult = NULL;
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// validate arguments...
|
||||
//
|
||||
|
||||
// both the node name and the service name can't be NULL.
|
||||
if ((!pszNodeName) && (!pszServiceName))
|
||||
return EAI_NONAME;
|
||||
|
||||
// validate hints.
|
||||
if (ptHints)
|
||||
{
|
||||
// all members other than ai_flags, ai_family, ai_socktype
|
||||
// and ai_protocol must be zero or a null pointer.
|
||||
if ((ptHints->ai_addrlen != 0) ||
|
||||
(ptHints->ai_canonname != NULL) ||
|
||||
(ptHints->ai_addr != NULL) ||
|
||||
(ptHints->ai_next != NULL))
|
||||
{
|
||||
return EAI_FAIL;
|
||||
}
|
||||
|
||||
// the spec has the "bad flags" error code, so presumably we
|
||||
// should check something here. insisting that there aren't
|
||||
// any unspecified flags set would break forward compatibility,
|
||||
// however. so we just check for non-sensical combinations.
|
||||
//
|
||||
// we cannot come up with a canonical name given a null node name.
|
||||
iFlags = ptHints->ai_flags;
|
||||
if ((iFlags & AI_CANONNAME) && !pszNodeName)
|
||||
return EAI_BADFLAGS;
|
||||
|
||||
// we only support a limited number of protocol families.
|
||||
iFamily = ptHints->ai_family;
|
||||
if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
|
||||
return EAI_FAMILY;
|
||||
|
||||
// we only support only these socket types.
|
||||
iSocketType = ptHints->ai_socktype;
|
||||
if ((iSocketType != 0) &&
|
||||
(iSocketType != SOCK_STREAM) &&
|
||||
(iSocketType != SOCK_DGRAM) &&
|
||||
(iSocketType != SOCK_RAW))
|
||||
return EAI_SOCKTYPE;
|
||||
|
||||
// REVIEW: What if ai_socktype and ai_protocol are at odds?
|
||||
iProtocol = ptHints->ai_protocol;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// do service lookup...
|
||||
|
||||
if (pszServiceName)
|
||||
{
|
||||
wPort = (WORD) strtoul(pszServiceName, &pc, 10);
|
||||
if (*pc == '\0') // numeric port string
|
||||
{
|
||||
wPort = wTcpPort = wUdpPort = htons(wPort);
|
||||
if (iSocketType == 0)
|
||||
{
|
||||
bClone = TRUE;
|
||||
iSocketType = SOCK_STREAM;
|
||||
}
|
||||
}
|
||||
else // non numeric port string
|
||||
{
|
||||
if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
|
||||
{
|
||||
ptService = getservbyname(pszServiceName, "udp");
|
||||
if (ptService)
|
||||
wPort = wUdpPort = ptService->s_port;
|
||||
}
|
||||
|
||||
if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
|
||||
{
|
||||
ptService = getservbyname(pszServiceName, "tcp");
|
||||
if (ptService)
|
||||
wPort = wTcpPort = ptService->s_port;
|
||||
}
|
||||
|
||||
// assumes 0 is an invalid service port...
|
||||
if (wPort == 0) // no service exists
|
||||
return (iSocketType ? EAI_SERVICE : EAI_NONAME);
|
||||
|
||||
if (iSocketType == 0)
|
||||
{
|
||||
// if both tcp and udp, process tcp now & clone udp later.
|
||||
iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
|
||||
bClone = (wTcpPort && wUdpPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// do node name lookup...
|
||||
|
||||
// if we weren't given a node name,
|
||||
// return the wildcard or loopback address (depending on AI_PASSIVE).
|
||||
//
|
||||
// if we have a numeric host address string,
|
||||
// return the binary address.
|
||||
//
|
||||
if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress)))
|
||||
{
|
||||
if (!pszNodeName)
|
||||
{
|
||||
dwAddress = htonl((iFlags & AI_PASSIVE)
|
||||
? INADDR_ANY
|
||||
: INADDR_LOOPBACK);
|
||||
}
|
||||
|
||||
// create an addrinfo structure...
|
||||
*pptResult =
|
||||
WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
|
||||
if (!(*pptResult))
|
||||
iError = EAI_MEMORY;
|
||||
|
||||
if (!iError && pszNodeName)
|
||||
{
|
||||
// implementation specific behavior: set AI_NUMERICHOST
|
||||
// to indicate that we got a numeric host address string.
|
||||
(*pptResult)->ai_flags |= AI_NUMERICHOST;
|
||||
|
||||
// return the numeric address string as the canonical name
|
||||
if (iFlags & AI_CANONNAME)
|
||||
{
|
||||
(*pptResult)->ai_canonname =
|
||||
WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));
|
||||
if (!(*pptResult)->ai_canonname)
|
||||
iError = EAI_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if we do not have a numeric host address string and
|
||||
// AI_NUMERICHOST flag is set, return an error!
|
||||
else if (iFlags & AI_NUMERICHOST)
|
||||
{
|
||||
iError = EAI_NONAME;
|
||||
}
|
||||
|
||||
|
||||
// since we have a non-numeric node name,
|
||||
// we have to do a regular node name lookup.
|
||||
else
|
||||
{
|
||||
iError = WspiapiLookupNode(pszNodeName,
|
||||
iSocketType,
|
||||
iProtocol,
|
||||
wPort,
|
||||
(iFlags & AI_CANONNAME),
|
||||
pptResult);
|
||||
}
|
||||
|
||||
if (!iError && bClone)
|
||||
{
|
||||
iError = WspiapiClone(wUdpPort, *pptResult);
|
||||
}
|
||||
|
||||
if (iError)
|
||||
{
|
||||
WspiapiLegacyFreeAddrInfo(*pptResult);
|
||||
*pptResult = NULL;
|
||||
}
|
||||
|
||||
return (iError);
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
int
|
||||
WINAPI
|
||||
WspiapiLegacyGetNameInfo(
|
||||
IN const struct sockaddr *ptSocketAddress,
|
||||
IN socklen_t tSocketLength,
|
||||
OUT char *pszNodeName,
|
||||
IN size_t tNodeLength,
|
||||
OUT char *pszServiceName,
|
||||
IN size_t tServiceLength,
|
||||
IN int iFlags)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
protocol-independent address-to-name translation.
|
||||
as specified in RFC 2553, Section 6.5.
|
||||
this is the hacked version that only supports IPv4.
|
||||
|
||||
Arguments
|
||||
ptSocketAddress socket address to translate.
|
||||
tSocketLength length of above socket address.
|
||||
pszNodeName where to return the node name.
|
||||
tNodeLength size of above buffer.
|
||||
pszServiceName where to return the service name.
|
||||
tServiceLength size of above buffer.
|
||||
iFlags flags of type NI_*.
|
||||
|
||||
Return Value
|
||||
returns zero if successful, an EAI_* error code if not.
|
||||
|
||||
--*/
|
||||
{
|
||||
struct servent *ptService;
|
||||
WORD wPort;
|
||||
char szBuffer[] = "65535";
|
||||
char *pszService = szBuffer;
|
||||
|
||||
struct hostent *ptHost;
|
||||
struct in_addr tAddress;
|
||||
char *pszNode = NULL;
|
||||
char *pc = NULL;
|
||||
|
||||
|
||||
// sanity check ptSocketAddress and tSocketLength.
|
||||
if (!ptSocketAddress)
|
||||
return EAI_FAIL;
|
||||
|
||||
if ((ptSocketAddress->sa_family != AF_INET) ||
|
||||
(tSocketLength != sizeof(struct sockaddr_in)))
|
||||
{
|
||||
return EAI_FAMILY;
|
||||
}
|
||||
|
||||
if (!(pszNodeName && tNodeLength) &&
|
||||
!(pszServiceName && tServiceLength))
|
||||
{
|
||||
return EAI_NONAME;
|
||||
}
|
||||
|
||||
// the draft has the "bad flags" error code, so presumably we
|
||||
// should check something here. insisting that there aren't
|
||||
// any unspecified flags set would break forward compatibility,
|
||||
// however. so we just check for non-sensical combinations.
|
||||
if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD))
|
||||
{
|
||||
return EAI_BADFLAGS;
|
||||
}
|
||||
|
||||
// translate the port to a service name (if requested).
|
||||
if (pszServiceName && tServiceLength)
|
||||
{
|
||||
wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;
|
||||
|
||||
if (iFlags & NI_NUMERICSERV)
|
||||
{
|
||||
// return numeric form of the address.
|
||||
sprintf(szBuffer, "%u", ntohs(wPort));
|
||||
}
|
||||
else
|
||||
{
|
||||
// return service name corresponding to port.
|
||||
ptService = getservbyport(wPort,
|
||||
(iFlags & NI_DGRAM) ? "udp" : NULL);
|
||||
if (ptService && ptService->s_name)
|
||||
{
|
||||
// lookup successful.
|
||||
pszService = ptService->s_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
// DRAFT: return numeric form of the port!
|
||||
sprintf(szBuffer, "%u", ntohs(wPort));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (tServiceLength > strlen(pszService))
|
||||
strcpy(pszServiceName, pszService);
|
||||
else
|
||||
return EAI_FAIL;
|
||||
}
|
||||
|
||||
|
||||
// translate the address to a node name (if requested).
|
||||
if (pszNodeName && tNodeLength)
|
||||
{
|
||||
// this is the IPv4-only version, so we have an IPv4 address.
|
||||
tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;
|
||||
|
||||
if (iFlags & NI_NUMERICHOST)
|
||||
{
|
||||
// return numeric form of the address.
|
||||
pszNode = inet_ntoa(tAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
// return node name corresponding to address.
|
||||
ptHost = gethostbyaddr((char *) &tAddress,
|
||||
sizeof(struct in_addr),
|
||||
AF_INET);
|
||||
if (ptHost && ptHost->h_name)
|
||||
{
|
||||
// DNS lookup successful.
|
||||
// stop copying at a "." if NI_NOFQDN is specified.
|
||||
pszNode = ptHost->h_name;
|
||||
if ((iFlags & NI_NOFQDN) && (pc = strchr(pszNode, '.')))
|
||||
*pc = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// DNS lookup failed. return numeric form of the address.
|
||||
if (iFlags & NI_NAMEREQD)
|
||||
{
|
||||
switch (WSAGetLastError())
|
||||
{
|
||||
case WSAHOST_NOT_FOUND: return EAI_NONAME;
|
||||
case WSATRY_AGAIN: return EAI_AGAIN;
|
||||
case WSANO_RECOVERY: return EAI_FAIL;
|
||||
default: return EAI_NONAME;
|
||||
}
|
||||
}
|
||||
else
|
||||
pszNode = inet_ntoa(tAddress);
|
||||
}
|
||||
}
|
||||
|
||||
if (tNodeLength > strlen(pszNode))
|
||||
strcpy(pszNodeName, pszNode);
|
||||
else
|
||||
return EAI_FAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char const *pszName;
|
||||
FARPROC pfAddress;
|
||||
} WSPIAPI_FUNCTION;
|
||||
|
||||
#define WSPIAPI_FUNCTION_ARRAY \
|
||||
{ \
|
||||
"getaddrinfo", (FARPROC) WspiapiLegacyGetAddrInfo, \
|
||||
"getnameinfo", (FARPROC) WspiapiLegacyGetNameInfo, \
|
||||
"freeaddrinfo", (FARPROC) WspiapiLegacyFreeAddrInfo, \
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
FARPROC
|
||||
WINAPI
|
||||
WspiapiLoad(
|
||||
IN WORD wFunction)
|
||||
/*++
|
||||
|
||||
Routine Description
|
||||
try to locate the address family independent name resolution routines
|
||||
(i.e. getaddrinfo, getnameinfo, freeaddrinfo, gai_strerror).
|
||||
|
||||
Locks
|
||||
this function call is not synchronized. hence the library containing
|
||||
the routines might be loaded multiple times. another option is to
|
||||
synchronize through a spin lock using a static local variable and the
|
||||
InterlockedExchange operation.
|
||||
|
||||
|
||||
Arguments
|
||||
wFunction ordinal # of the function to get the pointer to
|
||||
0 getaddrinfo
|
||||
1 getnameinfo
|
||||
2 freeaddrinfo
|
||||
|
||||
Return Value
|
||||
address of the library/legacy routine
|
||||
|
||||
--*/
|
||||
{
|
||||
HMODULE hLibrary = NULL;
|
||||
|
||||
// these static variables store state across calls, across threads.
|
||||
static BOOL bInitialized = FALSE;
|
||||
static WSPIAPI_FUNCTION rgtGlobal[] = WSPIAPI_FUNCTION_ARRAY;
|
||||
static const int iNumGlobal = (sizeof(rgtGlobal) /
|
||||
sizeof(WSPIAPI_FUNCTION));
|
||||
|
||||
// we overwrite rgtGlobal only if all routines exist in library.
|
||||
WSPIAPI_FUNCTION rgtLocal[] = WSPIAPI_FUNCTION_ARRAY;
|
||||
FARPROC fScratch = NULL;
|
||||
int i = 0;
|
||||
|
||||
|
||||
if (bInitialized) // WspiapiLoad has already been called once
|
||||
return (rgtGlobal[wFunction].pfAddress);
|
||||
|
||||
do // breakout loop
|
||||
{
|
||||
// in Whistler and beyond...
|
||||
// the routines are present in the WinSock 2 library (ws2_32.dll).
|
||||
// printf("Looking in ws2_32 for getaddrinfo...\n");
|
||||
hLibrary = LoadLibraryA("ws2_32");
|
||||
if (hLibrary != NULL)
|
||||
{
|
||||
fScratch = GetProcAddress(hLibrary, "getaddrinfo");
|
||||
if (fScratch == NULL)
|
||||
{
|
||||
FreeLibrary(hLibrary);
|
||||
hLibrary = NULL;
|
||||
}
|
||||
}
|
||||
if (hLibrary != NULL)
|
||||
break;
|
||||
|
||||
|
||||
// in the IPv6 Technology Preview...
|
||||
// the routines are present in the IPv6 WinSock library (wship6.dll).
|
||||
// printf("Looking in wship6 for getaddrinfo...\n");
|
||||
hLibrary = LoadLibraryA("wship6");
|
||||
if (hLibrary != NULL)
|
||||
{
|
||||
fScratch = GetProcAddress(hLibrary, "getaddrinfo");
|
||||
if (fScratch == NULL)
|
||||
{
|
||||
FreeLibrary(hLibrary);
|
||||
hLibrary = NULL;
|
||||
}
|
||||
}
|
||||
} while (FALSE);
|
||||
|
||||
|
||||
if (hLibrary != NULL)
|
||||
{
|
||||
// use routines from this library...
|
||||
// since getaddrinfo is here, we expect all routines to be here,
|
||||
// but will fall back to IPv4-only if any of them is missing.
|
||||
for (i = 0; i < iNumGlobal; i++)
|
||||
{
|
||||
rgtLocal[i].pfAddress
|
||||
= GetProcAddress(hLibrary, rgtLocal[i].pszName);
|
||||
if (rgtLocal[i].pfAddress == NULL)
|
||||
{
|
||||
FreeLibrary(hLibrary);
|
||||
hLibrary = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hLibrary != NULL)
|
||||
{
|
||||
// printf("found!\n");
|
||||
for (i = 0; i < iNumGlobal; i++)
|
||||
rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;
|
||||
}
|
||||
}
|
||||
|
||||
bInitialized = TRUE;
|
||||
return (rgtGlobal[wFunction].pfAddress);
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
int
|
||||
WINAPI
|
||||
WspiapiGetAddrInfo(
|
||||
IN const char *nodename,
|
||||
IN const char *servname,
|
||||
IN const struct addrinfo *hints,
|
||||
OUT struct addrinfo **res)
|
||||
{
|
||||
static WSPIAPI_PGETADDRINFO pfGetAddrInfo = NULL;
|
||||
|
||||
if (!pfGetAddrInfo)
|
||||
pfGetAddrInfo = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);
|
||||
return ((*pfGetAddrInfo)
|
||||
(nodename, servname, hints, res));
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
int
|
||||
WINAPI
|
||||
WspiapiGetNameInfo (
|
||||
IN const struct sockaddr *sa,
|
||||
IN socklen_t salen,
|
||||
OUT char *host,
|
||||
IN size_t hostlen,
|
||||
OUT char *serv,
|
||||
IN size_t servlen,
|
||||
IN int flags)
|
||||
{
|
||||
static WSPIAPI_PGETNAMEINFO pfGetNameInfo = NULL;
|
||||
|
||||
if (!pfGetNameInfo)
|
||||
pfGetNameInfo = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);
|
||||
return ((*pfGetNameInfo)
|
||||
(sa, salen, host, hostlen, serv, servlen, flags));
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
void
|
||||
WINAPI
|
||||
WspiapiFreeAddrInfo (
|
||||
IN struct addrinfo *ai)
|
||||
{
|
||||
static WSPIAPI_PFREEADDRINFO pfFreeAddrInfo = NULL;
|
||||
|
||||
if (!pfFreeAddrInfo)
|
||||
pfFreeAddrInfo = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);
|
||||
(*pfFreeAddrInfo)(ai);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _WSPIAPI_H_
|
||||
@@ -1,6 +0,0 @@
|
||||
Name: ${APPLICATION_NAME}
|
||||
Description: The SSH Library
|
||||
Version: ${APPLICATION_VERSION}
|
||||
Libs: -L${LIB_INSTALL_DIR} -lssh
|
||||
Cflags: -I${INCLUDE_INSTALL_DIR}
|
||||
|
||||
@@ -2,13 +2,13 @@ project(libssh-library C)
|
||||
|
||||
set(LIBSSH_PUBLIC_INCLUDE_DIRS
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}
|
||||
CACHE INTERNAL "libssh public include directories"
|
||||
)
|
||||
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${CMAKE_BINARY_DIR}
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
${GCRYPT_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
@@ -25,7 +25,6 @@ if (WITH_STATIC_LIB)
|
||||
endif (WITH_STATIC_LIB)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_REQUIRED_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
)
|
||||
|
||||
@@ -36,14 +35,7 @@ if (WIN32)
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
if (HAVE_LIBSOCKET)
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
socket
|
||||
)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
|
||||
if (OPENSSL_LIBRARIES)
|
||||
if (CRYPTO_LIBRARY)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
@@ -51,9 +43,9 @@ if (OPENSSL_LIBRARIES)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARY}
|
||||
)
|
||||
endif (OPENSSL_LIBRARIES)
|
||||
endif (CRYPTO_LIBRARY)
|
||||
|
||||
if (GCRYPT_LIBRARY)
|
||||
set(LIBSSH_PRIVATE_INCLUDE_DIRS
|
||||
@@ -67,51 +59,37 @@ if (GCRYPT_LIBRARY)
|
||||
)
|
||||
endif (GCRYPT_LIBRARY)
|
||||
|
||||
set(LIBSSH_LINK_LIBRARIES
|
||||
${LIBSSH_LINK_LIBRARIES}
|
||||
CACHE INTERNAL "libssh link libraries"
|
||||
)
|
||||
|
||||
set(libssh_SRCS
|
||||
agent.c
|
||||
auth.c
|
||||
base64.c
|
||||
buffer.c
|
||||
callbacks.c
|
||||
channels.c
|
||||
client.c
|
||||
config.c
|
||||
connect.c
|
||||
crc32.c
|
||||
crypt.c
|
||||
dh.c
|
||||
error.c
|
||||
getpass.c
|
||||
gcrypt_missing.c
|
||||
gzip.c
|
||||
init.c
|
||||
kex.c
|
||||
keyfiles.c
|
||||
keys.c
|
||||
known_hosts.c
|
||||
legacy.c
|
||||
libcrypto.c
|
||||
libgcrypt.c
|
||||
log.c
|
||||
match.c
|
||||
messages.c
|
||||
misc.c
|
||||
options.c
|
||||
packet.c
|
||||
pcap.c
|
||||
pki.c
|
||||
poll.c
|
||||
session.c
|
||||
scp.c
|
||||
socket.c
|
||||
string.c
|
||||
threads.c
|
||||
wrapper.c
|
||||
libssh.map
|
||||
)
|
||||
|
||||
if (WITH_SFTP)
|
||||
@@ -133,7 +111,6 @@ if (WITH_SSH1)
|
||||
${libssh_SRCS}
|
||||
auth1.c
|
||||
channels1.c
|
||||
packet1.c
|
||||
)
|
||||
endif (WITH_SSH1)
|
||||
|
||||
@@ -141,7 +118,6 @@ if (WITH_SERVER)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
server.c
|
||||
bind.c
|
||||
)
|
||||
endif (WITH_SERVER)
|
||||
|
||||
@@ -163,32 +139,22 @@ set_target_properties(
|
||||
${LIBRARY_SOVERSION}
|
||||
OUTPUT_NAME
|
||||
ssh
|
||||
DEFINE_SYMBOL
|
||||
LIBSSH_EXPORTS
|
||||
)
|
||||
|
||||
if (WITH_VISIBILITY_HIDDEN)
|
||||
set_target_properties(${LIBSSH_SHARED_LIBRARY} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
endif (WITH_VISIBILITY_HIDDEN)
|
||||
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
${LIBSSH_SHARED_LIBRARY}
|
||||
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
COMPONENT libraries
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}
|
||||
COMPONENT
|
||||
libraries
|
||||
)
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
add_library(${LIBSSH_STATIC_LIBRARY} STATIC ${libssh_SRCS})
|
||||
|
||||
if (MSVC)
|
||||
set(OUTPUT_SUFFIX static)
|
||||
else (MSVC)
|
||||
set(OUTPUT_SUFFIX )
|
||||
endif (MSVC)
|
||||
target_link_libraries(${LIBSSH_STATIC_LIBRARY} ${LIBSSH_LINK_LIBRARIES})
|
||||
|
||||
set_target_properties(
|
||||
${LIBSSH_STATIC_LIBRARY}
|
||||
PROPERTIES
|
||||
@@ -198,29 +164,15 @@ if (WITH_STATIC_LIB)
|
||||
${LIBRARY_SOVERSION}
|
||||
OUTPUT_NAME
|
||||
ssh
|
||||
ARCHIVE_OUTPUT_DIRECTORY
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
set_target_properties(
|
||||
${LIBSSH_STATIC_LIBRARY}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-DLIBSSH_STATIC"
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
${LIBSSH_STATIC_LIBRARY}
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
|
||||
${LIB_INSTALL_DIR}
|
||||
COMPONENT
|
||||
libraries
|
||||
)
|
||||
endif (WITH_STATIC_LIB)
|
||||
|
||||
if (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
add_subdirectory(threads)
|
||||
endif (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
@@ -27,7 +27,7 @@
|
||||
* How does the ssh-agent work?
|
||||
*
|
||||
* a) client sends a request to get a list of all keys
|
||||
* the agent returns the count and all public keys
|
||||
* the agent returns the cound and all public keys
|
||||
* b) iterate over them to check if the server likes one
|
||||
* c) the client sends a sign request to the agent
|
||||
* type, pubkey as blob, data to sign, flags
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -49,44 +50,39 @@
|
||||
|
||||
#include "libssh/agent.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/socket.h"
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/keys.h"
|
||||
#include "libssh/poll.h"
|
||||
|
||||
/* macro to check for "agent failure" message */
|
||||
#define agent_failed(x) \
|
||||
(((x) == SSH_AGENT_FAILURE) || ((x) == SSH_COM_AGENT2_FAILURE) || \
|
||||
((x) == SSH2_AGENT_FAILURE))
|
||||
|
||||
static uint32_t agent_get_u32(const void *vp) {
|
||||
const uint8_t *p = (const uint8_t *)vp;
|
||||
uint32_t v;
|
||||
static u32 agent_get_u32(const void *vp) {
|
||||
const u8 *p = (const u8 *)vp;
|
||||
u32 v;
|
||||
|
||||
v = (uint32_t)p[0] << 24;
|
||||
v |= (uint32_t)p[1] << 16;
|
||||
v |= (uint32_t)p[2] << 8;
|
||||
v |= (uint32_t)p[3];
|
||||
v = (u32)p[0] << 24;
|
||||
v |= (u32)p[1] << 16;
|
||||
v |= (u32)p[2] << 8;
|
||||
v |= (u32)p[3];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static void agent_put_u32(void *vp, uint32_t v) {
|
||||
uint8_t *p = (uint8_t *)vp;
|
||||
static void agent_put_u32(void *vp, u32 v) {
|
||||
u8 *p = (u8 *)vp;
|
||||
|
||||
p[0] = (uint8_t)(v >> 24) & 0xff;
|
||||
p[1] = (uint8_t)(v >> 16) & 0xff;
|
||||
p[2] = (uint8_t)(v >> 8) & 0xff;
|
||||
p[3] = (uint8_t)v & 0xff;
|
||||
p[0] = (u8)(v >> 24) & 0xff;
|
||||
p[1] = (u8)(v >> 16) & 0xff;
|
||||
p[2] = (u8)(v >> 8) & 0xff;
|
||||
p[3] = (u8)v & 0xff;
|
||||
}
|
||||
|
||||
static size_t atomicio(ssh_socket s, void *buf, size_t n, int do_read) {
|
||||
static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) {
|
||||
char *b = buf;
|
||||
size_t pos = 0;
|
||||
ssize_t res;
|
||||
ssh_pollfd_t pfd;
|
||||
socket_t fd = ssh_socket_get_fd_in(s);
|
||||
struct pollfd pfd;
|
||||
int fd = ssh_socket_get_fd(s);
|
||||
|
||||
pfd.fd = fd;
|
||||
pfd.events = do_read ? POLLIN : POLLOUT;
|
||||
@@ -107,7 +103,7 @@ static size_t atomicio(ssh_socket s, void *buf, size_t n, int do_read) {
|
||||
#else
|
||||
if (errno == EAGAIN) {
|
||||
#endif
|
||||
(void) ssh_poll(&pfd, 1, -1);
|
||||
(void) poll(&pfd, 1, -1);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
@@ -122,10 +118,10 @@ static size_t atomicio(ssh_socket s, void *buf, size_t n, int do_read) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
ssh_agent agent_new(struct ssh_session_struct *session) {
|
||||
ssh_agent agent = NULL;
|
||||
AGENT *agent_new(struct ssh_session *session) {
|
||||
AGENT *agent = NULL;
|
||||
|
||||
agent = malloc(sizeof(struct ssh_agent_struct));
|
||||
agent = malloc(sizeof(AGENT));
|
||||
if (agent == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -141,7 +137,7 @@ ssh_agent agent_new(struct ssh_session_struct *session) {
|
||||
return agent;
|
||||
}
|
||||
|
||||
void agent_close(struct ssh_agent_struct *agent) {
|
||||
void agent_close(struct agent_struct *agent) {
|
||||
if (agent == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -151,10 +147,10 @@ void agent_close(struct ssh_agent_struct *agent) {
|
||||
}
|
||||
}
|
||||
|
||||
void agent_free(ssh_agent agent) {
|
||||
void agent_free(AGENT *agent) {
|
||||
if (agent) {
|
||||
if (agent->ident) {
|
||||
ssh_buffer_free(agent->ident);
|
||||
buffer_free(agent->ident);
|
||||
}
|
||||
if (agent->sock) {
|
||||
agent_close(agent);
|
||||
@@ -164,7 +160,7 @@ void agent_free(ssh_agent agent) {
|
||||
}
|
||||
}
|
||||
|
||||
static int agent_connect(ssh_session session) {
|
||||
static int agent_connect(SSH_SESSION *session) {
|
||||
const char *auth_sock = NULL;
|
||||
|
||||
if (session == NULL || session->agent == NULL) {
|
||||
@@ -184,7 +180,7 @@ static int agent_connect(ssh_session session) {
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int agent_decode_reply(struct ssh_session_struct *session, int type) {
|
||||
static int agent_decode_reply(struct ssh_session *session, int type) {
|
||||
switch (type) {
|
||||
case SSH_AGENT_FAILURE:
|
||||
case SSH2_AGENT_FAILURE:
|
||||
@@ -203,18 +199,21 @@ static int agent_decode_reply(struct ssh_session_struct *session, int type) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static int agent_talk(struct ssh_session_struct *session,
|
||||
struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) {
|
||||
uint32_t len = 0;
|
||||
uint8_t payload[1024] = {0};
|
||||
static int agent_talk(struct ssh_session *session,
|
||||
struct buffer_struct *request, struct buffer_struct *reply) {
|
||||
u32 len = 0;
|
||||
u8 payload[1024] = {0};
|
||||
|
||||
len = buffer_get_rest_len(request);
|
||||
len = buffer_get_len(request);
|
||||
ssh_log(session, SSH_LOG_PACKET, "agent_talk - len of request: %u", len);
|
||||
agent_put_u32(payload, len);
|
||||
|
||||
/* send length and then the request packet */
|
||||
if (atomicio(session->agent->sock, payload, 4, 0) == 4) {
|
||||
if (atomicio(session->agent->sock, buffer_get_rest(request), len, 0)
|
||||
buffer_get_data(request, payload, len);
|
||||
ssh_log(session, SSH_LOG_PACKET,
|
||||
"agent_talk - sending request, payload[0] = %u", payload[0]);
|
||||
if (atomicio(session->agent->sock, payload, len, 0)
|
||||
!= len) {
|
||||
ssh_log(session, SSH_LOG_PACKET, "atomicio sending request failed: %s",
|
||||
strerror(errno));
|
||||
@@ -263,12 +262,12 @@ static int agent_talk(struct ssh_session_struct *session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
ssh_buffer request = NULL;
|
||||
ssh_buffer reply = NULL;
|
||||
int agent_get_ident_count(struct ssh_session *session) {
|
||||
BUFFER *request = NULL;
|
||||
BUFFER *reply = NULL;
|
||||
unsigned int type = 0;
|
||||
unsigned int c1 = 0, c2 = 0;
|
||||
uint8_t buf[4] = {0};
|
||||
u8 buf[4] = {0};
|
||||
|
||||
switch (session->version) {
|
||||
case 1:
|
||||
@@ -284,26 +283,26 @@ int agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
}
|
||||
|
||||
/* send message to the agent requesting the list of identities */
|
||||
request = ssh_buffer_new();
|
||||
request = buffer_new();
|
||||
if (buffer_add_u8(request, c1) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
||||
return -1;
|
||||
}
|
||||
|
||||
reply = ssh_buffer_new();
|
||||
reply = buffer_new();
|
||||
if (reply == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (agent_talk(session, request, reply) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
buffer_free(request);
|
||||
return 0;
|
||||
}
|
||||
ssh_buffer_free(request);
|
||||
buffer_free(request);
|
||||
|
||||
/* get message type and verify the answer */
|
||||
buffer_get_u8(reply, (uint8_t *) &type);
|
||||
buffer_get_u8(reply, (u8 *) &type);
|
||||
ssh_log(session, SSH_LOG_PACKET,
|
||||
"agent_ident_count - answer type: %d, expected answer: %d",
|
||||
type, c2);
|
||||
@@ -315,7 +314,7 @@ int agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_get_u32(reply, (uint32_t *) buf);
|
||||
buffer_get_u32(reply, (u32 *) buf);
|
||||
session->agent->count = agent_get_u32(buf);
|
||||
ssh_log(session, SSH_LOG_PACKET, "agent_ident_count - count: %d",
|
||||
session->agent->count);
|
||||
@@ -323,12 +322,12 @@ int agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Too many identities in authentication reply: %d",
|
||||
session->agent->count);
|
||||
ssh_buffer_free(reply);
|
||||
buffer_free(reply);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (session->agent->ident) {
|
||||
buffer_reinit(session->agent->ident);
|
||||
buffer_free(session->agent->ident);
|
||||
}
|
||||
session->agent->ident = reply;
|
||||
|
||||
@@ -336,7 +335,7 @@ int agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
}
|
||||
|
||||
/* caller has to free commment */
|
||||
struct ssh_public_key_struct *agent_get_first_ident(struct ssh_session_struct *session,
|
||||
struct public_key_struct *agent_get_first_ident(struct ssh_session *session,
|
||||
char **comment) {
|
||||
if (agent_get_ident_count(session) > 0) {
|
||||
return agent_get_next_ident(session, comment);
|
||||
@@ -346,11 +345,11 @@ struct ssh_public_key_struct *agent_get_first_ident(struct ssh_session_struct *s
|
||||
}
|
||||
|
||||
/* caller has to free commment */
|
||||
struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struct *session,
|
||||
struct public_key_struct *agent_get_next_ident(struct ssh_session *session,
|
||||
char **comment) {
|
||||
struct ssh_public_key_struct *pubkey = NULL;
|
||||
struct ssh_string_struct *blob = NULL;
|
||||
struct ssh_string_struct *tmp = NULL;
|
||||
struct public_key_struct *pubkey = NULL;
|
||||
struct string_struct *blob = NULL;
|
||||
struct string_struct *tmp = NULL;
|
||||
|
||||
if (session->agent->count == 0) {
|
||||
return NULL;
|
||||
@@ -369,24 +368,24 @@ struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struct *se
|
||||
/* get the comment */
|
||||
tmp = buffer_get_ssh_string(session->agent->ident);
|
||||
if (tmp == NULL) {
|
||||
ssh_string_free(blob);
|
||||
string_free(blob);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (comment) {
|
||||
*comment = ssh_string_to_char(tmp);
|
||||
*comment = string_to_char(tmp);
|
||||
} else {
|
||||
ssh_string_free(blob);
|
||||
ssh_string_free(tmp);
|
||||
string_free(blob);
|
||||
string_free(tmp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
ssh_string_free(tmp);
|
||||
string_free(tmp);
|
||||
|
||||
/* get key from blob */
|
||||
pubkey = publickey_from_string(session, blob);
|
||||
ssh_string_free(blob);
|
||||
string_free(blob);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
@@ -395,21 +394,21 @@ struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struct *se
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
ssh_string agent_sign_data(struct ssh_session_struct *session,
|
||||
struct ssh_buffer_struct *data,
|
||||
struct ssh_public_key_struct *pubkey) {
|
||||
struct ssh_string_struct *blob = NULL;
|
||||
struct ssh_string_struct *sig = NULL;
|
||||
struct ssh_buffer_struct *request = NULL;
|
||||
struct ssh_buffer_struct *reply = NULL;
|
||||
STRING *agent_sign_data(struct ssh_session *session,
|
||||
struct buffer_struct *data,
|
||||
struct public_key_struct *pubkey) {
|
||||
struct string_struct *blob = NULL;
|
||||
struct string_struct *sig = NULL;
|
||||
struct buffer_struct *request = NULL;
|
||||
struct buffer_struct *reply = NULL;
|
||||
int type = SSH2_AGENT_FAILURE;
|
||||
int flags = 0;
|
||||
uint32_t dlen = 0;
|
||||
u32 dlen = 0;
|
||||
|
||||
/* create blob from the pubkey */
|
||||
blob = publickey_to_string(pubkey);
|
||||
|
||||
request = ssh_buffer_new();
|
||||
request = buffer_new();
|
||||
if (request == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@@ -425,11 +424,11 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
|
||||
}
|
||||
|
||||
/* Add data */
|
||||
dlen = buffer_get_rest_len(data);
|
||||
dlen = buffer_get_len(data);
|
||||
if (buffer_add_u32(request, htonl(dlen)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (buffer_add_data(request, buffer_get_rest(data), dlen) < 0) {
|
||||
if (buffer_add_data(request, buffer_get(data), dlen) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -437,49 +436,49 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_string_free(blob);
|
||||
string_free(blob);
|
||||
|
||||
reply = ssh_buffer_new();
|
||||
reply = buffer_new();
|
||||
if (reply == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* send the request */
|
||||
if (agent_talk(session, request, reply) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
buffer_free(request);
|
||||
return NULL;
|
||||
}
|
||||
ssh_buffer_free(request);
|
||||
buffer_free(request);
|
||||
|
||||
/* check if reply is valid */
|
||||
if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) {
|
||||
if (buffer_get_u8(reply, (u8 *) &type) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (agent_failed(type)) {
|
||||
ssh_log(session, SSH_LOG_RARE, "Agent reports failure in signing the key");
|
||||
ssh_buffer_free(reply);
|
||||
buffer_free(reply);
|
||||
return NULL;
|
||||
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
|
||||
ssh_set_error(session, SSH_FATAL, "Bad authentication response: %d", type);
|
||||
ssh_buffer_free(reply);
|
||||
buffer_free(reply);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = buffer_get_ssh_string(reply);
|
||||
|
||||
ssh_buffer_free(reply);
|
||||
buffer_free(reply);
|
||||
|
||||
return sig;
|
||||
error:
|
||||
ssh_set_error(session, SSH_FATAL, "Not enough memory");
|
||||
ssh_string_free(blob);
|
||||
ssh_buffer_free(request);
|
||||
ssh_buffer_free(reply);
|
||||
string_free(blob);
|
||||
buffer_free(request);
|
||||
buffer_free(reply);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int agent_is_running(ssh_session session) {
|
||||
int agent_is_running(SSH_SESSION *session) {
|
||||
if (session == NULL || session->agent == NULL) {
|
||||
return 0;
|
||||
}
|
||||
1504
libssh/auth.c
Normal file
1504
libssh/auth.c
Normal file
File diff suppressed because it is too large
Load Diff
255
libssh/auth1.c
Normal file
255
libssh/auth1.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* auth1.c - authentication with SSH-1 protocol
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2005-2008 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh1.h"
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
static int wait_auth1_status(SSH_SESSION *session) {
|
||||
/* wait for a packet */
|
||||
if (packet_read(session) != SSH_OK) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
if(packet_translate(session) != SSH_OK) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
switch(session->in_packet.type) {
|
||||
case SSH_SMSG_SUCCESS:
|
||||
return SSH_AUTH_SUCCESS;
|
||||
case SSH_SMSG_FAILURE:
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
ssh_set_error(session, SSH_FATAL, "Was waiting for a SUCCESS or "
|
||||
"FAILURE, got %d", session->in_packet.type);
|
||||
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
static int send_username(SSH_SESSION *session, const char *username) {
|
||||
STRING *user = NULL;
|
||||
/* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */
|
||||
if(session->auth_service_asked) {
|
||||
return session->auth_service_asked;
|
||||
}
|
||||
|
||||
if (!username) {
|
||||
if(!(username = session->options->username)) {
|
||||
if(ssh_options_default_username(session->options)) {
|
||||
return session->auth_service_asked = SSH_AUTH_ERROR;
|
||||
} else {
|
||||
username = session->options->username;
|
||||
}
|
||||
}
|
||||
}
|
||||
user = string_from_char(username);
|
||||
if (user == NULL) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) {
|
||||
string_free(user);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
if (buffer_add_ssh_string(session->out_buffer, user) < 0) {
|
||||
string_free(user);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
string_free(user);
|
||||
if (packet_send(session) != SSH_OK) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
session->auth_service_asked = wait_auth1_status(session);
|
||||
|
||||
return session->auth_service_asked;
|
||||
}
|
||||
|
||||
/* use the "none" authentication question */
|
||||
int ssh_userauth1_none(SSH_SESSION *session, const char *username){
|
||||
return send_username(session, username);
|
||||
}
|
||||
|
||||
/*
|
||||
int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,int type, STRING *publickey){
|
||||
STRING *user;
|
||||
STRING *service;
|
||||
STRING *method;
|
||||
STRING *algo;
|
||||
int err=SSH_AUTH_ERROR;
|
||||
if(!username)
|
||||
if(!(username=session->options->username)){
|
||||
if(options_default_username(session->options))
|
||||
return SSH_AUTH_ERROR;
|
||||
else
|
||||
username=session->options->username;
|
||||
}
|
||||
if(ask_userauth(session))
|
||||
return SSH_AUTH_ERROR;
|
||||
user=string_from_char(username);
|
||||
service=string_from_char("ssh-connection");
|
||||
method=string_from_char("publickey");
|
||||
algo=string_from_char(ssh_type_to_char(type));
|
||||
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
|
||||
buffer_add_ssh_string(session->out_buffer,user);
|
||||
buffer_add_ssh_string(session->out_buffer,service);
|
||||
buffer_add_ssh_string(session->out_buffer,method);
|
||||
buffer_add_u8(session->out_buffer,0);
|
||||
buffer_add_ssh_string(session->out_buffer,algo);
|
||||
buffer_add_ssh_string(session->out_buffer,publickey);
|
||||
packet_send(session);
|
||||
err=wait_auth_status(session,0);
|
||||
free(user);
|
||||
free(method);
|
||||
free(service);
|
||||
free(algo);
|
||||
return err;
|
||||
}
|
||||
*/
|
||||
/** \internal
|
||||
* \todo implement ssh1 public key
|
||||
*/
|
||||
int ssh_userauth1_offer_pubkey(SSH_SESSION *session, const char *username,
|
||||
int type, STRING *pubkey) {
|
||||
(void) session;
|
||||
(void) username;
|
||||
(void) type;
|
||||
(void) pubkey;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
/*
|
||||
int ssh_userauth_pubkey(SSH_SESSION *session, char *username, STRING *publickey, PRIVATE_KEY *privatekey){
|
||||
STRING *user;
|
||||
STRING *service;
|
||||
STRING *method;
|
||||
STRING *algo;
|
||||
STRING *sign;
|
||||
int err=SSH_AUTH_ERROR;
|
||||
if(!username)
|
||||
if(!(username=session->options->username)){
|
||||
if(options_default_username(session->options))
|
||||
return err;
|
||||
else
|
||||
username=session->options->username;
|
||||
}
|
||||
if(ask_userauth(session))
|
||||
return err;
|
||||
user=string_from_char(username);
|
||||
service=string_from_char("ssh-connection");
|
||||
method=string_from_char("publickey");
|
||||
algo=string_from_char(ssh_type_to_char(privatekey->type));
|
||||
|
||||
|
||||
*/ /* we said previously the public key was accepted */
|
||||
/* packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
|
||||
buffer_add_ssh_string(session->out_buffer,user);
|
||||
buffer_add_ssh_string(session->out_buffer,service);
|
||||
buffer_add_ssh_string(session->out_buffer,method);
|
||||
buffer_add_u8(session->out_buffer,1);
|
||||
buffer_add_ssh_string(session->out_buffer,algo);
|
||||
buffer_add_ssh_string(session->out_buffer,publickey);
|
||||
sign=ssh_do_sign(session,session->out_buffer,privatekey);
|
||||
if(sign){
|
||||
buffer_add_ssh_string(session->out_buffer,sign);
|
||||
free(sign);
|
||||
packet_send(session);
|
||||
err=wait_auth_status(session,0);
|
||||
}
|
||||
free(user);
|
||||
free(service);
|
||||
free(method);
|
||||
free(algo);
|
||||
return err;
|
||||
}
|
||||
*/
|
||||
|
||||
int ssh_userauth1_password(SSH_SESSION *session, const char *username,
|
||||
const char *password) {
|
||||
STRING *pwd = NULL;
|
||||
int rc;
|
||||
|
||||
rc = send_username(session, username);
|
||||
if (rc != SSH_AUTH_DENIED) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* we trick a bit here. A known flaw in SSH1 protocol is that it's
|
||||
* easy to guess password sizes.
|
||||
* not that sure ...
|
||||
*/
|
||||
|
||||
/* XXX fix me here ! */
|
||||
/* cisco IOS doesn't like when a password is followed by zeroes and random pad. */
|
||||
if(1 || strlen(password) >= 128) {
|
||||
/* not risky to disclose the size of such a big password .. */
|
||||
pwd = string_from_char(password);
|
||||
if (pwd == NULL) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
} else {
|
||||
/* fill the password string from random things. the strcpy
|
||||
* ensure there is at least a nul byte after the password.
|
||||
* most implementation won't see the garbage at end.
|
||||
* why garbage ? because nul bytes will be compressed by
|
||||
* gzip and disclose password len.
|
||||
*/
|
||||
pwd = string_new(128);
|
||||
if (pwd == NULL) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
ssh_get_random( pwd->string, 128, 0);
|
||||
strcpy((char *) pwd->string, password);
|
||||
}
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_AUTH_PASSWORD) < 0) {
|
||||
string_burn(pwd);
|
||||
string_free(pwd);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
if (buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
|
||||
string_burn(pwd);
|
||||
string_free(pwd);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
string_burn(pwd);
|
||||
string_free(pwd);
|
||||
|
||||
if (packet_send(session) != SSH_OK) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
return wait_auth1_status(session);
|
||||
}
|
||||
|
||||
#endif /* WITH_SSH1 */
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
|
||||
static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
@@ -39,9 +38,9 @@ static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
#define SET_C(n, i) do { (n) |= ((i) & 63) << 6; } while (0)
|
||||
#define SET_D(n, i) do { (n) |= ((i) & 63); } while (0)
|
||||
|
||||
#define GET_A(n) (unsigned char) (((n) & 0xff0000) >> 16)
|
||||
#define GET_B(n) (unsigned char) (((n) & 0xff00) >> 8)
|
||||
#define GET_C(n) (unsigned char) ((n) & 0xff)
|
||||
#define GET_A(n) (((n) & 0xff0000) >> 16)
|
||||
#define GET_B(n) (((n) & 0xff00) >> 8)
|
||||
#define GET_C(n) ((n) & 0xff)
|
||||
|
||||
static int _base64_to_bin(unsigned char dest[3], const char *source, int num);
|
||||
static int get_equals(char *string);
|
||||
@@ -56,8 +55,8 @@ static int get_equals(char *string);
|
||||
* @returns A buffer containing the decoded string, NULL if something went
|
||||
* wrong (e.g. incorrect char).
|
||||
*/
|
||||
ssh_buffer base64_to_bin(const char *source) {
|
||||
ssh_buffer buffer = NULL;
|
||||
BUFFER *base64_to_bin(const char *source) {
|
||||
BUFFER *buffer = NULL;
|
||||
unsigned char block[3];
|
||||
char *base64;
|
||||
char *ptr;
|
||||
@@ -77,7 +76,7 @@ ssh_buffer base64_to_bin(const char *source) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
buffer = buffer_new();
|
||||
if (buffer == NULL) {
|
||||
SAFE_FREE(base64);
|
||||
return NULL;
|
||||
@@ -162,7 +161,7 @@ ssh_buffer base64_to_bin(const char *source) {
|
||||
|
||||
error:
|
||||
SAFE_FREE(base64);
|
||||
ssh_buffer_free(buffer);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
401
libssh/buffer.c
Normal file
401
libssh/buffer.c
Normal file
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
* buffer.c - buffer functions
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-2008 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
|
||||
/** \defgroup ssh_buffer SSH Buffers
|
||||
* \brief buffer handling
|
||||
*/
|
||||
|
||||
/** \addtogroup ssh_buffer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief creates a new buffer
|
||||
* \return a new initialized buffer, NULL on error.
|
||||
*/
|
||||
struct buffer_struct *buffer_new(void) {
|
||||
struct buffer_struct *buf = malloc(sizeof(struct buffer_struct));
|
||||
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(buf, 0, sizeof(struct buffer_struct));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** \brief deallocate a buffer
|
||||
* \param buffer buffer to free
|
||||
*/
|
||||
void buffer_free(struct buffer_struct *buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer->data) {
|
||||
/* burn the data */
|
||||
memset(buffer->data, 0, buffer->allocated);
|
||||
SAFE_FREE(buffer->data);
|
||||
}
|
||||
memset(buffer, 'X', sizeof(*buffer));
|
||||
SAFE_FREE(buffer);
|
||||
}
|
||||
|
||||
static int realloc_buffer(struct buffer_struct *buffer, int needed) {
|
||||
int smallest = 1;
|
||||
char *new = NULL;
|
||||
/* Find the smallest power of two which is greater or equal to needed */
|
||||
while(smallest <= needed) {
|
||||
smallest <<= 1;
|
||||
}
|
||||
needed = smallest;
|
||||
new = realloc(buffer->data, needed);
|
||||
if (new == NULL) {
|
||||
return -1;
|
||||
}
|
||||
buffer->data = new;
|
||||
buffer->allocated = needed;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* \internal
|
||||
* \brief reinitialize a buffer
|
||||
* \param buffer buffer
|
||||
* \return 0 on sucess, < 0 on error
|
||||
*/
|
||||
int buffer_reinit(struct buffer_struct *buffer) {
|
||||
memset(buffer->data, 0, buffer->used);
|
||||
buffer->used = 0;
|
||||
buffer->pos = 0;
|
||||
if(buffer->allocated > 127) {
|
||||
if (realloc_buffer(buffer, 127) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief add data at tail of the buffer
|
||||
* \param buffer buffer
|
||||
* \param data data pointer
|
||||
* \param len length of data
|
||||
*/
|
||||
int buffer_add_data(struct buffer_struct *buffer, const void *data, u32 len) {
|
||||
if (buffer->allocated < (buffer->used + len)) {
|
||||
if (realloc_buffer(buffer, buffer->used + len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buffer->data+buffer->used, data, len);
|
||||
buffer->used+=len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief add a SSH string to the tail of buffer
|
||||
* \param buffer buffer
|
||||
* \param string SSH String to add
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
int buffer_add_ssh_string(struct buffer_struct *buffer,
|
||||
struct string_struct *string) {
|
||||
u32 len = 0;
|
||||
|
||||
len = ntohl(string->size);
|
||||
if (buffer_add_data(buffer, string, len + sizeof(u32)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/** \internal
|
||||
* \brief add a 32 bits unsigned integer to the tail of buffer
|
||||
* \param buffer buffer
|
||||
* \param data 32 bits integer
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
int buffer_add_u32(struct buffer_struct *buffer,u32 data){
|
||||
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief add a 64 bits unsigned integer to the tail of buffer
|
||||
* \param buffer buffer
|
||||
* \param data 64 bits integer
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
int buffer_add_u64(struct buffer_struct *buffer, u64 data){
|
||||
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/** \internal
|
||||
* \brief add a 8 bits unsigned integer to the tail of buffer
|
||||
* \param buffer buffer
|
||||
* \param data 8 bits integer
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
int buffer_add_u8(struct buffer_struct *buffer,u8 data){
|
||||
if (buffer_add_data(buffer, &data, sizeof(u8)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief add data at head of a buffer
|
||||
* \param buffer buffer
|
||||
* \param data data to add
|
||||
* \param len length of data
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
int buffer_prepend_data(struct buffer_struct *buffer, const void *data,
|
||||
u32 len) {
|
||||
if (buffer->allocated < (buffer->used + len)) {
|
||||
if (realloc_buffer(buffer, buffer->used + len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
memmove(buffer->data + len, buffer->data, buffer->used);
|
||||
memcpy(buffer->data, data, len);
|
||||
buffer->used += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief append data from a buffer to tail of another
|
||||
* \param buffer destination buffer
|
||||
* \param source source buffer. Doesn't take position in buffer into account
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
int buffer_add_buffer(struct buffer_struct *buffer,
|
||||
struct buffer_struct *source) {
|
||||
if (buffer_add_data(buffer, buffer_get(source), buffer_get_len(source)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief get a pointer on the head of the buffer
|
||||
* \param buffer buffer
|
||||
* \return data pointer on the head. Doesn't take position into account.
|
||||
* \warning don't expect data to be nul-terminated
|
||||
* \see buffer_get_rest()
|
||||
* \see buffer_get_len()
|
||||
*/
|
||||
void *buffer_get(struct buffer_struct *buffer){
|
||||
return buffer->data;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief get a pointer to head of the buffer at current position
|
||||
* \param buffer buffer
|
||||
* \return pointer to the data from current position
|
||||
* \see buffer_get_rest_len()
|
||||
* \see buffer_get()
|
||||
*/
|
||||
void *buffer_get_rest(struct buffer_struct *buffer){
|
||||
return buffer->data + buffer->pos;
|
||||
}
|
||||
|
||||
/** \brief get length of the buffer, not counting position
|
||||
* \param buffer
|
||||
* \return length of the buffer
|
||||
* \see buffer_get()
|
||||
*/
|
||||
u32 buffer_get_len(struct buffer_struct *buffer){
|
||||
return buffer->used;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief get length of the buffer from the current position
|
||||
* \param buffer
|
||||
* \return length of the buffer
|
||||
* \see buffer_get_rest()
|
||||
*/
|
||||
u32 buffer_get_rest_len(struct buffer_struct *buffer){
|
||||
return buffer->used - buffer->pos;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* has effect to "eat" bytes at head of the buffer
|
||||
* \brief advance the position in the buffer
|
||||
* \param buffer buffer
|
||||
* \param len number of bytes to eat
|
||||
* \return new size of the buffer
|
||||
*/
|
||||
u32 buffer_pass_bytes(struct buffer_struct *buffer, u32 len){
|
||||
if(buffer->used < buffer->pos+len)
|
||||
return 0;
|
||||
buffer->pos+=len;
|
||||
/* if the buffer is empty after having passed the whole bytes into it, we can clean it */
|
||||
if(buffer->pos==buffer->used){
|
||||
buffer->pos=0;
|
||||
buffer->used=0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief cut the end of the buffer
|
||||
* \param buffer buffer
|
||||
* \param len number of bytes to remove from tail
|
||||
* \return new size of the buffer
|
||||
*/
|
||||
u32 buffer_pass_bytes_end(struct buffer_struct *buffer, u32 len){
|
||||
if(buffer->used < buffer->pos + len)
|
||||
return 0;
|
||||
buffer->used-=len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief gets remaining data out of the buffer. Adjust the read pointer.
|
||||
* \param buffer Buffer to read
|
||||
* \param data data buffer where to store the data
|
||||
* \param len length to read from the buffer
|
||||
* \returns 0 if there is not enough data in buffer
|
||||
* \returns len otherwise.
|
||||
*/
|
||||
u32 buffer_get_data(struct buffer_struct *buffer, void *data, u32 len){
|
||||
if(buffer->pos+len>buffer->used)
|
||||
return 0; /*no enough data in buffer */
|
||||
memcpy(data,buffer->data+buffer->pos,len);
|
||||
buffer->pos+=len;
|
||||
return len; /* no yet support for partial reads (is it really needed ?? ) */
|
||||
}
|
||||
/** \internal
|
||||
* \brief gets a 8 bits unsigned int out of the buffer. Adjusts the read pointer.
|
||||
* \param buffer Buffer to read
|
||||
* \param data pointer to a u8 where to store the data
|
||||
* \returns 0 if there is not enough data in buffer
|
||||
* \returns 1 otherwise.
|
||||
*/
|
||||
int buffer_get_u8(struct buffer_struct *buffer, u8 *data){
|
||||
return buffer_get_data(buffer,data,sizeof(u8));
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* \brief gets a 32 bits unsigned int out of the buffer. Adjusts the read pointer.
|
||||
* \param buffer Buffer to read
|
||||
* \param data pointer to a u32 where to store the data
|
||||
* \returns 0 if there is not enough data in buffer
|
||||
* \returns 4 otherwise.
|
||||
*/
|
||||
int buffer_get_u32(struct buffer_struct *buffer, u32 *data){
|
||||
return buffer_get_data(buffer,data,sizeof(u32));
|
||||
}
|
||||
/** \internal
|
||||
* \brief gets a 64 bits unsigned int out of the buffer. Adjusts the read pointer.
|
||||
* \param buffer Buffer to read
|
||||
* \param data pointer to a u64 where to store the data
|
||||
* \returns 0 if there is not enough data in buffer
|
||||
* \returns 8 otherwise.
|
||||
*/
|
||||
int buffer_get_u64(struct buffer_struct *buffer, u64 *data){
|
||||
return buffer_get_data(buffer,data,sizeof(u64));
|
||||
}
|
||||
/** \internal
|
||||
* \brief gets a SSH String out of the buffer. Adjusts the read pointer.
|
||||
* \param buffer Buffer to read
|
||||
* \returns The SSH String read
|
||||
* \returns NULL otherwise.
|
||||
*/
|
||||
struct string_struct *buffer_get_ssh_string(struct buffer_struct *buffer) {
|
||||
u32 stringlen;
|
||||
u32 hostlen;
|
||||
struct string_struct *str = NULL;
|
||||
|
||||
if (buffer_get_u32(buffer, &stringlen) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
hostlen = ntohl(stringlen);
|
||||
/* verify if there is enough space in buffer to get it */
|
||||
if ((buffer->pos + hostlen) > buffer->used) {
|
||||
return NULL; /* it is indeed */
|
||||
}
|
||||
str = string_new(hostlen);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (buffer_get_data(buffer, str->string, hostlen) != hostlen) {
|
||||
/* should never happen */
|
||||
SAFE_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
/** \internal
|
||||
* \brief gets a mpint out of the buffer. Adjusts the read pointer.
|
||||
* SSH-1 only
|
||||
* \param buffer Buffer to read
|
||||
* \returns the SSH String containing the mpint
|
||||
* \returns NULL otherwise
|
||||
*/
|
||||
|
||||
struct string_struct *buffer_get_mpint(struct buffer_struct *buffer) {
|
||||
u16 bits;
|
||||
u32 len;
|
||||
struct string_struct *str = NULL;
|
||||
|
||||
if (buffer_get_data(buffer, &bits, sizeof(u16)) != sizeof(u16)) {
|
||||
return NULL;
|
||||
}
|
||||
bits = ntohs(bits);
|
||||
len = (bits + 7) / 8;
|
||||
if ((buffer->pos + len) > buffer->used) {
|
||||
return NULL;
|
||||
}
|
||||
str = string_new(len);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (buffer_get_data(buffer, str->string, len) != len) {
|
||||
SAFE_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
/** @} */
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
1880
libssh/channels.c
Normal file
1880
libssh/channels.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -24,36 +24,28 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/ssh1.h"
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/packet.h"
|
||||
#include "libssh/channels.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
|
||||
/*
|
||||
* This is a big hack. In fact, SSH1 doesn't make a clever use of channels.
|
||||
* The whole packets concerning shells are sent outside of a channel.
|
||||
* Thus, an inside limitation of this behavior is that you can't only
|
||||
* Thus, an inside limitation of this behaviour is that you can't only
|
||||
* request one shell.
|
||||
* The question is still how they managed to embed two "channel" into one
|
||||
* The question is stil how they managed to imbed two "channel" into one
|
||||
* protocol.
|
||||
*/
|
||||
|
||||
int channel_open_session1(ssh_channel chan) {
|
||||
int channel_open_session1(CHANNEL *chan) {
|
||||
/*
|
||||
* We guess we are requesting an *exec* channel. It can only have one exec
|
||||
* channel. So we abort with an error if we need more than one.
|
||||
*/
|
||||
ssh_session session = chan->session;
|
||||
SSH_SESSION *session = chan->session;
|
||||
if (session->exec_channel_opened) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"SSH1 supports only one execution channel. "
|
||||
@@ -61,7 +53,7 @@ int channel_open_session1(ssh_channel chan) {
|
||||
return -1;
|
||||
}
|
||||
session->exec_channel_opened = 1;
|
||||
chan->state = SSH_CHANNEL_STATE_OPEN;
|
||||
chan->open = 1;
|
||||
chan->local_maxpacket = 32000;
|
||||
chan->local_window = 64000;
|
||||
ssh_log(session, SSH_LOG_PACKET, "Opened a SSH1 channel session");
|
||||
@@ -81,26 +73,22 @@ int channel_open_session1(ssh_channel chan) {
|
||||
* much simplier under ssh2. I just hope the defaults values are ok ...
|
||||
*/
|
||||
|
||||
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col,
|
||||
int channel_request_pty_size1(CHANNEL *channel, const char *terminal, int col,
|
||||
int row) {
|
||||
ssh_session session = channel->session;
|
||||
ssh_string str = NULL;
|
||||
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
|
||||
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
str = ssh_string_from_char(terminal);
|
||||
SSH_SESSION *session = channel->session;
|
||||
STRING *str = NULL;
|
||||
|
||||
str = string_from_char(terminal);
|
||||
if (str == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_REQUEST_PTY) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, str) < 0) {
|
||||
ssh_string_free(str);
|
||||
string_free(str);
|
||||
return -1;
|
||||
}
|
||||
ssh_string_free(str);
|
||||
string_free(str);
|
||||
|
||||
if (buffer_add_u32(session->out_buffer, ntohl(row)) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, ntohl(col)) < 0 ||
|
||||
@@ -111,82 +99,78 @@ int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Opening a ssh1 pty");
|
||||
|
||||
if (packet_send(session) == SSH_ERROR) {
|
||||
if (packet_send(session) != SSH_OK ||
|
||||
packet_read(session) != SSH_OK ||
|
||||
packet_translate(session) != SSH_OK) {
|
||||
return -1;
|
||||
}
|
||||
switch(channel->request_state){
|
||||
case SSH_CHANNEL_REQ_STATE_ERROR:
|
||||
case SSH_CHANNEL_REQ_STATE_PENDING:
|
||||
case SSH_CHANNEL_REQ_STATE_NONE:
|
||||
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
|
||||
return SSH_ERROR;
|
||||
case SSH_CHANNEL_REQ_STATE_ACCEPTED:
|
||||
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
|
||||
|
||||
switch (session->in_packet.type) {
|
||||
case SSH_SMSG_SUCCESS:
|
||||
ssh_log(session, SSH_LOG_RARE, "PTY: Success");
|
||||
return SSH_OK;
|
||||
case SSH_CHANNEL_REQ_STATE_DENIED:
|
||||
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
|
||||
return 0;
|
||||
break;
|
||||
case SSH_SMSG_FAILURE:
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Server denied PTY allocation");
|
||||
ssh_log(session, SSH_LOG_RARE, "PTY: denied\n");
|
||||
return SSH_ERROR;
|
||||
break;
|
||||
default:
|
||||
ssh_log(session, SSH_LOG_RARE, "PTY: error\n");
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Received unexpected packet type %d",
|
||||
session->in_packet.type);
|
||||
return -1;
|
||||
}
|
||||
// Not reached
|
||||
return SSH_ERROR;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
|
||||
ssh_session session = channel->session;
|
||||
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
|
||||
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
int channel_change_pty_size1(CHANNEL *channel, int cols, int rows) {
|
||||
SSH_SESSION *session = channel->session;
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_WINDOW_SIZE) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, ntohl(rows)) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, ntohl(cols)) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, 0) < 0 ||
|
||||
buffer_add_u32(session->out_buffer, 0) < 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
channel->request_state=SSH_CHANNEL_REQ_STATE_PENDING;
|
||||
if (packet_send(session) == SSH_ERROR) {
|
||||
return SSH_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "Change pty size send");
|
||||
while(channel->request_state==SSH_CHANNEL_REQ_STATE_PENDING){
|
||||
ssh_handle_packets(session,-1);
|
||||
if (packet_send(session)) {
|
||||
return -1;
|
||||
}
|
||||
switch(channel->request_state){
|
||||
case SSH_CHANNEL_REQ_STATE_ERROR:
|
||||
case SSH_CHANNEL_REQ_STATE_PENDING:
|
||||
case SSH_CHANNEL_REQ_STATE_NONE:
|
||||
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
|
||||
return SSH_ERROR;
|
||||
case SSH_CHANNEL_REQ_STATE_ACCEPTED:
|
||||
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "pty size changed");
|
||||
return SSH_OK;
|
||||
case SSH_CHANNEL_REQ_STATE_DENIED:
|
||||
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
|
||||
|
||||
ssh_log(session, SSH_LOG_RARE, "Change pty size send");
|
||||
|
||||
if (packet_wait(session, SSH_SMSG_SUCCESS, 1) != SSH_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (session->in_packet.type) {
|
||||
case SSH_SMSG_SUCCESS:
|
||||
ssh_log(session, SSH_LOG_RARE, "pty size changed");
|
||||
return 0;
|
||||
case SSH_SMSG_FAILURE:
|
||||
ssh_log(session, SSH_LOG_RARE, "pty size change denied");
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED, "pty size change denied");
|
||||
return SSH_ERROR;
|
||||
return -1;
|
||||
}
|
||||
// Not reached
|
||||
return SSH_ERROR;
|
||||
|
||||
ssh_set_error(session, SSH_FATAL, "Received unexpected packet type %d",
|
||||
session->in_packet.type);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int channel_request_shell1(ssh_channel channel) {
|
||||
ssh_session session = channel->session;
|
||||
int channel_request_shell1(CHANNEL *channel) {
|
||||
SSH_SESSION *session = channel->session;
|
||||
|
||||
if (buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (packet_send(session) == SSH_ERROR) {
|
||||
if (packet_send(session) != SSH_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -195,23 +179,23 @@ int channel_request_shell1(ssh_channel channel) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int channel_request_exec1(ssh_channel channel, const char *cmd) {
|
||||
ssh_session session = channel->session;
|
||||
ssh_string command = NULL;
|
||||
int channel_request_exec1(CHANNEL *channel, const char *cmd) {
|
||||
SSH_SESSION *session = channel->session;
|
||||
STRING *command = NULL;
|
||||
|
||||
command = ssh_string_from_char(cmd);
|
||||
command = string_from_char(cmd);
|
||||
if (command == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXEC_CMD) < 0 ||
|
||||
buffer_add_ssh_string(session->out_buffer, command) < 0) {
|
||||
ssh_string_free(command);
|
||||
string_free(command);
|
||||
return -1;
|
||||
}
|
||||
ssh_string_free(command);
|
||||
string_free(command);
|
||||
|
||||
if(packet_send(session) == SSH_ERROR) {
|
||||
if(packet_send(session) != SSH_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -220,58 +204,80 @@ int channel_request_exec1(ssh_channel channel, const char *cmd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_data1){
|
||||
ssh_channel channel = session->channels;
|
||||
ssh_string str = NULL;
|
||||
int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1);
|
||||
(void)user;
|
||||
str = buffer_get_ssh_string(packet);
|
||||
static int channel_rcv_data1(SSH_SESSION *session, int is_stderr) {
|
||||
CHANNEL *channel = session->channels;
|
||||
STRING *str = NULL;
|
||||
|
||||
str = buffer_get_ssh_string(session->in_buffer);
|
||||
if (str == NULL) {
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n");
|
||||
return SSH_PACKET_USED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_PROTOCOL,
|
||||
"Adding %" PRIdS " bytes data in %d",
|
||||
ssh_string_len(str), is_stderr);
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"Adding %zu bytes data in %d",
|
||||
string_len(str), is_stderr);
|
||||
|
||||
if (channel_default_bufferize(channel, ssh_string_data(str), ssh_string_len(str),
|
||||
if (channel_default_bufferize(channel, str->string, string_len(str),
|
||||
is_stderr) < 0) {
|
||||
ssh_string_free(str);
|
||||
return SSH_PACKET_USED;
|
||||
string_free(str);
|
||||
return -1;
|
||||
}
|
||||
ssh_string_free(str);
|
||||
string_free(str);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_close1){
|
||||
ssh_channel channel = session->channels;
|
||||
uint32_t status;
|
||||
(void)type;
|
||||
(void)user;
|
||||
buffer_get_u32(packet, &status);
|
||||
static int channel_rcv_close1(SSH_SESSION *session) {
|
||||
CHANNEL *channel = session->channels;
|
||||
u32 status;
|
||||
|
||||
buffer_get_u32(session->in_buffer, &status);
|
||||
/*
|
||||
* It's much more than a channel closing. spec says it's the last
|
||||
* message sent by server (strange)
|
||||
*/
|
||||
|
||||
/* actually status is lost somewhere */
|
||||
channel->state = SSH_CHANNEL_STATE_CLOSED;
|
||||
channel->open = 0;
|
||||
channel->remote_eof = 1;
|
||||
|
||||
buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION);
|
||||
packet_send(session);
|
||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
if (packet_send(session) != SSH_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int channel_handle1(SSH_SESSION *session, int type) {
|
||||
ssh_log(session, SSH_LOG_RARE, "Channel_handle1(%d)", type);
|
||||
switch (type) {
|
||||
case SSH_SMSG_STDOUT_DATA:
|
||||
if (channel_rcv_data1(session,0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case SSH_SMSG_EXITSTATUS:
|
||||
if (channel_rcv_close1(session) < 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Unexepected message %d", type);
|
||||
}
|
||||
|
||||
int channel_write1(ssh_channel channel, const void *data, int len) {
|
||||
ssh_session session = channel->session;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int channel_write1(CHANNEL *channel, const void *data, int len) {
|
||||
SSH_SESSION *session = channel->session;
|
||||
int origlen = len;
|
||||
int effectivelen;
|
||||
const unsigned char *ptr=data;
|
||||
|
||||
while (len > 0) {
|
||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) {
|
||||
return -1;
|
||||
@@ -280,14 +286,14 @@ int channel_write1(ssh_channel channel, const void *data, int len) {
|
||||
effectivelen = len > 32000 ? 32000 : len;
|
||||
|
||||
if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
|
||||
buffer_add_data(session->out_buffer, ptr, effectivelen) < 0) {
|
||||
buffer_add_data(session->out_buffer, data, effectivelen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr += effectivelen;
|
||||
data += effectivelen;
|
||||
len -= effectivelen;
|
||||
|
||||
if (packet_send(session) == SSH_ERROR) {
|
||||
if (packet_send(session) != SSH_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user