Compare commits

..

13 Commits

Author SHA1 Message Date
Andreas Schneider
d411260a68 Fix build on windows, missing include. 2009-07-14 10:52:18 +02:00
Aris Adamantiadis
f8f0663eb9 Fix doxygen to match SSH_SERVER_FILE_NOT_FOUND fix 2009-07-14 10:22:17 +02:00
Andreas Schneider
cedc635ed0 Add changelog entries for 0.3.1. 2009-07-14 09:51:49 +02:00
Andreas Schneider
ff819489b7 Set version to 0.3.1. 2009-07-14 09:51:36 +02:00
Aris Adamantiadis
37dc2a5279 Reflect the SSH_SERVER_NOT_KNOWN add-on in sample 2009-07-13 12:07:31 +02:00
Aris Adamantiadis
50ebbe636e Added return code SSH_SERVER_FILE_NOT_FOUND
This error is returned by ssh_is_server_known when known_hosts
file does not exist and gives more action to the developer.
2009-07-13 12:07:19 +02:00
Aris Adamantiadis
101bf21d41 Fixed Could not write as much data as expected msg
Bug caused by verifying the size of the buffer in the wrong place
2009-07-02 10:37:32 +02:00
Aris Adamantiadis
ae3bb42da5 Fixed memory leak in ssh_is_server_known() 2009-06-23 09:13:26 +02:00
Aris Adamantiadis
918a912cd5 Fixed yet another read-after-free bug
read of a buffer len after free in sftp_write()
2009-06-23 09:13:15 +02:00
Aris Adamantiadis
7ba81b974e Fixed a use-after-free in match_hashed_host() 2009-06-21 22:18:43 +02:00
Aris Adamantiadis
b5e868fb8b Fix doublefree bug found by Cyril 2009-06-21 22:18:38 +02:00
Andreas Schneider
693c041ba9 Fix a memory leak in ssh_message_free(). 2009-06-20 11:30:09 +02:00
Aris Adamantiadis
39c7e3c7dd Fixed potential format string attacks
Potential format string attacks on error reporting in channels.c
2009-06-20 11:25:23 +02:00
101 changed files with 6326 additions and 14867 deletions

6
.gitignore vendored
View File

@@ -1,6 +0,0 @@
.*
*.swp
*~$
build
cscope.*
tags

View File

@@ -6,21 +6,14 @@ cmake_minimum_required(VERSION 2.6.0)
# global needed variables
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION "0.3.0")
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "4")
set(APPLICATION_VERSION_PATCH "6")
set(APPLICATION_VERSION_MINOR "3")
set(APPLICATION_VERSION_PATCH "1")
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.1.3")
set(LIBRARY_SOVERSION "4")
set(LIBRARY_VERSION "3.1.0")
set(LIBRARY_SOVERSION "3")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH
@@ -45,20 +38,14 @@ include(MacroCopyFile)
# search for libraries
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)
endif (NOT CRYPTO_FOUND)
# config.h checks
include(ConfigureChecks.cmake)
@@ -72,7 +59,12 @@ add_subdirectory(libssh)
# build samples
include_directories(${CMAKE_SOURCE_DIR}/include)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
add_subdirectory(examples)
endif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
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)

View File

@@ -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 "4")
set(CPACK_PACKAGE_VERSION_PATCH "6")
set(CPACK_PACKAGE_VERSION_MINOR "3")
set(CPACK_PACKAGE_VERSION_PATCH "1")
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 (HAVE_NSIS)
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 (HAVE_NSIS)
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")

133
ChangeLog
View File

@@ -1,139 +1,6 @@
ChangeLog
==========
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.
* Added sftp_symlink() function.
* Fixed ssh_write_knownhost().
* 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.

View File

@@ -1,11 +1,9 @@
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckCXXSourceCompiles)
include(TestBigEndian)
set(PACKAGE ${APPLICATION_NAME})
set(VERSION ${APPLICATION_VERSION})
@@ -17,105 +15,31 @@ set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(BINARYDIR ${CMAKE_BINARY_DIR})
set(SOURCEDIR ${CMAKE_SOURCE_DIR})
function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
execute_process(
COMMAND
${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1} -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)
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)
# HEADER FILES
check_include_file(argp.h HAVE_ARGP_H)
check_include_file(pty.h HAVE_PTY_H)
check_include_file(terminos.h HAVE_TERMIOS_H)
if (WIN32)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
if (NOT HAVE_WSPIAPI_H)
message(STATUS "WARNING: Without wspiapi.h (or dependencies), this build will only work on Windows XP and newer versions")
endif (NOT HAVE_WSPIAPI_H)
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
if (NOT HAVE_WS2TCPIP_H)
message(ERROR "WARNING: Does not have ws2tcpip.h or winsock2.h")
endif (NOT HAVE_WS2TCPIP_H)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE)
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
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)
# 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)
endif (WIN32)
if (UNIX)
# libsocket (Solaris)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
if (HAVE_LIBSOCKET)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
endif (HAVE_LIBSOCKET)
# libnsl (Solaris)
check_library_exists(nsl gethostbyname "" HAVE_LIBNSL)
if (HAVE_LIBNSL)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
endif (HAVE_LIBNSL)
# libresolv
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
if (HAVE_LIBRESOLV)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
endif (HAVE_LIBRESOLV)
check_library_exists(rt nanosleep "" HAVE_LIBRT)
# librt
if (HAVE_LIBRT)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
endif (HAVE_LIBRT)
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)
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(regcomp HAVE_REGCOMP)
endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
endif (WIN32)
# LIBRARIES
if (OPENSSL_FOUND)
if (CRYPTO_FOUND)
set(HAVE_LIBCRYPTO 1)
endif (OPENSSL_FOUND)
endif (CRYPTO_FOUND)
if (GCRYPT_FOUND)
set(HAVE_LIBGCRYPT 1)
@@ -130,11 +54,3 @@ 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)

View File

@@ -3,7 +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" OFF)
option(WITH_DEBUG_CRYPTO "Build with cryto debut output" OFF)

49
README
View File

@@ -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,33 +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.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");
http://0xbadc0de.be/?part=libssh

View File

@@ -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|--cmakedir /directory|--make
(gmake|make)|--ccompiler (gcc|cc)|--withstaticlib|--unittesting|--withss1|--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"
@@ -118,34 +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"
shift
;;
*-unittesting)
OPTIONS="${OPTIONS} -DUNIT_TESTING=ON"
shift
;;
*-withssh1)
OPTIONS="${OPTIONS} -DWITH_SSH1=ON"
shift
;;
*-withserver)
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
shift
;;
----noarg)
echo "$ARG does not take an argument"
cleanup_and_exit
@@ -160,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
@@ -193,3 +149,4 @@ exec >&0 2>&0 # so that the logging tee finishes
sleep 1 # wait till tee terminates
cleanup_and_exit 0

View File

@@ -3,57 +3,47 @@
include(CheckCCompilerFlag)
if (UNIX AND NOT WIN32)
if (${CMAKE_C_COMPILER_ID} MATCHES GNU)
# add -Wconversion ?
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute")
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
endif (WITH_FPIC)
check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
endif (WITH_STACK_PROTECTOR)
check_c_compiler_flag("-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)
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
add_definitions(-fPIC)
endif (WITH_FPIC)
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS64_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
if (_lfs_CFLAGS)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
endif (_lfs_CFLAGS)
# 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
)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
add_definitions(${_lfs_CFLAGS})
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
add_definitions(-Wall -Wextra -Wmissing-prototypes -Wdeclaration-after-statement -Wunused)
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 (UNIX AND NOT WIN32)
# suppress warning about "deprecated" functions
if (MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
endif (MSVC)

View File

@@ -94,7 +94,7 @@ endif (UNIX)
if (WIN32)
# Same same
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
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 "-")

View File

@@ -1,31 +0,0 @@
# - Try to find NSIS
# Once done this will define
#
# NSIS_FOUND - system has NSIS
# NSIS_MAKE - NSIS creator executable
#
# 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.
#
if (NSIS_MAKE)
# in cache already
set(NSIS_FOUND TRUE)
elseif (NSIS_MAKE)
find_program(NSIS_MAKE
NAMES
makensis
PATHS
${_NSIS_DIR}
${_NSIS_DIR}/Bin
$ENV{PROGRAMFILES}/NSIS
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
mark_as_advanced(NSIS_MAKE)
endif (NSIS_MAKE)

View File

@@ -18,10 +18,6 @@ if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
# in cache already
set(OPENSSL_FOUND TRUE)
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
if (WIN32)
set(_OPENSSL_DIR $ENV{PROGRAMFILES}/OpenSSL)
endif (WIN32)
# 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)
@@ -38,31 +34,23 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
openssl/ssl.h
PATHS
${_OPENSSL_DIR}/include
${_OPENSSL_INCLUDEDIR}
/usr/include
/usr/local/include
/usr/local/ssl/include
/opt/local/include
/sw/include
/usr/lib/sfw/include
)
mark_as_advanced(OPENSSL_INCLUDE_DIR)
find_library(SSL_LIBRARY
NAMES
ssl
libssl
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
/usr/local/ssl/lib
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
)
mark_as_advanced(SSL_LIBRARY)
@@ -70,15 +58,11 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
ssleay32
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
/usr/local/ssl/lib
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
)
mark_as_advanced(SSLEAY32_LIBRARY)
@@ -86,37 +70,23 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
NAMES
ssleay32MD
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
/usr/local/ssl/lib
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
)
mark_as_advanced(SSLEAY32MD_LIBRARY)
find_library(CRYPTO_LIBRARY
NAMES
crypto
libcrypto
eay
eay32
libeay
libeay32
PATHS
${_OPENSSL_DIR}/lib
${_OPENSSL_LIBDIR}
/lib
/usr/lib
/usr/local/lib
/usr/local/ssl/lib
/opt/local/lib
/sw/lib
/usr/sfw/lib/64
/usr/sfw/lib
)
mark_as_advanced(CRYPTO_LIBRARY)

View File

@@ -18,15 +18,11 @@ if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
# in cache already
set(ZLIB_FOUND TRUE)
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
if (WIN32)
set(_ZLIB_DIR $ENV{PROGRAMFILES}/GnuWin32)
endif (WIN32)
find_path(ZLIB_INCLUDE_DIR
NAMES
zlib.h
PATHS
${_ZLIB_DIR}/include
/usr/include
/usr/local/include
/opt/local/include
@@ -40,7 +36,6 @@ else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
zlib
zlib1
PATHS
${_ZLIB_DIR}/lib
/usr/lib
/usr/local/lib
/opt/local/lib

View File

@@ -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()

View File

@@ -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,9 +23,6 @@
/* 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
@@ -37,37 +31,6 @@
/*************************** 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 `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 `strncpy' function. */
#cmakedefine HAVE_STRNCPY 1
/* Define to 1 if you have the `cfmakeraw' function. */
#cmakedefine HAVE_CFMAKERAW 1
@@ -83,9 +46,6 @@
/* 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
/*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */
@@ -102,7 +62,7 @@
/* 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 */
@@ -114,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

View File

@@ -1 +0,0 @@
<!-- Doxygen TracFooter -->

View File

@@ -1,4 +0,0 @@
<!-- Doxygen TracHeader -->
<style>@import url(/chrome/site/doxygen.css);</style>
<style>@import url(/chrome/site/tabs.css);</style>
<!-- /Doxygen TracHeader -->

View File

@@ -1,4 +1,4 @@
# Doxyfile 1.5.6
# Doxyfile 1.5.8
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -57,8 +57,8 @@ CREATE_SUBDIRS = NO
# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
# and Ukrainian.
# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
# Spanish, Swedish, and Ukrainian.
OUTPUT_LANGUAGE = English
@@ -165,13 +165,6 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
# If the DETAILS_AT_TOP tag is set to YES then Doxygen
# will output the detailed description near the top, like JavaDoc.
# If set to NO, the detailed description appears after the member
# documentation.
DETAILS_AT_TOP = YES
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
@@ -224,6 +217,17 @@ OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it parses.
# With this tag you can assign which parser to use for a given extension.
# Doxygen has a built-in mapping, but you can override or extend it using this tag.
# The format is ext=language, where ext is a file extension, and language is one of
# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
# use: inc=Fortran f=C
EXTENSION_MAPPING =
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
@@ -233,7 +237,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
CPP_CLI_SUPPORT = NO
@@ -276,7 +280,23 @@ SUBGROUPING = YES
# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
TYPEDEF_HIDES_STRUCT = YES
TYPEDEF_HIDES_STRUCT = NO
# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
# determine which symbols to keep in memory and which to flush to disk.
# When the cache is full, less often used symbols will be written to disk.
# For small to medium size projects (<1000 input files) the default value is
# probably good enough. For larger projects a too small cache size can cause
# doxygen to be busy swapping symbols to and from disk most of the time
# causing a significant performance penality.
# If the system has enough physical memory increasing the cache will improve the
# performance by keeping more symbols in memory. Note that the value works on
# a logarithmic scale so increasing the size by one will rougly double the
# memory usage. The cache size is given by this formula:
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
# corresponding to a cache size of 2^16 = 65536 symbols
SYMBOL_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
@@ -405,7 +425,7 @@ SORT_GROUP_NAMES = NO
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the
# alphabetical list.
@@ -462,14 +482,15 @@ SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
# Namespaces page. This will remove the Namespaces entry from the Quick Index
# Namespaces page.
# This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.
SHOW_NAMESPACES = YES
@@ -484,6 +505,15 @@ SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
# doxygen. The layout file controls the global structure of the generated output files
# in an output format independent way. The create the layout file that represents
# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
# file name after the option, if omitted DoxygenLayout.xml will be used as the name
# of the layout file.
LAYOUT_FILE =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -545,8 +575,7 @@ WARN_LOGFILE = @CMAKE_CURRENT_BINARY_DIR@/doxy.log
# with spaces.
INPUT = @CMAKE_SOURCE_DIR@/include \
@CMAKE_SOURCE_DIR@/libssh \
@CMAKE_SOURCE_DIR@/doc
@CMAKE_SOURCE_DIR@/libssh
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -613,15 +642,18 @@ EXCLUDE_SYMBOLS =
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/examples
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/tests \
@CMAKE_SOURCE_DIR@
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS = *.c \
EXAMPLE_PATTERNS = *.cpp \
*.cc \
*.h \
*.hh \
INSTALL \
DEPENDENCIES \
CHANGELOG \
@@ -646,14 +678,17 @@ IMAGE_PATH =
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# to standard output.
# If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form:
# basis.
# Doxygen will compare the file name with each pattern and apply the
# filter if there is a match.
# The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
# is applied to all files.
@@ -700,10 +735,11 @@ REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code. Otherwise they will link to the documentstion.
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code.
# Otherwise they will link to the documentation.
REFERENCES_LINK_SOURCE = YES
@@ -792,12 +828,13 @@ HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
GENERATE_HTMLHELP = NO
HTML_DYNAMIC_SECTIONS = NO
# If the GENERATE_DOCSET tag is set to YES, additional index files
# will be generated that can be used as input for Apple's Xcode 3
@@ -806,7 +843,8 @@ GENERATE_HTMLHELP = NO
# HTML output directory. Running make will produce the docset in that
# directory and running "make install" will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
# it at startup.
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
GENERATE_DOCSET = NO
@@ -824,13 +862,12 @@ DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
HTML_DYNAMIC_SECTIONS = NO
GENERATE_HTMLHELP = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
@@ -852,8 +889,8 @@ HHC_LOCATION =
GENERATE_CHI = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# content.
CHM_INDEX_ENCODING =
@@ -869,6 +906,55 @@ BINARY_TOC = NO
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
# are set, an additional index file will be generated that can be used as input for
# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
# HTML documentation.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
# be used to specify the file name of the resulting .qch file.
# The path specified is relative to the HTML output folder.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#namespace
QHP_NAMESPACE =
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#virtual-folders
QHP_VIRTUAL_FOLDER = doc
# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
# For more information please see
# http://doc.trolltech.com/qthelpproject.html#custom-filters
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
# filter section matches.
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
QHP_SECT_FILTER_ATTRS =
# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
# be used to specify the location of Qt's qhelpgenerator.
# If non-empty doxygen will try to run qhelpgenerator on the generated
# .qhp file.
QHG_LOCATION =
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
@@ -880,19 +966,19 @@ DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to FRAME, a side panel will be generated
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to FRAME, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
# probably better off using the HTML help feature. Other possible values
# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
# and Class Hiererachy pages using a tree view instead of an ordered list;
# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
# disables this behavior completely. For backwards compatibility with previous
# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
# and Class Hierarchy pages using a tree view instead of an ordered list;
# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
# disables this behavior completely. For backwards compatibility with previous
# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
# respectively.
GENERATE_TREEVIEW = NO
@@ -918,7 +1004,7 @@ FORMULA_FONTSIZE = 10
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = @DOXYFILE_LATEX@
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
@@ -1123,8 +1209,10 @@ GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
# nicely formatted so it can be parsed by a human reader. This is useful
# if you want to understand what is going on. On the other hand, if this
# nicely formatted so it can be parsed by a human reader.
# This is useful
# if you want to understand what is going on.
# On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
@@ -1211,14 +1299,16 @@ SKIP_FUNCTION_MACROS = YES
# Optionally an initial location of the external documentation
# can be added for each tagfile. The format of a tag file without
# this location is as follows:
# TAGFILES = file1 file2 ...
#
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
#
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where "loc1" and "loc2" can be relative or absolute paths or
# URLs. If a location is present for each tag, the installdox tool
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# If a tag file is not located in the directory in which doxygen
# is run, you must also specify the path to the tagfile here.
@@ -1292,6 +1382,11 @@ HAVE_DOT = @DOXYGEN_DOT_FOUND@
DOT_FONTNAME = FreeSans
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the output directory to look for the
# FreeSans.ttf font (which doxygen will put there itself). If you specify a
# different font using DOT_FONTNAME you can set the path where dot
@@ -1334,7 +1429,7 @@ TEMPLATE_RELATIONS = YES
# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = NO
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
@@ -1349,7 +1444,7 @@ INCLUDED_BY_GRAPH = YES
# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
CALL_GRAPH = NO
CALL_GRAPH = YES
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function
@@ -1357,7 +1452,7 @@ CALL_GRAPH = NO
# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
CALLER_GRAPH = NO
CALLER_GRAPH = YES
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
@@ -1366,13 +1461,13 @@ GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
DOT_IMAGE_FORMAT = png
@@ -1409,10 +1504,10 @@ DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is enabled by default, which results in a transparent
# background. Warning: Depending on the platform used, enabling this option
# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
# become hard to read).
# background. This is disabled by default, because dot on Windows does not
# seem to support this out of the box. Warning: Depending on the platform used,
# enabling this option may lead to badly anti-aliased labels on the edges of
# a graph (i.e. they become hard to read).
DOT_TRANSPARENT = NO
@@ -1436,7 +1531,7 @@ GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
# Options related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
/**
* @mainpage
* This manual documents the libssh C API.
*
* There are several other places to look for libssh information, such as the
* <a href="http://dev.libssh.org/wiki/Tutorial" target="_blank">tutorial</a>
* and the specification; those can be found at the <a
* href="http://www.libssh.org/" target="_blank">libssh website</a>.
*
* To be continued...
*/

View File

@@ -1,41 +0,0 @@
project(libssh-examples C)
set(examples_SRCS
authentication.c
knownhosts.c
connect_ssh.c
)
include_directories(
${LIBSSH_PUBLIC_INCLUDE_DIRS}
${LIBSSH_PRIVATE_INCLUDE_DIRS}
)
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
add_executable(scp_download scp_download.c ${examples_SRCS})
add_executable(samplessh sample.c ${examples_SRCS})
add_executable(exec exec.c ${examples_SRCS})
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
include_directories(
${LIBSSH_PUBLIC_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}
)
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)

View File

@@ -1,125 +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 <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libssh/libssh.h>
#include "examples_common.h"
int authenticate_kbdint(ssh_session session){
int err=ssh_userauth_kbdint(session,NULL,NULL);
const char *name, *instruction, *prompt;
char *ptr;
char buffer[128];
int i,n;
char echo;
while (err==SSH_AUTH_INFO){
name=ssh_userauth_kbdint_getname(session);
instruction=ssh_userauth_kbdint_getinstruction(session);
n=ssh_userauth_kbdint_getnprompts(session);
if(strlen(name)>0)
printf("%s\n",name);
if(strlen(instruction)>0)
printf("%s\n",instruction);
for(i=0;i<n;++i){
prompt=ssh_userauth_kbdint_getprompt(session,i,&echo);
if(echo){
printf("%s",prompt);
fgets(buffer,sizeof(buffer),stdin);
buffer[sizeof(buffer)-1]=0;
if((ptr=strchr(buffer,'\n')))
*ptr=0;
if (ssh_userauth_kbdint_setanswer(session,i,buffer) < 0) {
return SSH_AUTH_ERROR;
}
memset(buffer,0,strlen(buffer));
} else {
ptr=getpass(prompt);
if (ssh_userauth_kbdint_setanswer(session,i,ptr) < 0) {
return SSH_AUTH_ERROR;
}
}
}
err=ssh_userauth_kbdint(session,NULL,NULL);
}
return err;
}
int authenticate_console(ssh_session session){
int rc;
int method;
char *password;
char *banner;
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR) {
perror("Authentication failed.");
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) {
perror("Authentication failed.");
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);
if (rc == SSH_AUTH_ERROR) {
perror("Authentication failed.");
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
password=getpass("Password: ");
// Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR) {
perror("Authentication failed.");
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
}
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n",banner);
free(banner);
}
return rc;
}

View File

@@ -1,63 +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_disconnect(session);
return NULL;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
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);
return NULL;
}
if(verify_knownhost(session)<0){
ssh_disconnect(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);
return NULL;
}

View File

@@ -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);
int verify_knownhost(ssh_session session);
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
#endif /* EXAMPLES_COMMON_H_ */

View File

@@ -1,57 +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 buf[4096];
int rc;
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
return 1;
}
channel = channel_new(session);;
if (channel == NULL) {
ssh_disconnect(session);
ssh_finalize();
return 1;
}
rc = channel_open_session(channel);
if (rc < 0) {
channel_close(channel);
ssh_disconnect(session);
ssh_finalize();
return 1;
}
rc = channel_request_exec(channel, "ps aux");
if (rc < 0) {
channel_close(channel);
ssh_disconnect(session);
ssh_finalize();
return 1;
}
do {
if (channel_is_open(channel)) {
rc = channel_read(channel, buf, sizeof(buf), 0);
if(rc > 0){
fwrite(buf,1,rc,stdout);
}
}
} while(rc > 0);
channel_send_eof(channel);
channel_close(channel);
ssh_disconnect(session);
ssh_finalize();
return 0;
}

View File

@@ -1,88 +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 <unistd.h>
#include <string.h>
#include <libssh/libssh.h>
#include "examples_common.h"
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);
free(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);
free(hexa);
fgets(buf,sizeof(buf),stdin);
if(strncasecmp(buf,"yes",3)!=0){
return -1;
}
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
fgets(buf,sizeof(buf),stdin);
if(strncasecmp(buf,"yes",3)==0){
if (ssh_write_knownhost(session) < 0) {
free(hash);
fprintf(stderr, "error %s\n", strerror(errno));
return -1;
}
}
break;
case SSH_SERVER_ERROR:
free(hash);
fprintf(stderr,"%s",ssh_get_error(session));
return -1;
}
free(hash);
return 0;
}

View File

@@ -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;
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,0644);
// snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
if(r==SSH_ERROR){
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
ssh_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;
}

View File

@@ -1,528 +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;
#ifdef WITH_PCAP
/* this header file won't be necessary in the future */
#include <libssh/pcap.h>
char *pcap_file=NULL;
#endif
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 {
answer = getpass(prompt);
}
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){
#ifdef WITH_PCAP
case 'P':
pcap_file=optarg;
break;
#endif
#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);
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=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)
channel_write(channel,buffer,lus);
else {
eof=1;
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=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 && channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(channels[0]){
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
lus=channel_read_buffer(channel,readbuf,0,0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
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
write(1,buffer_get(readbuf),lus);
}
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
lus=channel_read_buffer(channel,readbuf,0,1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
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
write(2,buffer_get(readbuf),lus);
}
}
if(channel && channel_is_closed(channel)){
channel_free(channel);
channel=NULL;
}
}
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)
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
write(1,buffer,lus);
}
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
write(2,buffer,lus);
}
}
if(channel && channel_is_closed(channel)){
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 = channel_new(session);
if(interactive){
tcgetattr(0,&terminal_local);
memcpy(&terminal,&terminal_local,sizeof(struct termios));
}
if(channel_open_session(channel)){
printf("error opening channel : %s\n",ssh_get_error(session));
return;
}
chan=channel;
if(interactive){
channel_request_pty(channel);
sizechanged();
}
if(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]);
channel=channel_new(session);
channel_open_session(channel);
if(channel_request_exec(channel,buffer)){
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
return;
}
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;
}
#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();
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);
#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;
}

View File

@@ -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;
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[8000]={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,8000);
printf("wrote %d bytes\n",len);
if(len != 8000){
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

View File

@@ -1,269 +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>
#include <unistd.h>
#ifndef KEYS_FOLDER
#ifdef _WIN32
#define KEYS_FOLDER
#else
#define KEYS_FOLDER "/etc/ssh/"
#endif
#endif
static int auth_password(char *user, char *password){
if(strcmp(user,"aris"))
return 0;
if(strcmp(password,"lala"))
return 0;
return 1; // authenticated
}
#ifdef HAVE_ARGP_H
const char *argp_program_version = "libssh server example "
SSH_STRINGIFY(LIBSSH_VERSION);
const char *argp_program_bug_address = "<libssh@libssh.org>";
/* Program documentation. */
static char doc[] = "libssh -- a Secure Shell protocol implementation";
/* A description of the arguments we accept. */
static char args_doc[] = "BINDADDR";
/* The options we understand. */
static struct argp_option options[] = {
{
.name = "port",
.key = 'p',
.arg = "PORT",
.flags = 0,
.doc = "Set the port to bind.",
.group = 0
},
{
.name = "hostkey",
.key = 'k',
.arg = "FILE",
.flags = 0,
.doc = "Set the host key.",
.group = 0
},
{
.name = "dsakey",
.key = 'd',
.arg = "FILE",
.flags = 0,
.doc = "Set the dsa key.",
.group = 0
},
{
.name = "rsakey",
.key = 'r',
.arg = "FILE",
.flags = 0,
.doc = "Set the rsa key.",
.group = 0
},
{
.name = "verbose",
.key = 'v',
.arg = NULL,
.flags = 0,
.doc = "Get verbose output.",
.group = 0
},
{NULL, 0, 0, 0, NULL, 0}
};
/* Parse a single option. */
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
/* Get the input argument from argp_parse, which we
* know is a pointer to our arguments structure.
*/
ssh_bind sshbind = state->input;
switch (key) {
case 'p':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
break;
case 'd':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
break;
case 'k':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
break;
case 'r':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
break;
case 'v':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
break;
case ARGP_KEY_ARG:
if (state->arg_num >= 1) {
/* Too many arguments. */
argp_usage (state);
}
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
break;
case ARGP_KEY_END:
if (state->arg_num < 1) {
/* Not enough arguments. */
argp_usage (state);
}
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
/* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
int main(int argc, char **argv){
ssh_session session;
ssh_bind sshbind;
ssh_message message;
ssh_channel chan=0;
ssh_buffer buf;
int auth=0;
int sftp=0;
int i;
int r;
sshbind=ssh_bind_new();
session=ssh_new();
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
#ifdef HAVE_ARGP_H
/*
* Parse our arguments; every option seen by parse_opt will
* be reflected in arguments.
*/
argp_parse (&argp, argc, argv, 0, 0, sshbind);
#endif
if(ssh_bind_listen(sshbind)<0){
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
return 1;
}
r=ssh_bind_accept(sshbind,session);
if(r==SSH_ERROR){
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
return 1;
}
if(ssh_accept(session)){
printf("ssh_accept: %s\n",ssh_get_error(session));
return 1;
}
do {
message=ssh_message_get(session);
if(!message)
break;
switch(ssh_message_type(message)){
case SSH_REQUEST_AUTH:
switch(ssh_message_subtype(message)){
case SSH_AUTH_METHOD_PASSWORD:
printf("User %s wants to auth with pass %s\n",
ssh_message_auth_user(message),
ssh_message_auth_password(message));
if(auth_password(ssh_message_auth_user(message),
ssh_message_auth_password(message))){
auth=1;
ssh_message_auth_reply_success(message,0);
break;
}
// not authenticated, send default message
case SSH_AUTH_METHOD_NONE:
default:
ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD);
ssh_message_reply_default(message);
break;
}
break;
default:
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (!auth);
if(!auth){
printf("auth error: %s\n",ssh_get_error(session));
ssh_disconnect(session);
return 1;
}
do {
message=ssh_message_get(session);
if(message){
switch(ssh_message_type(message)){
case SSH_REQUEST_CHANNEL_OPEN:
if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){
chan=ssh_message_channel_request_open_reply_accept(message);
break;
}
default:
ssh_message_reply_default(message);
}
ssh_message_free(message);
}
} while(message && !chan);
if(!chan){
printf("error : %s\n",ssh_get_error(session));
ssh_finalize();
return 1;
}
do {
message=ssh_message_get(session);
if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL &&
ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){
// if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){
sftp=1;
ssh_message_channel_request_reply_success(message);
break;
// }
}
if(!sftp){
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (message && !sftp);
if(!sftp){
printf("error : %s\n",ssh_get_error(session));
return 1;
}
printf("it works !\n");
buf=buffer_new();
do{
i=channel_read_buffer(chan,buf,0,0);
if(i>0)
write(1,buffer_get(buf),buffer_get_len(buf));
} while (i>0);
buffer_free(buf);
ssh_disconnect(session);
ssh_bind_free(sshbind);
ssh_finalize();
return 0;
}

View File

@@ -1,149 +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=channel_new(session);
char buffer[1];
if(channel == NULL){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
exit(EXIT_FAILURE);
}
if(channel_open_session(channel) != SSH_OK){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
exit(EXIT_FAILURE);
}
if(channel_request_exec(channel,createcommand) != SSH_OK){
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
exit(EXIT_FAILURE);
}
while(!channel_is_eof(channel)){
channel_read(channel,buffer,1,1);
write(1,buffer,1);
}
channel_close(channel);
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));
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));
return -1;
}
printf("done\n");
break;
case SSH_ERROR:
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
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:
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_finalize();
return 0;
}

View File

@@ -1,247 +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
write(1,buffer,lus);
}
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
write(2,buffer,lus);
}
}
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;
}

View File

@@ -1,8 +1,8 @@
project(libssh-headers C)
set(libssh_HDRS
callbacks.h
libssh.h
crypto.h
ssh2.h
)

View File

@@ -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 socket *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: */

View File

@@ -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 BUFFER_H_
#define BUFFER_H_
/* Describes a buffer state */
struct ssh_buffer_struct {
char *data;
uint32_t used;
uint32_t allocated;
uint32_t pos;
};
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_ */

View File

@@ -1,113 +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
/**
* @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);
typedef void (*ssh_log_callback) (ssh_session session, int priority,
const char *message, void *userdata);
/** this callback will be called with status going from 0.0 to 1.0 during
* connection */
typedef void (*ssh_status_callback) (ssh_session session, float status,
void *userdata);
struct ssh_callbacks_struct {
/** size of this structure. internal, shoud be set with ssh_callbacks_init()*/
size_t size;
/** User-provided data. User is free to set anything he wants here */
void *userdata;
/** this functions will be called if e.g. a keyphrase is needed. */
ssh_auth_callback auth_function;
/** this function will be called each time a loggable event happens. */
ssh_log_callback log_function;
/** this function gets called during connection time to indicate the percentage
* of connection steps completed.
*/
void (*connect_status_function)(void *userdata, float status);
};
typedef struct ssh_callbacks_struct * ssh_callbacks;
/** 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);
/**
* @brief Set the callback functions.
*
* This functions sets the callback structure to use your own callback
* functions for auth, logging and status.
*
* @code
* struct ssh_callbacks_struct cb;
* memset(&cb, 0, sizeof(struct ssh_callbacks_struct));
* cb.userdata = data;
* cb.auth_function = my_auth_function;
*
* ssh_callbacks_init(&cb);
* ssh_set_callbacks(session, &cb);
* @endcode
*
* @param session The session to set the callback structure.
*
* @param cb The callback itself.
*
* @return 0 on success, < 0 on error.
*/
LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
#ifdef __cplusplus
}
#endif
#endif /*_SSH_CALLBACK_H */

View File

@@ -1,58 +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"
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;
int open; /* shows if the channel is still opened */
int delayed_close;
ssh_buffer stdout_buffer;
ssh_buffer stderr_buffer;
void *userarg;
int version;
int blocking;
int exit_status;
};
void channel_handle(ssh_session session, int type);
ssh_channel channel_new(ssh_session session);
int channel_default_bufferize(ssh_channel channel, void *data, int len,
int is_stderr);
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);
#endif /* CHANNELS_H_ */

View File

@@ -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,27 +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 */
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 */
@@ -92,4 +66,3 @@ struct crypto_struct {
};
/* vim: set ts=2 sw=2 et cindent: */
#endif /* _CRYPTO_H_ */

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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
#ifdef LIBSSH_STATIC
#define LIBSSH_API
#else
#if defined _WIN32 || defined __CYGWIN__
#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
#else
#if __GNUC__ >= 4
#define LIBSSH_API __attribute__((visibility("default")))
#else
#define LIBSSH_API
#endif
#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,8 +50,8 @@
/* libssh version */
#define LIBSSH_VERSION_MAJOR 0
#define LIBSSH_VERSION_MINOR 4
#define LIBSSH_VERSION_MICRO 6
#define LIBSSH_VERSION_MINOR 3
#define LIBSSH_VERSION_MICRO 1
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
LIBSSH_VERSION_MINOR, \
@@ -95,128 +67,84 @@
#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;
struct keys_struct;
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_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_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,
};
#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
};
#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 */
@@ -224,10 +152,16 @@ enum ssh_error_types_e {
#define SSH_AGAIN -2 /* The nonblocking call must be repeated */
#define SSH_EOF -127 /* We have already a eof */
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 {
@@ -237,224 +171,214 @@ 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,
/* 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);
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
};
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
};
/* 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);
/* get copyright informations */
const char *ssh_copyright(void);
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
};
/* string.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);
/* 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 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);
/* 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 void privatekey_free(ssh_private_key prv);
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
int type, const char *passphrase);
LIBSSH_API void publickey_free(ssh_public_key key);
LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file,
ssh_string pubkey, int type);
LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
int *type);
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type);
/* 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 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 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_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 ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
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);
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);
LIBSSH_API int 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);
STRING *try_publickey_from_file(SSH_SESSION *session,
struct keys_struct keytab,
char **privkeyfile, 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);
char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
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 const char *ssh_version(int req_version);
LIBSSH_API int ssh_write_knownhost(ssh_session session);
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);
/* init.c */
int ssh_finalize(void);
#ifdef __cplusplus
}

View File

@@ -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 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_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;
};
void message_handle(ssh_session session, uint32_t type);
int ssh_execute_message_callbacks(ssh_session session);
#endif /* MESSAGES_H_ */

View File

@@ -1,71 +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);
/* 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_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_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))
#endif /* MISC_H_ */

View File

@@ -1,41 +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;
void packet_parse(ssh_session session);
int packet_send(ssh_session session);
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);
#endif /* PACKET_H_ */

View File

@@ -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: */

View File

@@ -1,156 +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.
*
* @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
* it's 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_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);
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p);
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout);
#endif /* POLL_H_ */

View File

@@ -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,79 +29,15 @@
#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
# undef strdup
# define strdup _strdup
# 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 */
# ifndef HAVE_STRNCPY
# define strncpy(d, s, n) strncpy_s((d), (n), (s), _TRUNCATE)
# endif
# 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
#define ERROR_BUFFERLEN 1024
@@ -109,147 +45,680 @@
#define CLIENTBANNER2 "SSH-2.0-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
#define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
/* some types for public keys */
enum public_key_types_e{
TYPE_DSS=1,
TYPE_RSA,
TYPE_RSA1
};
#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];
} __attribute__ ((packed));
/** 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 */
unsigned int error_code;
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;
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;
ssh_callbacks callbacks; /* Callbacks to user functions */
/* 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 error_struct error;
socket_t bindfd;
SSH_OPTIONS *options;
int blocking;
int toaccept;
};
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);
char *ssh_get_banner(ssh_session session);
/* 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*/
int packet_hmac_verify(ssh_session session,ssh_buffer buffer,unsigned char *mac);
int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,unsigned char *mac);
/* in packet.c */
void packet_parse(SSH_SESSION *session);
int packet_send(SSH_SESSION *session);
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 */
int ssh_regex_init(void);
void ssh_regex_finalize(void);
ssh_session ssh_session_new(void);
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);
/* 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_get_kex(ssh_session session, int server_kex);
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);
/* 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, ssh_string pubkey);
int ssh_userauth1_password(ssh_session session, const char *username,
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(ssh_channel channel);
int channel_request_pty_size1(ssh_channel channel, const char *terminal,
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(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_handle1(ssh_session session, int type);
int channel_write1(ssh_channel channel, const void *data, int len);
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);
/* 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){ \
@@ -266,18 +735,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);
/** Free memory space */
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)

View File

@@ -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

View File

@@ -1,4 +1,3 @@
/* Public include file for server support */
/*
* This file is part of the SSH Library
*
@@ -36,101 +35,82 @@
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;
typedef struct ssh_bind_struct* ssh_bind;
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 opitons for the current SSH server bind.
*
* @param sshbind The ssh server bind to use.
* @param ssh_bind The ssh server bind to use.
*
* @param type The option type to set.
*
* @param value The option value to set.
*
* @return 0 on success, < 0 on error.
* @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);
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
* @param ssh_bind The ssh server bind to accept a connection.
*
* @return A newly allocated ssh session, NULL on error.
*/
LIBSSH_API int ssh_bind_accept(ssh_bind ssh_bind_o, 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.
@@ -139,45 +119,54 @@ LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o);
*
* @return 0 on success, < 0 on error.
*/
LIBSSH_API int ssh_accept(ssh_session session);
LIBSSH_API int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len);
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 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_set_methods(ssh_message msg, int methods);
#define SSH_AUTH_REQUEST 1
#define SSH_CHANNEL_REQUEST_OPEN 2
#define SSH_CHANNEL_REQUEST 3
LIBSSH_API int ssh_message_service_reply_success(ssh_message msg);
LIBSSH_API char *ssh_message_service_service(ssh_message msg);
#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 void ssh_set_message_callback(ssh_session session,
int(*ssh_message_callback)(ssh_session session, 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 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);
#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 ssh_channel ssh_message_channel_request_channel(ssh_message msg);
typedef struct ssh_message SSH_MESSAGE;
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);
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 char *ssh_message_channel_request_env_name(ssh_message msg);
LIBSSH_API char *ssh_message_channel_request_env_value(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_command(ssh_message msg);
CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg);
LIBSSH_API char *ssh_message_channel_request_subsystem(ssh_message msg);
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
}

View File

@@ -1,122 +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"
typedef struct ssh_kbdint_struct* ssh_kbdint;
struct ssh_session_struct {
struct error_struct error;
struct socket *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;
/* socket status */
int blocking; // functions should block
ssh_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 */
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 */
int packet_state;
int dh_handshake_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);
int log_verbosity; /*cached copy of the option structure */
int log_indent; /* indentation level in enter_function logs */
ssh_callbacks callbacks; /* Callbacks to user functions */
/* 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];
unsigned long timeout; /* seconds */
unsigned long timeout_usec;
unsigned int port;
socket_t fd;
int ssh2;
int ssh1;
char *ProxyCommand;
};
int ssh_handle_packets(ssh_session session);
void ssh_global_request_handle(ssh_session session);
#endif /* SESSION_H_ */

View File

@@ -25,12 +25,12 @@
* @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 ssh_sftp SFTP Functions
* @{
@@ -38,155 +38,126 @@
#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,58 +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);
/**
* @brief Create a symbolic link.
*
* @param sftp The sftp session handle.
*
* @param target Specifies the target of the symlink.
*
* @param dest Specifies the path name of the symlink to be created.
*
* @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);
/**
* @brief Read the value of a symbolic link.
*
* @param sftp The sftp session handle.
*
* @param path Specifies the path name of the symlink to be read.
*
* @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);
int sftp_utimes(SFTP_SESSION *sftp, const char *file, const struct timeval *times);
/**
* @brief Canonicalize a sftp path.
@@ -731,7 +601,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 +610,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 +622,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 +631,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
@@ -892,9 +762,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
} ;

View File

@@ -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 SOCKET_H_
#define SOCKET_H_
/* 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);
void ssh_socket_cleanup(void);
#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, socket_t *max_fd);
int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len);
int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len);
int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t 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);
#ifndef _WIN32
void ssh_execute_command(const char *command, socket_t in, socket_t out);
socket_t ssh_socket_connect_proxycommand(ssh_session session,
const char *command);
#endif
#endif /* SOCKET_H_ */

View File

@@ -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_ */

View File

@@ -1,119 +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"
#ifdef MD5_DIGEST_LEN
#undef MD5_DIGEST_LEN
#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;
#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;
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
#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)
#endif /* OPENSSL_CRYPTO */
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
View 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_

View File

@@ -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,15 +59,14 @@ if (GCRYPT_LIBRARY)
)
endif (GCRYPT_LIBRARY)
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
@@ -95,20 +86,12 @@ set(libssh_SRCS
packet.c
poll.c
session.c
scp.c
socket.c
string.c
wrapper.c
libssh.map
)
if (WITH_PCAP)
set(libssh_SRCS
${libssh_SRCS}
pcap.c
)
endif (WITH_PCAP)
if (WITH_SFTP)
set(libssh_SRCS
${libssh_SRCS}
@@ -156,27 +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})
target_link_libraries(${LIBSSH_STATIC_LIBRARY} ${LIBSSH_LINK_LIBRARIES})
set_target_properties(
${LIBSSH_STATIC_LIBRARY}
PROPERTIES
@@ -184,8 +162,8 @@ if (WITH_STATIC_LIB)
${LIBRARY_VERSION}
SOVERSION
${LIBRARY_SOVERSION}
COMPILE_FLAGS
"-DLIBSSH_STATIC"
OUTPUT_NAME
ssh
)
install(

View File

@@ -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(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(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(struct 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(struct 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,7 +147,7 @@ void agent_close(struct ssh_agent_struct *agent) {
}
}
void agent_free(ssh_agent agent) {
void agent_free(AGENT *agent) {
if (agent) {
if (agent->ident) {
buffer_free(agent->ident);
@@ -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,10 +199,10 @@ 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_len(request);
ssh_log(session, SSH_LOG_PACKET, "agent_talk - len of request: %u", len);
@@ -214,7 +210,10 @@ static int agent_talk(struct ssh_session_struct *session,
/* 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:
@@ -303,7 +302,7 @@ int agent_get_ident_count(struct ssh_session_struct *session) {
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);
@@ -328,7 +327,7 @@ int agent_get_ident_count(struct ssh_session_struct *session) {
}
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;
@@ -395,16 +394,16 @@ 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);
@@ -452,7 +451,7 @@ ssh_string agent_sign_data(struct ssh_session_struct *session,
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)) {
@@ -479,7 +478,7 @@ error:
return NULL;
}
int agent_is_running(ssh_session session) {
int agent_is_running(SSH_SESSION *session) {
if (session == NULL || session->agent == NULL) {
return 0;
}

View File

@@ -32,13 +32,6 @@
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#include "libssh/agent.h"
#include "libssh/keyfiles.h"
#include "libssh/misc.h"
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/keys.h"
/** \defgroup ssh_auth SSH Authentication functions
* \brief functions to authenticate to servers
@@ -46,7 +39,7 @@
/** \addtogroup ssh_auth
* @{ */
static int ask_userauth(ssh_session session) {
static int ask_userauth(SSH_SESSION *session) {
int rc = 0;
enter_function();
@@ -63,12 +56,12 @@ static int ask_userauth(ssh_session session) {
return rc;
}
static int wait_auth_status(ssh_session session, int kbdint) {
static int wait_auth_status(SSH_SESSION *session, int kbdint) {
char *auth_methods = NULL;
ssh_string auth;
STRING *auth;
int rc = SSH_AUTH_ERROR;
int cont = 1;
uint8_t partial = 0;
u8 partial = 0;
enter_function();
@@ -146,7 +139,7 @@ static int wait_auth_status(ssh_session session, int kbdint) {
break;
case SSH2_MSG_USERAUTH_BANNER:
{
ssh_string banner;
STRING *banner;
banner = buffer_get_ssh_string(session->in_buffer);
if (banner == NULL) {
@@ -170,33 +163,24 @@ static int wait_auth_status(ssh_session session, int kbdint) {
return rc;
}
/**
* @brief retrieves available authentication methods for this session
* @deprecated
* @see ssh_userauth_list
*/
int ssh_auth_list(ssh_session session) {
return ssh_userauth_list(session, NULL);
int ssh_auth_list(SSH_SESSION *session) {
if (session == NULL) {
return -1;
}
return session->auth_methods;
}
/**
* @brief retrieves available authentication methods for this session
* @param[in] session the SSH session
* @param[in] username set to NULL
* @returns A bitfield of values SSH_AUTH_METHOD_NONE, SSH_AUTH_METHOD_PASSWORD,
SSH_AUTH_METHOD_PUBLICKEY, SSH_AUTH_METHOD_HOSTBASED,
SSH_AUTH_METHOD_INTERACTIVE.
@warning Other reserved flags may appear in future versions.
*/
int ssh_userauth_list(ssh_session session, const char *username) {
if (session == NULL) {
int ssh_userauth_list(SSH_SESSION *session, const char *username) {
if (session == NULL || username == NULL) {
return SSH_AUTH_ERROR;
}
if (session->auth_methods == 0) {
ssh_userauth_none(session, username);
}
return session->auth_methods;
return ssh_auth_list(session);
}
/* use the "none" authentication question */
@@ -216,15 +200,15 @@ int ssh_userauth_list(ssh_session session, const char *username) {
* have to use another method\n
* SSH_AUTH_SUCCESS: Authentication success
*/
int ssh_userauth_none(ssh_session session, const char *username) {
ssh_string user = NULL;
ssh_string service = NULL;
ssh_string method = NULL;
int ssh_userauth_none(SSH_SESSION *session, const char *username) {
STRING *user = NULL;
STRING *service = NULL;
STRING *method = NULL;
int rc = SSH_AUTH_ERROR;
enter_function();
#ifdef WITH_SSH1
#ifdef HAVE_SSH1
if (session->version == 1) {
ssh_userauth1_none(session, username);
leave_function();
@@ -233,13 +217,13 @@ int ssh_userauth_none(ssh_session session, const char *username) {
#endif
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_apply(session) < 0) {
if (session->options->username == NULL) {
if (ssh_options_default_username(session->options) < 0) {
leave_function();
return rc;
}
}
user = string_from_char(session->username);
user = string_from_char(session->options->username);
} else {
user = string_from_char(username);
}
@@ -284,7 +268,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
leave_function();
return rc;
error:
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
string_free(service);
string_free(method);
string_free(user);
@@ -320,17 +304,17 @@ error:
* @see privatekey_from_file()
* @see ssh_userauth_pubkey()
*/
int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
int type, ssh_string publickey) {
ssh_string user = NULL;
ssh_string service = NULL;
ssh_string method = NULL;
ssh_string algo = NULL;
int ssh_userauth_offer_pubkey(SSH_SESSION *session, const char *username,
int type, STRING *publickey) {
STRING *user = NULL;
STRING *service = NULL;
STRING *method = NULL;
STRING *algo = NULL;
int rc = SSH_AUTH_ERROR;
enter_function();
#ifdef WITH_SSH1
#ifdef HAVE_SSH1
if (session->version == 1) {
ssh_userauth1_offer_pubkey(session, username, type, publickey);
leave_function();
@@ -339,13 +323,13 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
#endif
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_apply(session) < 0) {
if (session->options->username == NULL) {
if (ssh_options_default_username(session->options) < 0) {
leave_function();
return rc;
}
}
user = string_from_char(session->username);
user = string_from_char(session->options->username);
} else {
user = string_from_char(username);
}
@@ -398,7 +382,7 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
leave_function();
return rc;
error:
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
string_free(user);
string_free(method);
string_free(service);
@@ -433,13 +417,13 @@ error:
* @see privatekey_free()
* @see ssh_userauth_offer_pubkey()
*/
int ssh_userauth_pubkey(ssh_session session, const char *username,
ssh_string publickey, ssh_private_key privatekey) {
ssh_string user = NULL;
ssh_string service = NULL;
ssh_string method = NULL;
ssh_string algo = NULL;
ssh_string sign = NULL;
int ssh_userauth_pubkey(SSH_SESSION *session, const char *username,
STRING *publickey, PRIVATE_KEY *privatekey) {
STRING *user = NULL;
STRING *service = NULL;
STRING *method = NULL;
STRING *algo = NULL;
STRING *sign = NULL;
int rc = SSH_AUTH_ERROR;
enter_function();
@@ -451,13 +435,13 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
#endif
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_apply(session) < 0) {
if (session->options->username == NULL) {
if (ssh_options_default_username(session->options) < 0) {
leave_function();
return rc;
}
}
user = string_from_char(session->username);
user = string_from_char(session->options->username);
} else {
user = string_from_char(username);
}
@@ -519,7 +503,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
leave_function();
return rc;
error:
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
string_free(user);
string_free(service);
string_free(method);
@@ -552,14 +536,14 @@ error:
* @see privatekey_free()
* @see ssh_userauth_offer_pubkey()
*/
int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
ssh_public_key publickey) {
ssh_string user = NULL;
ssh_string service = NULL;
ssh_string method = NULL;
ssh_string algo = NULL;
ssh_string key = NULL;
ssh_string sign = NULL;
int ssh_userauth_agent_pubkey(SSH_SESSION *session, const char *username,
PUBLIC_KEY *publickey) {
STRING *user = NULL;
STRING *service = NULL;
STRING *method = NULL;
STRING *algo = NULL;
STRING *key = NULL;
STRING *sign = NULL;
int rc = SSH_AUTH_ERROR;
enter_function();
@@ -569,13 +553,13 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
}
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_apply(session) < 0) {
if (session->options->username == NULL) {
if (ssh_options_default_username(session->options) < 0) {
leave_function();
return rc;
}
}
user = string_from_char(session->username);
user = string_from_char(session->options->username);
} else {
user = string_from_char(username);
}
@@ -643,7 +627,7 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
return rc;
error:
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
string_free(sign);
string_free(user);
string_free(service);
@@ -677,17 +661,17 @@ error:
* @see ssh_userauth_kbdint()
* @see BURN_STRING
*/
int ssh_userauth_password(ssh_session session, const char *username,
int ssh_userauth_password(SSH_SESSION *session, const char *username,
const char *password) {
ssh_string user = NULL;
ssh_string service = NULL;
ssh_string method = NULL;
ssh_string pwd = NULL;
STRING *user = NULL;
STRING *service = NULL;
STRING *method = NULL;
STRING *pwd = NULL;
int rc = SSH_AUTH_ERROR;
enter_function();
#ifdef WITH_SSH1
#ifdef HAVE_SSH1
if (session->version == 1) {
rc = ssh_userauth1_password(session, username, password);
leave_function();
@@ -696,13 +680,13 @@ int ssh_userauth_password(ssh_session session, const char *username,
#endif
if (username == NULL) {
if (session->username == NULL) {
if (ssh_options_apply(session) < 0) {
if (session->options->username == NULL) {
if (ssh_options_default_username(session->options) < 0) {
leave_function();
return rc;
}
}
user = string_from_char(session->username);
user = string_from_char(session->options->username);
} else {
user = string_from_char(username);
}
@@ -755,7 +739,7 @@ int ssh_userauth_password(ssh_session session, const char *username,
leave_function();
return rc;
error:
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
string_free(user);
string_free(service);
string_free(method);
@@ -766,6 +750,28 @@ error:
return rc;
}
static struct keys_struct keytab[] = {
{
.privatekey = "%s/.ssh/identity",
.publickey = "%s/.ssh/identity.pub"
},
{
.privatekey = "%s/.ssh/id_dsa",
.publickey = "%s/.ssh/id_dsa.pub",
},
{
.privatekey = "%s/.ssh/id_rsa",
.publickey = "%s/.ssh/id_rsa.pub",
},
{
.privatekey = NULL,
.publickey = NULL
}
};
/* this function initialy was in the client */
/* but the fools are the ones who never change mind */
/**
* @brief Tries to automaticaly authenticate with public key and "none"
*
@@ -786,12 +792,16 @@ error:
*
* @see ssh_userauth_kbdint()
* @see ssh_userauth_password()
* @see ssh_options_set_identity()
*/
int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
struct ssh_iterator *it;
ssh_private_key privkey;
ssh_public_key pubkey;
ssh_string pubkey_string;
int ssh_userauth_autopubkey(SSH_SESSION *session, const char *passphrase) {
struct public_key_struct *publickey;
STRING *pubkey;
PRIVATE_KEY *privkey;
char *privkeyfile = NULL;
char *id = NULL;
size_t size;
unsigned int i = 0;
int type = 0;
int rc;
@@ -807,159 +817,139 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
/* Try authentication with ssh-agent first */
#ifndef _WIN32
if (agent_is_running(session)) {
char *privkey_file = NULL;
ssh_log(session, SSH_LOG_RARE,
"Trying to authenticate with SSH agent keys as user: %s",
session->username);
"Trying to authenticate with SSH agent keys");
for (pubkey = agent_get_first_ident(session, &privkey_file);
pubkey != NULL;
pubkey = agent_get_next_ident(session, &privkey_file)) {
for (publickey = agent_get_first_ident(session, &privkeyfile);
publickey != NULL;
publickey = agent_get_next_ident(session, &privkeyfile)) {
ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkey_file);
ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkeyfile);
pubkey_string = publickey_to_string(pubkey);
if (pubkey_string) {
rc = ssh_userauth_offer_pubkey(session, NULL, pubkey->type, pubkey_string);
string_free(pubkey_string);
pubkey = publickey_to_string(publickey);
if (pubkey) {
rc = ssh_userauth_offer_pubkey(session, NULL, publickey->type, pubkey);
string_free(pubkey);
if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(privkey_file);
publickey_free(pubkey);
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
leave_function();
return rc;
} else if (rc != SSH_AUTH_SUCCESS) {
ssh_log(session, SSH_LOG_PROTOCOL, "Public key refused by server");
SAFE_FREE(privkey_file);
publickey_free(pubkey);
ssh_log(session, SSH_LOG_PACKET, "Public key refused by server\n");
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
continue;
}
ssh_log(session, SSH_LOG_RARE, "Public key accepted");
/* pubkey accepted by server ! */
rc = ssh_userauth_agent_pubkey(session, NULL, pubkey);
rc = ssh_userauth_agent_pubkey(session, NULL, publickey);
if (rc == SSH_AUTH_ERROR) {
SAFE_FREE(privkey_file);
publickey_free(pubkey);
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
leave_function();
return rc;
} else if (rc != SSH_AUTH_SUCCESS) {
ssh_log(session, SSH_LOG_RARE,
"Server accepted public key but refused the signature ;"
" It might be a bug of libssh");
SAFE_FREE(privkey_file);
publickey_free(pubkey);
"Server accepted public key but refused the signature\n"
"It might be a bug of libssh\n");
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
continue;
}
/* auth success */
ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success",
privkey_file);
SAFE_FREE(privkey_file);
publickey_free(pubkey);
ssh_log(session, SSH_LOG_RARE, "Authentication using %s success\n",
privkeyfile);
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
leave_function();
return SSH_AUTH_SUCCESS;
} /* if pubkey */
SAFE_FREE(privkey_file);
publickey_free(pubkey);
SAFE_FREE(id);
SAFE_FREE(privkeyfile);
publickey_free(publickey);
} /* for each privkey */
} /* if agent is running */
#endif
size = ARRAY_SIZE(keytab);
if (session->options->identity) {
ssh_log(session, SSH_LOG_RARE,
"Trying identity file %s\n", session->options->identity);
for (it = ssh_list_get_iterator(session->identity);
it != NULL;
it = it->next) {
const char *privkey_file = it->data;
int privkey_open = 0;
id = malloc(strlen(session->options->identity) + 1 + 4);
if (id == NULL) {
leave_function();
return SSH_AUTH_ERROR;
}
sprintf(id, "%s.pub", session->options->identity);
privkey = NULL;
keytab[size - 1].privatekey = session->options->identity;
keytab[size - 1].publickey = id;
}
ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file);
rc = ssh_try_publickey_from_file(session, privkey_file, &pubkey_string, &type);
if (rc == 1) {
char *publickey_file;
size_t len;
privkey = privatekey_from_file(session, privkey_file, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_RARE,
"Reading private key %s failed (bad passphrase ?)",
privkey_file);
leave_function();
return SSH_AUTH_ERROR;
}
privkey_open = 1;
pubkey = publickey_from_privatekey(privkey);
if (pubkey == NULL) {
privatekey_free(privkey);
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
pubkey_string = publickey_to_string(pubkey);
type = pubkey->type;
publickey_free(pubkey);
if (pubkey_string == NULL) {
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
len = strlen(privkey_file) + 5;
publickey_file = malloc(len);
if (publickey_file == NULL) {
ssh_set_error_oom(session);
leave_function();
return SSH_AUTH_ERROR;
}
snprintf(publickey_file, len, "%s.pub", privkey_file);
rc = ssh_publickey_to_file(session, publickey_file, pubkey_string, type);
if (rc < 0) {
ssh_log(session, SSH_LOG_PACKET,
"Could not write public key to file: %s", publickey_file);
}
SAFE_FREE(publickey_file);
} else if (rc < 0) {
for (i = 0, pubkey = try_publickey_from_file(session, keytab[i],
&privkeyfile, &type);
i < size;
pubkey = try_publickey_from_file(session, keytab[i++],
&privkeyfile, &type)) {
if (pubkey == NULL) {
continue;
}
rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string);
rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey);
if (rc == SSH_AUTH_ERROR){
string_free(pubkey_string);
ssh_log(session, SSH_LOG_RARE, "Publickey authentication error");
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
string_free(pubkey);
SAFE_FREE(privkeyfile);
leave_function();
return rc;
} else {
if (rc != SSH_AUTH_SUCCESS){
ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server");
string_free(pubkey_string);
ssh_log(session, SSH_LOG_RARE, "Public key refused by server");
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
continue;
}
}
/* Public key accepted by server! */
if (!privkey_open) {
ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s",
privkey_file);
privkey = privatekey_from_file(session, privkey_file, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_RARE,
"Reading private key %s failed (bad passphrase ?)",
privkey_file);
string_free(pubkey_string);
continue; /* continue the loop with other pubkey */
}
privkey = privatekey_from_file(session, privkeyfile, type, passphrase);
if (privkey == NULL) {
ssh_log(session, SSH_LOG_FUNCTIONS,
"Reading private key %s failed (bad passphrase ?)",
privkeyfile);
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
continue; /* continue the loop with other pubkey */
}
rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey);
rc = ssh_userauth_pubkey(session, NULL, pubkey, privkey);
if (rc == SSH_AUTH_ERROR) {
string_free(pubkey_string);
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
string_free(pubkey);
SAFE_FREE(privkeyfile);
privatekey_free(privkey);
leave_function();
return rc;
@@ -967,44 +957,48 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
if (rc != SSH_AUTH_SUCCESS){
ssh_log(session, SSH_LOG_FUNCTIONS,
"The server accepted the public key but refused the signature");
string_free(pubkey_string);
string_free(pubkey);
pubkey = NULL;
SAFE_FREE(privkeyfile);
privkeyfile = NULL;
privatekey_free(privkey);
continue;
}
}
/* auth success */
ssh_log(session, SSH_LOG_PROTOCOL,
"Successfully authenticated using %s", privkey_file);
string_free(pubkey_string);
ssh_log(session, SSH_LOG_RARE,
"Successfully authenticated using %s", privkeyfile);
string_free(pubkey);
privatekey_free(privkey);
SAFE_FREE(privkeyfile);
if (id != NULL) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
leave_function();
return SSH_AUTH_SUCCESS;
}
/* at this point, pubkey is NULL and so is privkeyfile */
ssh_log(session, SSH_LOG_FUNCTIONS,
"Tried every public key, none matched");
ssh_set_error(session,SSH_NO_ERROR,"No public key matched");
if (id) {
keytab[size - 1].privatekey = NULL;
keytab[size - 1].publickey = NULL;
SAFE_FREE(id);
}
leave_function();
return SSH_AUTH_DENIED;
}
struct ssh_kbdint_struct {
uint32_t nprompts;
char *name;
char *instruction;
char **prompts;
unsigned char *echo; /* bool array */
char **answers;
};
static struct ssh_kbdint *kbdint_new(void) {
struct ssh_kbdint *kbd;
static ssh_kbdint kbdint_new(void) {
ssh_kbdint kbd;
kbd = malloc(sizeof (struct ssh_kbdint_struct));
kbd = malloc(sizeof (struct ssh_kbdint));
if (kbd == NULL) {
return NULL;
}
@@ -1014,7 +1008,7 @@ static ssh_kbdint kbdint_new(void) {
}
static void kbdint_free(ssh_kbdint kbd) {
static void kbdint_free(struct ssh_kbdint *kbd) {
int i, n;
if (kbd == NULL) {
@@ -1045,7 +1039,7 @@ static void kbdint_free(ssh_kbdint kbd) {
SAFE_FREE(kbd);
}
static void kbdint_clean(ssh_kbdint kbd) {
static void kbdint_clean(struct ssh_kbdint *kbd) {
int i, n;
if (kbd == NULL) {
@@ -1079,12 +1073,12 @@ static void kbdint_clean(ssh_kbdint kbd) {
/* this function sends the first packet as explained in section 3.1
* of the draft */
static int kbdauth_init(ssh_session session, const char *user,
static int kbdauth_init(SSH_SESSION *session, const char *user,
const char *submethods) {
ssh_string usr = NULL;
ssh_string sub = NULL;
ssh_string service = NULL;
ssh_string method = NULL;
STRING *usr = NULL;
STRING *sub = NULL;
STRING *service = NULL;
STRING *method = NULL;
int rc = SSH_AUTH_ERROR;
enter_function();
@@ -1129,7 +1123,7 @@ static int kbdauth_init(ssh_session session, const char *user,
leave_function();
return rc;
error:
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
string_free(usr);
string_free(service);
string_free(method);
@@ -1139,12 +1133,12 @@ error:
return rc;
}
static int kbdauth_info_get(ssh_session session) {
ssh_string name; /* name of the "asking" window showed to client */
ssh_string instruction;
ssh_string tmp;
uint32_t nprompts;
uint32_t i;
static int kbdauth_info_get(SSH_SESSION *session) {
STRING *name; /* name of the "asking" window showed to client */
STRING *instruction;
STRING *tmp;
u32 nprompts;
u32 i;
enter_function();
@@ -1256,10 +1250,10 @@ static int kbdauth_info_get(ssh_session session) {
}
/* sends challenge back to the server */
static int kbdauth_send(ssh_session session) {
ssh_string answer = NULL;
static int kbdauth_send(SSH_SESSION *session) {
STRING *answer = NULL;
int rc = SSH_AUTH_ERROR;
uint32_t i;
u32 i;
enter_function();
@@ -1296,7 +1290,7 @@ static int kbdauth_send(ssh_session session) {
leave_function();
return rc;
error:
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
string_burn(answer);
string_free(answer);
@@ -1329,7 +1323,7 @@ error:
* @see ssh_userauth_kbdint_getprompt()
* @see ssh_userauth_kbdint_setanswer()
*/
int ssh_userauth_kbdint(ssh_session session, const char *user,
int ssh_userauth_kbdint(SSH_SESSION *session, const char *user,
const char *submethods) {
int rc = SSH_AUTH_ERROR;
@@ -1343,12 +1337,12 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
if (session->kbdint == NULL) {
/* first time we call. we must ask for a challenge */
if (user == NULL) {
if ((user = session->username) == NULL) {
if (ssh_options_apply(session) < 0) {
if ((user = session->options->username) == NULL) {
if (ssh_options_default_username(session->options) < 0) {
leave_function();
return SSH_AUTH_ERROR;
} else {
user = session->username;
user = session->options->username;
}
}
}
@@ -1376,7 +1370,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
/*
* If we are at this point, it ss because session->kbdint exists.
* It means the user has set some information there we need to send
* It means the user has set some informations there we need to send
* the server and then we need to ack the status (new questions or ok
* pass in).
*/
@@ -1409,7 +1403,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
*
* @returns The number of prompts.
*/
int ssh_userauth_kbdint_getnprompts(ssh_session session) {
int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session) {
return session->kbdint->nprompts;
}
@@ -1423,7 +1417,7 @@ int ssh_userauth_kbdint_getnprompts(ssh_session session) {
*
* @returns The name of the message block. Do not free it.
*/
const char *ssh_userauth_kbdint_getname(ssh_session session) {
char *ssh_userauth_kbdint_getname(SSH_SESSION *session) {
return session->kbdint->name;
}
@@ -1438,7 +1432,7 @@ const char *ssh_userauth_kbdint_getname(ssh_session session) {
* @returns The instruction of the message block.
*/
const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session) {
return session->kbdint->instruction;
}
@@ -1458,7 +1452,7 @@ const char *ssh_userauth_kbdint_getinstruction(ssh_session session) {
*
* @returns A pointer to the prompt. Do not free it.
*/
const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, unsigned int i,
char *echo) {
if (i > session->kbdint->nprompts) {
return NULL;
@@ -1479,9 +1473,9 @@ const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i,
* \param answer answer to give to server
* \return 0 on success, < 0 on error.
*/
int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i,
int ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i,
const char *answer) {
if (session == NULL || answer == NULL || i > session->kbdint->nprompts) {
if (i > session->kbdint->nprompts) {
return -1;
}

View File

@@ -21,20 +21,14 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include "libssh/priv.h"
#include "libssh/ssh1.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/string.h"
#ifdef WITH_SSH1
static int wait_auth1_status(ssh_session session) {
#ifdef HAVE_SSH1
static int wait_auth1_status(SSH_SESSION *session) {
/* wait for a packet */
if (packet_read(session) != SSH_OK) {
return SSH_AUTH_ERROR;
@@ -57,19 +51,19 @@ static int wait_auth1_status(ssh_session session) {
return SSH_AUTH_ERROR;
}
static int send_username(ssh_session session, const char *username) {
ssh_string user = NULL;
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->username)) {
if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) {
if(!(username = session->options->username)) {
if(ssh_options_default_username(session->options)) {
return session->auth_service_asked = SSH_AUTH_ERROR;
} else {
username = session->username;
username = session->options->username;
}
}
}
@@ -97,16 +91,16 @@ static int send_username(ssh_session session, const char *username) {
}
/* use the "none" authentication question */
int ssh_userauth1_none(ssh_session session, const char *username){
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, ssh_string publickey){
ssh_string user;
ssh_string service;
ssh_string method;
ssh_string algo;
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)){
@@ -142,22 +136,18 @@ int ssh_userauth_offer_pubkey(ssh_session session, char *username,int type, ssh_
/** \internal
* \todo implement ssh1 public key
*/
int ssh_userauth1_offer_pubkey(ssh_session session, const char *username,
int type, ssh_string pubkey) {
(void) session;
(void) username;
(void) type;
(void) pubkey;
return SSH_AUTH_DENIED;
int ssh_userauth1_offer_pubkey(SSH_SESSION *session, const char *username,
int type, STRING *pubkey) {
return SSH_AUTH_DENIED;
}
/*
int ssh_userauth_pubkey(ssh_session session, char *username, ssh_string publickey, ssh_private_key privatekey){
ssh_string user;
ssh_string service;
ssh_string method;
ssh_string algo;
ssh_string sign;
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)){
@@ -198,9 +188,9 @@ int ssh_userauth_pubkey(ssh_session session, char *username, ssh_string publicke
}
*/
int ssh_userauth1_password(ssh_session session, const char *username,
int ssh_userauth1_password(SSH_SESSION *session, const char *username,
const char *password) {
ssh_string pwd = NULL;
STRING *pwd = NULL;
int rc;
rc = send_username(session, username);
@@ -257,5 +247,5 @@ int ssh_userauth1_password(ssh_session session, const char *username,
return wait_auth1_status(session);
}
#endif /* WITH_SSH1 */
#endif /* HAVE_SSH1 */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -27,7 +27,6 @@
#include <stdlib.h>
#include "libssh/priv.h"
#include "libssh/buffer.h"
static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
@@ -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;

View File

@@ -3,7 +3,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,7 +29,7 @@
#endif
#include "libssh/priv.h"
#include "libssh/buffer.h"
/** \defgroup ssh_buffer SSH Buffers
* \brief buffer handling
*/
@@ -38,57 +38,27 @@
* @{
*/
/** \brief checks that preconditions and postconditions are valid
* \internal
*/
#ifdef DEBUG_BUFFER
static void buffer_verify(struct buffer_struct *buf){
int doabort=0;
if(buf->data == NULL)
return;
if(buf->used > buf->allocated){
fprintf(stderr,"Buffer error : allocated %u, used %u\n",buf->allocated, buf->used);
doabort=1;
}
if(buf->pos > buf->used){
fprintf(stderr,"Buffer error : position %u, used %u\n",buf->pos, buf->used);
doabort=1;
}
if(buf->pos > buf->allocated){
fprintf(stderr,"Buffer error : position %u, allocated %u\n",buf->pos, buf->allocated);
doabort=1;
}
if(doabort)
abort();
}
#else
#define buffer_verify(x)
#endif
/** \brief creates a new buffer
* \return a new initialized buffer, NULL on error.
*/
struct ssh_buffer_struct *buffer_new(void) {
struct ssh_buffer_struct *buf = malloc(sizeof(struct ssh_buffer_struct));
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 ssh_buffer_struct));
buffer_verify(buf);
memset(buf, 0, sizeof(struct buffer_struct));
return buf;
}
/** \brief deallocate a buffer
* \param buffer buffer to free
*/
void buffer_free(struct ssh_buffer_struct *buffer) {
void buffer_free(struct buffer_struct *buffer) {
if (buffer == NULL) {
return;
}
buffer_verify(buffer);
if (buffer->data) {
/* burn the data */
@@ -99,12 +69,11 @@ void buffer_free(struct ssh_buffer_struct *buffer) {
SAFE_FREE(buffer);
}
static int realloc_buffer(struct ssh_buffer_struct *buffer, int needed) {
static int realloc_buffer(struct buffer_struct *buffer, int needed) {
int smallest = 1;
char *new = NULL;
buffer_verify(buffer);
/* Find the smallest power of two which is greater or equal to needed */
while(smallest < needed) {
while(smallest <= needed) {
smallest <<= 1;
}
needed = smallest;
@@ -114,7 +83,7 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, int needed) {
}
buffer->data = new;
buffer->allocated = needed;
buffer_verify(buffer);
return 0;
}
@@ -123,8 +92,7 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, int needed) {
* \param buffer buffer
* \return 0 on sucess, < 0 on error
*/
int buffer_reinit(struct ssh_buffer_struct *buffer) {
buffer_verify(buffer);
int buffer_reinit(struct buffer_struct *buffer) {
memset(buffer->data, 0, buffer->used);
buffer->used = 0;
buffer->pos = 0;
@@ -133,7 +101,6 @@ int buffer_reinit(struct ssh_buffer_struct *buffer) {
return -1;
}
}
buffer_verify(buffer);
return 0;
}
@@ -143,8 +110,7 @@ int buffer_reinit(struct ssh_buffer_struct *buffer) {
* \param data data pointer
* \param len length of data
*/
int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
buffer_verify(buffer);
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;
@@ -153,7 +119,6 @@ int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t
memcpy(buffer->data+buffer->used, data, len);
buffer->used+=len;
buffer_verify(buffer);
return 0;
}
@@ -163,39 +128,24 @@ int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t
* \param string SSH String to add
* \return 0 on success, -1 on error.
*/
int buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
struct ssh_string_struct *string) {
uint32_t len = 0;
int buffer_add_ssh_string(struct buffer_struct *buffer,
struct string_struct *string) {
u32 len = 0;
len = string_len(string);
if (buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 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 ssh_buffer_struct *buffer,uint32_t data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
}
/** \internal
* \brief add a 16 bits unsigned integer to the tail of buffer
* \param buffer buffer
* \param data 16 bits integer
* \return 0 on success, -1 on error.
*/
int buffer_add_u16(struct ssh_buffer_struct *buffer,uint16_t data){
int buffer_add_u32(struct buffer_struct *buffer,u32 data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
@@ -209,7 +159,7 @@ int buffer_add_u16(struct ssh_buffer_struct *buffer,uint16_t data){
* \param data 64 bits integer
* \return 0 on success, -1 on error.
*/
int buffer_add_u64(struct ssh_buffer_struct *buffer, uint64_t data){
int buffer_add_u64(struct buffer_struct *buffer, u64 data){
if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
@@ -222,8 +172,8 @@ int buffer_add_u64(struct ssh_buffer_struct *buffer, uint64_t data){
* \param data 8 bits integer
* \return 0 on success, -1 on error.
*/
int buffer_add_u8(struct ssh_buffer_struct *buffer,uint8_t data){
if (buffer_add_data(buffer, &data, sizeof(uint8_t)) < 0) {
int buffer_add_u8(struct buffer_struct *buffer,u8 data){
if (buffer_add_data(buffer, &data, sizeof(u8)) < 0) {
return -1;
}
@@ -237,9 +187,8 @@ int buffer_add_u8(struct ssh_buffer_struct *buffer,uint8_t data){
* \param len length of data
* \return 0 on success, -1 on error.
*/
int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
uint32_t len) {
buffer_verify(buffer);
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;
@@ -248,7 +197,7 @@ int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
memmove(buffer->data + len, buffer->data, buffer->used);
memcpy(buffer->data, data, len);
buffer->used += len;
buffer_verify(buffer);
return 0;
}
@@ -258,8 +207,8 @@ int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
* \param source source buffer. Doesn't take position in buffer into account
* \return 0 on success, -1 on error.
*/
int buffer_add_buffer(struct ssh_buffer_struct *buffer,
struct ssh_buffer_struct *source) {
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;
}
@@ -274,7 +223,7 @@ int buffer_add_buffer(struct ssh_buffer_struct *buffer,
* \see buffer_get_rest()
* \see buffer_get_len()
*/
void *buffer_get(struct ssh_buffer_struct *buffer){
void *buffer_get(struct buffer_struct *buffer){
return buffer->data;
}
@@ -285,7 +234,7 @@ void *buffer_get(struct ssh_buffer_struct *buffer){
* \see buffer_get_rest_len()
* \see buffer_get()
*/
void *buffer_get_rest(struct ssh_buffer_struct *buffer){
void *buffer_get_rest(struct buffer_struct *buffer){
return buffer->data + buffer->pos;
}
@@ -294,7 +243,7 @@ void *buffer_get_rest(struct ssh_buffer_struct *buffer){
* \return length of the buffer
* \see buffer_get()
*/
uint32_t buffer_get_len(struct ssh_buffer_struct *buffer){
u32 buffer_get_len(struct buffer_struct *buffer){
return buffer->used;
}
@@ -304,9 +253,8 @@ uint32_t buffer_get_len(struct ssh_buffer_struct *buffer){
* \return length of the buffer
* \see buffer_get_rest()
*/
uint32_t buffer_get_rest_len(struct ssh_buffer_struct *buffer){
buffer_verify(buffer);
return buffer->used - buffer->pos;
u32 buffer_get_rest_len(struct buffer_struct *buffer){
return buffer->used - buffer->pos;
}
/** \internal
@@ -316,8 +264,7 @@ uint32_t buffer_get_rest_len(struct ssh_buffer_struct *buffer){
* \param len number of bytes to eat
* \return new size of the buffer
*/
uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer);
u32 buffer_pass_bytes(struct buffer_struct *buffer, u32 len){
if(buffer->used < buffer->pos+len)
return 0;
buffer->pos+=len;
@@ -326,7 +273,6 @@ uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
buffer->pos=0;
buffer->used=0;
}
buffer_verify(buffer);
return len;
}
@@ -336,13 +282,11 @@ uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
* \param len number of bytes to remove from tail
* \return new size of the buffer
*/
uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer);
if(buffer->used < buffer->pos + len)
return 0;
buffer->used-=len;
buffer_verify(buffer);
return len;
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
@@ -353,14 +297,9 @@ uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
* \returns 0 if there is not enough data in buffer
* \returns len otherwise.
*/
uint32_t buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t len){
/*
* Check for a integer overflow first, then check if not enough data is in
* the buffer.
*/
if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return 0;
}
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 ?? ) */
@@ -368,33 +307,33 @@ uint32_t buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t
/** \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 uint8_t where to store the data
* \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 ssh_buffer_struct *buffer, uint8_t *data){
return buffer_get_data(buffer,data,sizeof(uint8_t));
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 uint32_t where to store the data
* \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 ssh_buffer_struct *buffer, uint32_t *data){
return buffer_get_data(buffer,data,sizeof(uint32_t));
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 uint64_t where to store the data
* \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 ssh_buffer_struct *buffer, uint64_t *data){
return buffer_get_data(buffer,data,sizeof(uint64_t));
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.
@@ -402,10 +341,10 @@ int buffer_get_u64(struct ssh_buffer_struct *buffer, uint64_t *data){
* \returns The SSH String read
* \returns NULL otherwise.
*/
struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer) {
uint32_t stringlen;
uint32_t hostlen;
struct ssh_string_struct *str = NULL;
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;
@@ -419,7 +358,7 @@ struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer
if (str == NULL) {
return NULL;
}
if (buffer_get_data(buffer, string_data(str), hostlen) != hostlen) {
if (buffer_get_data(buffer, str->string, hostlen) != hostlen) {
/* should never happen */
SAFE_FREE(str);
return NULL;
@@ -435,12 +374,12 @@ struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer
* \returns NULL otherwise
*/
struct ssh_string_struct *buffer_get_mpint(struct ssh_buffer_struct *buffer) {
uint16_t bits;
uint32_t len;
struct ssh_string_struct *str = NULL;
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(uint16_t)) != sizeof(uint16_t)) {
if (buffer_get_data(buffer, &bits, sizeof(u16)) != sizeof(u16)) {
return NULL;
}
bits = ntohs(bits);
@@ -452,7 +391,7 @@ struct ssh_string_struct *buffer_get_mpint(struct ssh_buffer_struct *buffer) {
if (str == NULL) {
return NULL;
}
if (buffer_get_data(buffer, string_data(str), len) != len) {
if (buffer_get_data(buffer, str->string, len) != len) {
SAFE_FREE(str);
return NULL;
}

View File

@@ -1,37 +0,0 @@
/*
* callbacks.c - callback functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
*
* 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 "config.h"
#include "libssh/callbacks.h"
#include "libssh/session.h"
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
if (session == NULL || cb == NULL) {
return -1;
}
session->callbacks = cb;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -26,17 +26,10 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#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
#ifdef HAVE_SSH1
/*
* This is a big hack. In fact, SSH1 doesn't make a clever use of channels.
@@ -47,12 +40,12 @@
* 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. "
@@ -80,10 +73,10 @@ 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;
SSH_SESSION *session = channel->session;
STRING *str = NULL;
str = string_from_char(terminal);
if (str == NULL) {
@@ -133,8 +126,8 @@ int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col
return -1;
}
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
ssh_session session = channel->session;
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 ||
@@ -170,8 +163,8 @@ int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
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;
@@ -186,9 +179,9 @@ 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 = string_from_char(cmd);
if (command == NULL) {
@@ -211,9 +204,9 @@ int channel_request_exec1(ssh_channel channel, const char *cmd) {
return 0;
}
static int channel_rcv_data1(ssh_session session, int is_stderr) {
ssh_channel channel = session->channels;
ssh_string str = NULL;
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) {
@@ -225,7 +218,7 @@ static int channel_rcv_data1(ssh_session session, int is_stderr) {
"Adding %zu bytes data in %d",
string_len(str), is_stderr);
if (channel_default_bufferize(channel, string_data(str), string_len(str),
if (channel_default_bufferize(channel, str->string, string_len(str),
is_stderr) < 0) {
string_free(str);
return -1;
@@ -235,9 +228,9 @@ static int channel_rcv_data1(ssh_session session, int is_stderr) {
return 0;
}
static int channel_rcv_close1(ssh_session session) {
ssh_channel channel = session->channels;
uint32_t status;
static int channel_rcv_close1(SSH_SESSION *session) {
CHANNEL *channel = session->channels;
u32 status;
buffer_get_u32(session->in_buffer, &status);
/*
@@ -260,7 +253,7 @@ static int channel_rcv_close1(ssh_session session) {
return 0;
}
int channel_handle1(ssh_session session, int type) {
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:
@@ -268,11 +261,6 @@ int channel_handle1(ssh_session session, int type) {
return -1;
}
break;
case SSH_SMSG_STDERR_DATA:
if (channel_rcv_data1(session,1) < 0) {
return -1;
}
break;
case SSH_SMSG_EXITSTATUS:
if (channel_rcv_close1(session) < 0) {
return -1;
@@ -285,11 +273,11 @@ int channel_handle1(ssh_session session, int type) {
return 0;
}
int channel_write1(ssh_channel channel, const void *data, int len) {
ssh_session session = channel->session;
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;
@@ -298,11 +286,11 @@ 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_OK) {
@@ -313,5 +301,5 @@ int channel_write1(ssh_channel channel, const void *data, int len) {
return origlen;
}
#endif /* WITH_SSH1 */
#endif /* HAVE_SSH1 */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -31,15 +31,10 @@
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/socket.h"
#include "libssh/session.h"
#include "libssh/dh.h"
#define set_status(session, status) do {\
if (session->callbacks && session->callbacks->connect_status_function) \
session->callbacks->connect_status_function(session->callbacks->userdata, status); \
#define set_status(opt,status) do {\
if (opt->connect_status_function) \
opt->connect_status_function(opt->connect_status_arg, status); \
} while (0)
/**
@@ -53,7 +48,7 @@
*
* @return A newly allocated string with the banner or NULL on error.
*/
char *ssh_get_banner(ssh_session session) {
char *ssh_get_banner(SSH_SESSION *session) {
char buffer[128] = {0};
char *str = NULL;
int i;
@@ -66,11 +61,7 @@ char *ssh_get_banner(ssh_session session) {
leave_function();
return NULL;
}
#ifdef WITH_PCAP
if(session->pcap_ctx && buffer[i] == '\n'){
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
}
#endif
if (buffer[i] == '\r') {
buffer[i] = '\0';
}
@@ -106,11 +97,8 @@ char *ssh_get_banner(ssh_session session) {
*
* @see ssh_get_banner()
*/
static int ssh_analyze_banner(ssh_session session, int *ssh1, int *ssh2) {
const char *banner = session->serverbanner;
const char *openssh;
ssh_log(session, SSH_LOG_RARE, "Analyzing banner: %s", banner);
static int ssh_analyze_banner(SSH_SESSION *session, int *ssh1, int *ssh2) {
char *banner = session->serverbanner;
if (strncmp(banner, "SSH-", 4) != 0) {
ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner);
@@ -141,17 +129,6 @@ static int ssh_analyze_banner(ssh_session session, int *ssh1, int *ssh2) {
return -1;
}
openssh = strstr(banner, "OpenSSH");
if (openssh != NULL) {
int major, minor;
major = strtol(openssh + 8, (char **) NULL, 10);
minor = strtol(openssh + 10, (char **) NULL, 10);
session->openssh = SSH_VERSION_INT(major, minor, 0);
ssh_log(session, SSH_LOG_RARE,
"We are talking to an OpenSSH server version: %d.%d (%x)",
major, minor, session->openssh);
}
return 0;
}
@@ -164,7 +141,7 @@ static int ssh_analyze_banner(ssh_session session, int *ssh1, int *ssh2) {
*
* @return 0 on success, < 0 on error.
*/
int ssh_send_banner(ssh_session session, int server) {
int ssh_send_banner(SSH_SESSION *session, int server) {
const char *banner = NULL;
char buffer[128] = {0};
@@ -172,8 +149,8 @@ int ssh_send_banner(ssh_session session, int server) {
banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2;
if (session->xbanner) {
banner = session->xbanner;
if (session->options->banner) {
banner = session->options->banner;
}
if (server) {
@@ -201,10 +178,7 @@ int ssh_send_banner(ssh_session session, int server) {
leave_function();
return -1;
}
#ifdef WITH_PCAP
if(session->pcap_ctx)
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,buffer,strlen(buffer),strlen(buffer));
#endif
leave_function();
return 0;
}
@@ -215,11 +189,11 @@ int ssh_send_banner(ssh_session session, int server) {
#define DH_STATE_NEWKEYS_TO_SEND 3
#define DH_STATE_NEWKEYS_SENT 4
#define DH_STATE_FINISHED 5
static int dh_handshake(ssh_session session) {
ssh_string e = NULL;
ssh_string f = NULL;
ssh_string pubkey = NULL;
ssh_string signature = NULL;
static int dh_handshake(SSH_SESSION *session) {
STRING *e = NULL;
STRING *f = NULL;
STRING *pubkey = NULL;
STRING *signature = NULL;
int rc = SSH_ERROR;
enter_function();
@@ -296,7 +270,6 @@ static int dh_handshake(ssh_session session) {
goto error;
}
session->dh_server_signature = signature;
signature=NULL; /* ownership changed */
if (dh_build_k(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
rc = SSH_ERROR;
@@ -401,6 +374,10 @@ error:
string_burn(f);
string_free(f);
}
if(pubkey != NULL){
string_burn(pubkey);
string_free(pubkey);
}
if(signature != NULL){
string_burn(signature);
string_free(signature);
@@ -422,8 +399,8 @@ error:
*
* @return 0 on success, < 0 on error.
*/
int ssh_service_request(ssh_session session, const char *service) {
ssh_string service_s = NULL;
int ssh_service_request(SSH_SESSION *session, const char *service) {
STRING *service_s = NULL;
enter_function();
@@ -478,55 +455,53 @@ int ssh_service_request(ssh_session session, const char *service) {
* \see ssh_new()
* \see ssh_disconnect()
*/
int ssh_connect(ssh_session session) {
int ssh_connect(SSH_SESSION *session) {
SSH_OPTIONS *options = session->options;
int ssh1 = 0;
int ssh2 = 0;
socket_t fd = SSH_INVALID_SOCKET;
int ret;
int fd = -1;
if (session == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid session pointer");
return SSH_ERROR;
}
if (session->options == NULL) {
ssh_set_error(session, SSH_FATAL, "No options set");
return SSH_ERROR;
}
options = session->options;
enter_function();
session->alive = 0;
session->client = 1;
if (ssh_init() < 0) {
if (ssh_crypto_init() < 0) {
leave_function();
return SSH_ERROR;
}
if (session->fd == SSH_INVALID_SOCKET && session->host == NULL &&
session->ProxyCommand == NULL) {
if (ssh_socket_init() < 0) {
leave_function();
return SSH_ERROR;
}
if (options->fd == -1 && options->host == NULL) {
ssh_set_error(session, SSH_FATAL, "Hostname required");
leave_function();
return SSH_ERROR;
}
ret = ssh_options_apply(session);
if (ret < 0) {
ssh_set_error(session, SSH_FATAL, "Couldn't apply options");
leave_function();
return SSH_ERROR;
}
if (session->fd != SSH_INVALID_SOCKET) {
fd = session->fd;
#ifndef _WIN32
} else if (session->ProxyCommand != NULL) {
fd=ssh_socket_connect_proxycommand(session, session->ProxyCommand);
#endif
if (options->fd != -1) {
fd = options->fd;
} else {
fd = ssh_connect_host(session, session->host, session->bindaddr,
session->port, session->timeout, session->timeout_usec);
fd = ssh_connect_host(session, options->host, options->bindaddr,
options->port, options->timeout, options->timeout_usec);
}
if (fd == SSH_INVALID_SOCKET) {
if (fd < 0) {
leave_function();
return SSH_ERROR;
}
set_status(session, 0.2);
set_status(options, 0.2);
ssh_socket_set_fd(session->socket, fd);
@@ -538,7 +513,7 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
set_status(session, 0.4);
set_status(options, 0.4);
ssh_log(session, SSH_LOG_RARE,
"SSH server banner: %s", session->serverbanner);
@@ -552,9 +527,9 @@ int ssh_connect(ssh_session session) {
}
/* Here we decide which version of the protocol to use. */
if (ssh2 && session->ssh2) {
if (ssh2 && options->ssh2allowed) {
session->version = 2;
} else if(ssh1 && session->ssh1) {
} else if(ssh1 && options->ssh1allowed) {
session->version = 1;
} else {
ssh_set_error(session, SSH_FATAL,
@@ -573,7 +548,7 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
set_status(session, 0.5);
set_status(options, 0.5);
switch (session->version) {
case 2:
@@ -583,7 +558,7 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
set_status(session,0.6);
set_status(options,0.6);
ssh_list_kex(session, &session->server_kex);
if (set_kex(session) < 0) {
@@ -598,7 +573,7 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
set_status(session,0.8);
set_status(options,0.8);
if (dh_handshake(session) < 0) {
ssh_socket_close(session->socket);
@@ -606,7 +581,7 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
set_status(session,1.0);
set_status(options,1.0);
session->connected = 1;
break;
@@ -617,7 +592,7 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
set_status(session,0.6);
set_status(options,0.6);
session->connected = 1;
break;
@@ -637,7 +612,7 @@ int ssh_connect(ssh_session session) {
*
* @return A newly allocated string with the banner, NULL on error.
*/
char *ssh_get_issue_banner(ssh_session session) {
char *ssh_get_issue_banner(SSH_SESSION *session) {
if (session == NULL || session->banner == NULL) {
return NULL;
}
@@ -645,39 +620,21 @@ char *ssh_get_issue_banner(ssh_session session) {
return string_to_char(session->banner);
}
/**
* @brief Get the version of the OpenSSH server, if it is not an OpenSSH server
* then 0 will be returned.
*
* You can use the SSH_VERSION_INT macro to compare version numbers.
*
* @param session The SSH session to use.
*
* @return The version number if available, 0 otherwise.
*/
int ssh_get_openssh_version(ssh_session session) {
if (session == NULL) {
return 0;
}
return session->openssh;
}
/**
* @brief Disconnect from a session (client or server).
* The session can then be reused to open a new session.
*
* @param session The SSH session to disconnect.
*/
void ssh_disconnect(ssh_session session) {
ssh_string str = NULL;
if (session == NULL) {
return;
}
void ssh_disconnect(SSH_SESSION *session) {
STRING *str = NULL;
enter_function();
if (session == NULL) {
leave_function();
return;
}
if (ssh_socket_is_open(session->socket)) {
if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
goto error;
@@ -705,12 +662,13 @@ void ssh_disconnect(ssh_session session) {
error:
leave_function();
ssh_cleanup(session);
}
const char *ssh_copyright(void) {
return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2008 Aris Adamantiadis "
"(aris@0xbadc0de.be) Distributed under the LGPL, please refer to COPYING"
"file for information about your rights";
"file for informations about your rights";
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -1,327 +0,0 @@
/*
* config.c - parse the ssh config file
*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
*
* 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 <ctype.h>
#include <stdio.h>
#include <string.h>
#include "libssh/priv.h"
#include "libssh/session.h"
enum ssh_config_opcode_e {
SOC_UNSUPPORTED = -1,
SOC_HOST,
SOC_HOSTNAME,
SOC_PORT,
SOC_USERNAME,
SOC_IDENTITY,
SOC_CIPHERS,
SOC_COMPRESSION,
SOC_TIMEOUT,
SOC_PROTOCOL,
SOC_PROXYCOMMAND
};
struct ssh_config_keyword_table_s {
const char *name;
enum ssh_config_opcode_e opcode;
};
static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "host", SOC_HOST },
{ "hostname", SOC_HOSTNAME },
{ "port", SOC_PORT },
{ "user", SOC_USERNAME },
{ "identityfile", SOC_IDENTITY },
{ "ciphers", SOC_CIPHERS },
{ "compression", SOC_COMPRESSION },
{ "connecttimeout", SOC_TIMEOUT },
{ "protocol", SOC_PROTOCOL },
{ "proxycommand", SOC_PROXYCOMMAND },
{ NULL, SOC_UNSUPPORTED }
};
static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) {
int i;
for (i = 0; ssh_config_keyword_table[i].name != NULL; i++) {
if (strcasecmp(keyword, ssh_config_keyword_table[i].name) == 0) {
return ssh_config_keyword_table[i].opcode;
}
}
return SOC_UNSUPPORTED;
}
static char *ssh_config_get_token(char **str) {
register char *c;
char *r;
/* Ignore leading spaces */
for (c = *str; *c; c++) {
if (! isblank(*c)) {
break;
}
}
if (*c == '\"') {
for (r = ++c; *c; c++) {
if (*c == '\"') {
*c = '\0';
goto out;
}
}
}
for (r = c; *c; c++) {
if (isblank(*c)) {
*c = '\0';
goto out;
}
}
out:
*str = c + 1;
return r;
}
static int ssh_config_get_int(char **str, int notfound) {
char *p, *endp;
int i;
p = ssh_config_get_token(str);
if (p && *p) {
i = strtol(p, &endp, 10);
if (p == endp) {
return notfound;
}
return i;
}
return notfound;
}
static const char *ssh_config_get_str(char **str, const char *def) {
char *p;
p = ssh_config_get_token(str);
if (p && *p) {
return p;
}
return def;
}
static int ssh_config_get_yesno(char **str, int notfound) {
const char *p;
p = ssh_config_get_str(str, NULL);
if (p == NULL) {
return notfound;
}
if (strncasecmp(p, "yes", 3) == 0) {
return 1;
} else if (strncasecmp(p, "no", 2) == 0) {
return 0;
}
return notfound;
}
static int ssh_config_parse_line(ssh_session session, const char *line,
unsigned int count, int *parsing) {
enum ssh_config_opcode_e opcode;
const char *p;
char *s, *x;
char *keyword;
size_t len;
int i;
x = s = strdup(line);
if (s == NULL) {
ssh_set_error_oom(session);
return -1;
}
/* Remove trailing spaces */
for (len = strlen(s) - 1; len > 0; len--) {
if (! isspace(s[len])) {
break;
}
s[len] = '\0';
}
keyword = ssh_config_get_token(&s);
if (keyword == NULL || *keyword == '#' ||
*keyword == '\0' || *keyword == '\n') {
SAFE_FREE(x);
return 0;
}
opcode = ssh_config_get_opcode(keyword);
switch (opcode) {
case SOC_HOST:
*parsing = 0;
for (p = ssh_config_get_str(&s, NULL); p && *p;
p = ssh_config_get_str(&s, NULL)) {
if (match_hostname(session->host, p, strlen(p))) {
*parsing = 1;
}
}
break;
case SOC_HOSTNAME:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_HOST, p);
}
break;
case SOC_PORT:
if (session->port == 22) {
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PORT_STR, p);
}
}
break;
case SOC_USERNAME:
if (session->username == NULL) {
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_USER, p);
}
}
break;
case SOC_IDENTITY:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p);
}
break;
case SOC_CIPHERS:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p);
ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p);
}
break;
case SOC_COMPRESSION:
i = ssh_config_get_yesno(&s, -1);
if (i >= 0 && *parsing) {
if (i) {
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib,none");
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib,none");
} else {
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "none");
ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "none");
}
}
break;
case SOC_PROTOCOL:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
char *a, *b;
b = strdup(p);
if (b == NULL) {
SAFE_FREE(x);
ssh_set_error_oom(session);
return -1;
}
i = 0;
ssh_options_set(session, SSH_OPTIONS_SSH1, &i);
ssh_options_set(session, SSH_OPTIONS_SSH2, &i);
for (a = strtok(b, ","); a; a = strtok(NULL, ",")) {
switch (atoi(a)) {
case 1:
i = 1;
ssh_options_set(session, SSH_OPTIONS_SSH1, &i);
break;
case 2:
i = 1;
ssh_options_set(session, SSH_OPTIONS_SSH2, &i);
break;
default:
break;
}
}
SAFE_FREE(b);
}
break;
case SOC_TIMEOUT:
i = ssh_config_get_int(&s, -1);
if (i >= 0 && *parsing) {
ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &i);
}
break;
case SOC_PROXYCOMMAND:
p = ssh_config_get_str(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
}
break;
case SOC_UNSUPPORTED:
ssh_log(session, SSH_LOG_RARE, "Unsupported option: %s, line: %d\n",
keyword, count);
break;
default:
ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d\n",
opcode);
SAFE_FREE(x);
return -1;
break;
}
SAFE_FREE(x);
return 0;
}
/* ssh_config_parse_file */
int ssh_config_parse_file(ssh_session session, const char *filename) {
char line[1024] = {0};
unsigned int count = 0;
FILE *f;
int parsing;
if ((f = fopen(filename, "r")) == NULL) {
return 0;
}
if (session->log_verbosity) {
fprintf(stderr, "Reading configuration data from %s\n", filename);
}
parsing = 1;
while (fgets(line, sizeof(line), f)) {
count++;
if (ssh_config_parse_line(session, line, count, &parsing) < 0) {
fclose(f);
return -1;
}
}
fclose(f);
return 0;
}

View File

@@ -3,7 +3,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
@@ -26,33 +26,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef _WIN32
/*
* Only use Windows API functions available on Windows 2000 SP4 or later.
* The available constants are in <sdkddkver.h>.
* http://msdn.microsoft.com/en-us/library/aa383745.aspx
* http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx
*/
#undef _WIN32_WINNT
#ifdef HAVE_WSPIAPI_H
#define _WIN32_WINNT 0x0500 /* _WIN32_WINNT_WIN2K */
#undef NTDDI_VERSION
#define NTDDI_VERSION 0x05000400 /* NTDDI_WIN2KSP4 */
#else
#define _WIN32_WINNT 0x0501 /* _WIN32_WINNT_WINXP */
#undef NTDDI_VERSION
#define NTDDI_VERSION 0x05010000 /* NTDDI_WINXP */
#endif
/* getaddrinfo, freeaddrinfo, getnameinfo */
#define _WIN32_WINNT 0x0501
#include <winsock2.h>
#include <ws2tcpip.h>
/* <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
* available on some platforms like MinGW. */
#ifdef HAVE_WSPIAPI_H
#include <wspiapi.h>
#endif
#include "wspiapi.h" /* Workaround for w2k systems */
#else /* _WIN32 */
@@ -64,9 +47,6 @@
#endif /* _WIN32 */
#include "libssh/priv.h"
#include "libssh/socket.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#ifndef HAVE_SELECT
#error "Your system must have select()"
@@ -76,14 +56,6 @@
#error "Your system must have getaddrinfo()"
#endif
#ifdef HAVE_REGCOMP
/* don't declare gnu extended regexp's */
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE
#endif
#include <regex.h>
#endif /* HAVE_REGCOMP */
#ifdef _WIN32
static void sock_set_nonblocking(socket_t sock) {
u_long nonblocking = 1;
@@ -113,64 +85,9 @@ static void sock_set_nonblocking(socket_t sock) {
static void sock_set_blocking(socket_t sock) {
fcntl(sock, F_SETFL, 0);
}
#endif /* _WIN32 */
#ifdef HAVE_REGCOMP
static regex_t *ip_regex = NULL;
/** @internal
* @brief initializes and compile the regexp to be used for IP matching
* @returns -1 on error (and error message is set)
* @returns 0 on success
*/
int ssh_regex_init(){
if(ip_regex==NULL){
int err;
regex_t *regex=malloc(sizeof (regex_t));
ZERO_STRUCTP(regex);
err=regcomp(regex,"^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$",REG_EXTENDED | REG_NOSUB);
if(err != 0){
char buffer[128];
regerror(err,regex,buffer,sizeof(buffer));
fprintf(stderr,"Error while compiling regular expression : %s\n",buffer);
SAFE_FREE(regex);
return -1;
}
ip_regex=regex;
}
return 0;
}
/** @internal
* @brief clean up the IP regexp
*/
void ssh_regex_finalize(){
if(ip_regex){
regfree(ip_regex);
SAFE_FREE(ip_regex);
}
}
#else /* HAVE_REGCOMP */
int ssh_regex_init(){
return 0;
}
void ssh_regex_finalize(){
}
#endif
static int ssh_connect_socket_close(socket_t s){
#ifdef _WIN32
return closesocket(s);
#else
return close(s);
#endif
}
static int getai(ssh_session session, const char *host, int port, struct addrinfo **ai) {
static int getai(const char *host, int port, struct addrinfo **ai) {
const char *service = NULL;
struct addrinfo hints;
char s_port[10];
@@ -186,21 +103,12 @@ static int getai(ssh_session session, const char *host, int port, struct addrinf
} else {
snprintf(s_port, sizeof(s_port), "%hu", port);
service = s_port;
#ifdef AI_NUMERICSERV
hints.ai_flags=AI_NUMERICSERV;
#endif
}
#ifdef HAVE_REGCOMP
if(regexec(ip_regex,host,0,NULL,0) == 0){
/* this is an IP address */
ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host);
hints.ai_flags |= AI_NUMERICHOST;
}
#endif
return getaddrinfo(host, service, &hints, ai);
}
static int ssh_connect_ai_timeout(ssh_session session, const char *host,
static int ssh_connect_ai_timeout(SSH_SESSION *session, const char *host,
int port, struct addrinfo *ai, long timeout, long usec, socket_t s) {
struct timeval to;
fd_set set;
@@ -214,9 +122,6 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
sock_set_nonblocking(s);
ssh_log(session, SSH_LOG_RARE, "Trying to connect to host: %s:%d with "
"timeout %ld.%ld", host, port, timeout, usec);
/* The return value is checked later */
connect(s, ai->ai_addr, ai->ai_addrlen);
freeaddrinfo(ai);
@@ -229,7 +134,7 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
/* timeout */
ssh_set_error(session, SSH_FATAL,
"Timeout while connecting to %s:%d", host, port);
ssh_connect_socket_close(s);
close(s);
leave_function();
return -1;
}
@@ -237,7 +142,7 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
if (rc < 0) {
ssh_set_error(session, SSH_FATAL,
"Select error: %s", strerror(errno));
ssh_connect_socket_close(s);
close(s);
leave_function();
return -1;
}
@@ -248,7 +153,7 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Connect to %s:%d failed: %s", host, port, strerror(rc));
ssh_connect_socket_close(s);
close(s);
leave_function();
return -1;
}
@@ -269,7 +174,7 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
*
* @returns A file descriptor, < 0 on error.
*/
socket_t ssh_connect_host(ssh_session session, const char *host,
socket_t ssh_connect_host(SSH_SESSION *session, const char *host,
const char *bind_addr, int port, long timeout, long usec) {
socket_t s = -1;
int rc;
@@ -278,7 +183,7 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
enter_function();
rc = getai(session,host, port, &ai);
rc = getai(host, port, &ai);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Failed to resolve hostname %s (%s)", host, gai_strerror(rc));
@@ -301,7 +206,7 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
ssh_log(session, SSH_LOG_PACKET, "Resolving %s\n", bind_addr);
rc = getai(session,bind_addr, 0, &bind_ai);
rc = getai(host, 0, &bind_ai);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Failed to resolve bind address %s (%s)",
@@ -324,7 +229,7 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
/* Cannot bind to any local addresses */
if (bind_itr == NULL) {
ssh_connect_socket_close(s);
close(s);
s = -1;
continue;
}
@@ -339,8 +244,9 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
if (connect(s, itr->ai_addr, itr->ai_addrlen) < 0) {
ssh_set_error(session, SSH_FATAL, "Connect failed: %s", strerror(errno));
ssh_connect_socket_close(s);
close(s);
s = -1;
leave_function();
continue;
} else {
/* We are connected */
@@ -386,11 +292,10 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
*
* @see select(2)
*/
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
int ssh_select(CHANNEL **channels, CHANNEL **outchannels, socket_t maxfd,
fd_set *readfds, struct timeval *timeout) {
struct timeval zerotime;
fd_set localset, localset2;
socket_t f;
int rep;
int set;
int i;
@@ -431,8 +336,8 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
/* Look into the localset for active fd */
set = 0;
for (f = 0; (f < maxfd) && !set; f++) {
if (FD_ISSET(f, &localset)) {
for (i = 0; (i < maxfd) && !set; i++) {
if (FD_ISSET(i, &localset)) {
set = 1;
}
}
@@ -494,9 +399,9 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
outchannels[j] = NULL;
FD_ZERO(&localset2);
for (f = 0; f < maxfd; f++) {
if (FD_ISSET(f, readfds) && FD_ISSET(i, &localset)) {
FD_SET(f, &localset2);
for (i = 0; i < maxfd; i++) {
if (FD_ISSET(i, readfds) && FD_ISSET(i, &localset)) {
FD_SET(i, &localset2);
}
}

View File

@@ -23,7 +23,7 @@
#include "libssh/priv.h"
static uint32_t crc_table[] = {
static u32 crc_table[] = {
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
@@ -78,8 +78,8 @@ static uint32_t crc_table[] = {
0x2d02ef8dUL
};
uint32_t ssh_crc32(const char *buf, uint32_t len) {
uint32_t ret = 0;
u32 ssh_crc32(const char *buf, u32 len) {
u32 ret = 0;
while(len > 0) {
ret = crc_table[(ret ^ *buf) & 0xff] ^ (ret >> 8);
--len;

View File

@@ -21,7 +21,7 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -37,11 +37,10 @@
#endif
#include "libssh/priv.h"
#include "libssh/session.h"
#include "libssh/wrapper.h"
#include "libssh/crypto.h"
uint32_t packet_decrypt_len(ssh_session session, char *crypted){
uint32_t decrypted;
u32 packet_decrypt_len(SSH_SESSION *session, char *crypted){
u32 decrypted;
if (session->current_crypto) {
if (packet_decrypt(session, crypted,
@@ -58,13 +57,10 @@ uint32_t packet_decrypt_len(ssh_session session, char *crypted){
return ntohl(decrypted);
}
int packet_decrypt(ssh_session session, void *data,uint32_t len) {
int packet_decrypt(SSH_SESSION *session, void *data,u32 len) {
struct crypto_struct *crypto = session->current_crypto->in_cipher;
char *out = NULL;
if(len % session->current_crypto->in_cipher->blocksize != 0){
ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
return SSH_ERROR;
}
out = malloc(len);
if (out == NULL) {
return -1;
@@ -94,20 +90,17 @@ int packet_decrypt(ssh_session session, void *data,uint32_t len) {
return 0;
}
unsigned char *packet_encrypt(ssh_session session, void *data, uint32_t len) {
unsigned char *packet_encrypt(SSH_SESSION *session, void *data, u32 len) {
struct crypto_struct *crypto = NULL;
HMACCTX ctx = NULL;
char *out = NULL;
unsigned int finallen;
uint32_t seq;
u32 seq;
if (!session->current_crypto) {
return NULL; /* nothing to do here */
}
if(len % session->current_crypto->in_cipher->blocksize != 0){
ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
return NULL;
}
out = malloc(len);
if (out == NULL) {
return NULL;
@@ -139,7 +132,7 @@ unsigned char *packet_encrypt(ssh_session session, void *data, uint32_t len) {
SAFE_FREE(out);
return NULL;
}
hmac_update(ctx,(unsigned char *)&seq,sizeof(uint32_t));
hmac_update(ctx,(unsigned char *)&seq,sizeof(u32));
hmac_update(ctx,data,len);
hmac_final(ctx,session->current_crypto->hmacbuf,&finallen);
#ifdef DEBUG_CRYPTO
@@ -181,12 +174,12 @@ unsigned char *packet_encrypt(ssh_session session, void *data, uint32_t len) {
* @return 0 if hmac and mac are equal, < 0 if not or an error
* occured.
*/
int packet_hmac_verify(ssh_session session, ssh_buffer buffer,
int packet_hmac_verify(SSH_SESSION *session, BUFFER *buffer,
unsigned char *mac) {
unsigned char hmacbuf[EVP_MAX_MD_SIZE] = {0};
HMACCTX ctx;
unsigned int len;
uint32_t seq;
u32 seq;
ctx = hmac_init(session->current_crypto->decryptMAC, 20, HMAC_SHA1);
if (ctx == NULL) {
@@ -195,14 +188,14 @@ int packet_hmac_verify(ssh_session session, ssh_buffer buffer,
seq = htonl(session->recv_seq);
hmac_update(ctx, (unsigned char *) &seq, sizeof(uint32_t));
hmac_update(ctx, (unsigned char *) &seq, sizeof(u32));
hmac_update(ctx, buffer_get(buffer), buffer_get_len(buffer));
hmac_final(ctx, hmacbuf, &len);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("received mac",mac,len);
ssh_print_hexa("Computed mac",hmacbuf,len);
ssh_print_hexa("seq",(unsigned char *)&seq,sizeof(uint32_t));
ssh_print_hexa("seq",(unsigned char *)&seq,sizeof(u32));
#endif
if (memcmp(mac, hmacbuf, len) == 0) {
return 0;

View File

@@ -40,7 +40,6 @@
* if everything went correctly, k and k' are equal
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -51,13 +50,7 @@
#include "libssh/priv.h"
#include "libssh/crypto.h"
#include "libssh/buffer.h"
#include "libssh/session.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
/* todo: remove it */
#include "libssh/string.h"
#ifdef HAVE_LIBCRYPTO
#include <openssl/rand.h>
#include <openssl/evp.h>
@@ -156,7 +149,6 @@ void ssh_crypto_finalize(void) {
g = NULL;
bignum_free(p);
p = NULL;
ssh_crypto_initialized=0;
}
}
@@ -224,7 +216,7 @@ void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
printf("%s: %s\n", descr, hexa);
}
int dh_generate_x(ssh_session session) {
int dh_generate_x(SSH_SESSION *session) {
session->next_crypto->x = bignum_new();
if (session->next_crypto->x == NULL) {
return -1;
@@ -245,7 +237,7 @@ int dh_generate_x(ssh_session session) {
}
/* used by server */
int dh_generate_y(ssh_session session) {
int dh_generate_y(SSH_SESSION *session) {
session->next_crypto->y = bignum_new();
if (session->next_crypto->y == NULL) {
return -1;
@@ -266,7 +258,7 @@ int dh_generate_y(ssh_session session) {
}
/* used by server */
int dh_generate_e(ssh_session session) {
int dh_generate_e(SSH_SESSION *session) {
#ifdef HAVE_LIBCRYPTO
bignum_CTX ctx = bignum_ctx_new();
if (ctx == NULL) {
@@ -299,7 +291,7 @@ int dh_generate_e(ssh_session session) {
return 0;
}
int dh_generate_f(ssh_session session) {
int dh_generate_f(SSH_SESSION *session) {
#ifdef HAVE_LIBCRYPTO
bignum_CTX ctx = bignum_ctx_new();
if (ctx == NULL) {
@@ -332,8 +324,8 @@ int dh_generate_f(ssh_session session) {
return 0;
}
ssh_string make_bignum_string(bignum num) {
ssh_string ptr = NULL;
STRING *make_bignum_string(bignum num) {
STRING *ptr = NULL;
int pad = 0;
unsigned int len = bignum_num_bytes(num);
unsigned int bits = bignum_num_bits(num);
@@ -347,7 +339,7 @@ ssh_string make_bignum_string(bignum num) {
#ifdef DEBUG_CRYPTO
fprintf(stderr, "%d bits, %d bytes, %d padding\n", bits, len, pad);
#endif /* DEBUG_CRYPTO */
/* TODO: fix that crap !! */
ptr = malloc(4 + len + pad);
if (ptr == NULL) {
return NULL;
@@ -366,7 +358,7 @@ ssh_string make_bignum_string(bignum num) {
return ptr;
}
bignum make_string_bn(ssh_string string){
bignum make_string_bn(STRING *string){
bignum bn = NULL;
unsigned int len = string_len(string);
@@ -384,20 +376,20 @@ bignum make_string_bn(ssh_string string){
return bn;
}
ssh_string dh_get_e(ssh_session session) {
STRING *dh_get_e(SSH_SESSION *session) {
return make_bignum_string(session->next_crypto->e);
}
/* used by server */
ssh_string dh_get_f(ssh_session session) {
STRING *dh_get_f(SSH_SESSION *session) {
return make_bignum_string(session->next_crypto->f);
}
void dh_import_pubkey(ssh_session session, ssh_string pubkey_string) {
void dh_import_pubkey(SSH_SESSION *session, STRING *pubkey_string) {
session->next_crypto->server_pubkey = pubkey_string;
}
int dh_import_f(ssh_session session, ssh_string f_string) {
int dh_import_f(SSH_SESSION *session, STRING *f_string) {
session->next_crypto->f = make_string_bn(f_string);
if (session->next_crypto->f == NULL) {
return -1;
@@ -411,7 +403,7 @@ int dh_import_f(ssh_session session, ssh_string f_string) {
}
/* used by the server implementation */
int dh_import_e(ssh_session session, ssh_string e_string) {
int dh_import_e(SSH_SESSION *session, STRING *e_string) {
session->next_crypto->e = make_string_bn(e_string);
if (session->next_crypto->e == NULL) {
return -1;
@@ -424,7 +416,7 @@ int dh_import_e(ssh_session session, ssh_string e_string) {
return 0;
}
int dh_build_k(ssh_session session) {
int dh_build_k(SSH_SESSION *session) {
#ifdef HAVE_LIBCRYPTO
bignum_CTX ctx = bignum_ctx_new();
if (ctx == NULL) {
@@ -473,7 +465,7 @@ int dh_build_k(ssh_session session) {
}
/*
static void sha_add(ssh_string str,SHACTX ctx){
static void sha_add(STRING *str,SHACTX ctx){
sha1_update(ctx,str,string_len(str)+4);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("partial hashed sessionid",str,string_len(str)+4);
@@ -481,14 +473,14 @@ static void sha_add(ssh_string str,SHACTX ctx){
}
*/
int make_sessionid(ssh_session session) {
int make_sessionid(SSH_SESSION *session) {
SHACTX ctx;
ssh_string num = NULL;
ssh_string str = NULL;
ssh_buffer server_hash = NULL;
ssh_buffer client_hash = NULL;
ssh_buffer buf = NULL;
uint32_t len;
STRING *num = NULL;
STRING *str = NULL;
BUFFER *server_hash = NULL;
BUFFER *client_hash = NULL;
BUFFER *buf = NULL;
u32 len;
int rc = SSH_ERROR;
enter_function();
@@ -627,27 +619,27 @@ error:
return rc;
}
int hashbufout_add_cookie(ssh_session session) {
int hashbufout_add_cookie(SSH_SESSION *session) {
session->out_hashbuf = buffer_new();
if (session->out_hashbuf == NULL) {
return -1;
}
if (buffer_add_u8(session->out_hashbuf, 20) < 0) {
buffer_reinit(session->out_hashbuf);
buffer_free(session->out_hashbuf);
return -1;
}
if (session->server) {
if (buffer_add_data(session->out_hashbuf,
session->server_kex.cookie, 16) < 0) {
buffer_reinit(session->out_hashbuf);
buffer_free(session->out_hashbuf);
return -1;
}
} else {
if (buffer_add_data(session->out_hashbuf,
session->client_kex.cookie, 16) < 0) {
buffer_reinit(session->out_hashbuf);
buffer_free(session->out_hashbuf);
return -1;
}
}
@@ -655,25 +647,25 @@ int hashbufout_add_cookie(ssh_session session) {
return 0;
}
int hashbufin_add_cookie(ssh_session session, unsigned char *cookie) {
int hashbufin_add_cookie(SSH_SESSION *session, unsigned char *cookie) {
session->in_hashbuf = buffer_new();
if (session->in_hashbuf == NULL) {
return -1;
}
if (buffer_add_u8(session->in_hashbuf, 20) < 0) {
buffer_reinit(session->in_hashbuf);
buffer_free(session->in_hashbuf);
return -1;
}
if (buffer_add_data(session->in_hashbuf,cookie, 16) < 0) {
buffer_reinit(session->in_hashbuf);
buffer_free(session->in_hashbuf);
return -1;
}
return 0;
}
static int generate_one_key(ssh_string k,
static int generate_one_key(STRING *k,
unsigned char session_id[SHA_DIGEST_LEN],
unsigned char output[SHA_DIGEST_LEN],
char letter) {
@@ -693,8 +685,8 @@ static int generate_one_key(ssh_string k,
return 0;
}
int generate_session_keys(ssh_session session) {
ssh_string k_string = NULL;
int generate_session_keys(SSH_SESSION *session) {
STRING *k_string = NULL;
SHACTX ctx = NULL;
int rc = -1;
@@ -823,19 +815,16 @@ error:
* @see ssh_get_hexa()
* @see ssh_print_hexa()
*/
int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) {
ssh_string pubkey;
int ssh_get_pubkey_hash(SSH_SESSION *session, unsigned char **hash) {
STRING *pubkey;
MD5CTX ctx;
unsigned char *h;
if (session == NULL || hash == NULL) {
return -1;
}
*hash = NULL;
if (session->current_crypto == NULL ||
session->current_crypto->server_pubkey == NULL){
ssh_set_error(session,SSH_FATAL,"No current cryptographic context");
}
h = malloc(sizeof(unsigned char *) * MD5_DIGEST_LEN);
if (h == NULL) {
@@ -858,21 +847,7 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) {
return MD5_DIGEST_LEN;
}
/**
* @brief Deallocate the hash obtained by ssh_get_pubkey_hash.
* This is required under Microsoft platform as this library might use a
* different C library than your software, hence a different heap.
*
* @param hash The buffer to deallocate.
*
* @see ssh_get_pubkey_hash()
*/
void ssh_clean_pubkey_hash(unsigned char **hash) {
SAFE_FREE(*hash);
*hash = NULL;
}
ssh_string ssh_get_pubkey(ssh_session session){
STRING *ssh_get_pubkey(SSH_SESSION *session){
return string_copy(session->current_crypto->server_pubkey);
}
@@ -900,8 +875,8 @@ static int match(const char *group, const char *object){
return 0;
}
int sig_verify(ssh_session session, ssh_public_key pubkey,
SIGNATURE *signature, unsigned char *digest, int size) {
static int sig_verify(SSH_SESSION *session, PUBLIC_KEY *pubkey,
SIGNATURE *signature, unsigned char *digest) {
#ifdef HAVE_LIBGCRYPT
gcry_error_t valid = 0;
gcry_sexp_t gcryhash;
@@ -910,7 +885,7 @@ int sig_verify(ssh_session session, ssh_public_key pubkey,
#endif
unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
sha1(digest, size, hash + 1);
sha1(digest,SHA_DIGEST_LEN, hash + 1);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Hash to be verified with dsa", hash + 1, SHA_DIGEST_LEN);
@@ -995,24 +970,30 @@ int sig_verify(ssh_session session, ssh_public_key pubkey,
return -1;
}
int signature_verify(ssh_session session, ssh_string signature) {
ssh_public_key pubkey = NULL;
int signature_verify(SSH_SESSION *session, STRING *signature) {
PUBLIC_KEY *pubkey = NULL;
SIGNATURE *sign = NULL;
int err;
enter_function();
if (session->options->dont_verify_hostkey) {
ssh_log(session, SSH_LOG_FUNCTIONS, "Host key wasn't verified");
leave_function();
return 0;
}
pubkey = publickey_from_string(session,session->next_crypto->server_pubkey);
if(pubkey == NULL) {
leave_function();
return -1;
}
if (session->wanted_methods[SSH_HOSTKEYS]) {
if(!match(session->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)) {
if (session->options->wanted_methods[SSH_HOSTKEYS]) {
if(!match(session->options->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)) {
ssh_set_error(session, SSH_FATAL,
"Public key from server (%s) doesn't match user preference (%s)",
pubkey->type_c, session->wanted_methods[SSH_HOSTKEYS]);
pubkey->type_c, session->options->wanted_methods[SSH_HOSTKEYS]);
publickey_free(pubkey);
leave_function();
return -1;
@@ -1030,8 +1011,7 @@ int signature_verify(ssh_session session, ssh_string signature) {
ssh_log(session, SSH_LOG_FUNCTIONS,
"Going to verify a %s type signature", pubkey->type_c);
err = sig_verify(session,pubkey,sign,
session->next_crypto->session_id,SHA_DIGEST_LEN);
err = sig_verify(session,pubkey,sign,session->next_crypto->session_id);
signature_free(sign);
session->next_crypto->server_pubkey_type = pubkey->type_c;
publickey_free(pubkey);

View File

@@ -41,7 +41,7 @@
*
* @brief Registers an error with a description.
*
* @param error The place to store the error.
* @param error The class of error.
*
* @param code The class of error.
*
@@ -58,35 +58,6 @@ void ssh_set_error(void *error, int code, const char *descr, ...) {
err->error_code = code;
}
/**
* @internal
*
* @brief Registers an out of memory error
*
* @param error The place to store the error.
*
*/
void ssh_set_error_oom(void *error) {
struct error_struct *err = error;
strcpy(err->error_buffer, "Out of memory");
err->error_code = SSH_FATAL;
}
/**
* @internal
*
* @brief Registers an invalid argument error
*
* @param error The place to store the error.
*
* @param function The function the error happened in.
*
*/
void ssh_set_error_invalid(void *error, const char *function) {
ssh_set_error(error, SSH_FATAL, "Invalid argument in %s", function);
}
/**
* @brief Retrieve the error text message from the last error.
*
@@ -105,13 +76,13 @@ const char *ssh_get_error(void *error) {
*
* @param error The SSH session pointer.
*
* \return SSH_NO_ERROR No error occurred\n
* \return SSH_NO_ERROR No error occured\n
* SSH_REQUEST_DENIED The last request was denied but situation is
* recoverable\n
* SSH_FATAL A fatal error occurred. This could be an unexpected
* SSH_FATAL A fatal error occured. This could be an unexpected
* disconnection\n
*
* Other error codes are internal but can be considered same than
* \nOther error codes are internal but can be considered same than
* SSH_FATAL.
*/
int ssh_get_error_code(void *error) {

View File

@@ -24,8 +24,6 @@
#include "config.h"
#include "libssh/priv.h"
#include "libssh/buffer.h"
#include "libssh/session.h"
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
@@ -35,7 +33,7 @@
#define BLOCKSIZE 4092
static z_stream *initcompress(ssh_session session, int level) {
static z_stream *initcompress(SSH_SESSION *session, int level) {
z_stream *stream = NULL;
int status;
@@ -56,11 +54,11 @@ static z_stream *initcompress(ssh_session session, int level) {
return stream;
}
static ssh_buffer gzip_compress(ssh_session session,ssh_buffer source,int level){
static BUFFER *gzip_compress(SSH_SESSION *session,BUFFER *source,int level){
z_stream *zout = session->current_crypto->compress_out_ctx;
void *in_ptr = buffer_get(source);
unsigned long in_size = buffer_get_len(source);
ssh_buffer dest = NULL;
BUFFER *dest = NULL;
static unsigned char out_buf[BLOCKSIZE] = {0};
unsigned long len;
int status;
@@ -100,8 +98,8 @@ static ssh_buffer gzip_compress(ssh_session session,ssh_buffer source,int level)
return dest;
}
int compress_buffer(ssh_session session, ssh_buffer buf) {
ssh_buffer dest = NULL;
int compress_buffer(SSH_SESSION *session, BUFFER *buf) {
BUFFER *dest = NULL;
dest = gzip_compress(session, buf, 9);
if (dest == NULL) {
@@ -124,7 +122,7 @@ int compress_buffer(ssh_session session, ssh_buffer buf) {
/* decompression */
static z_stream *initdecompress(ssh_session session) {
static z_stream *initdecompress(SSH_SESSION *session) {
z_stream *stream = NULL;
int status;
@@ -145,12 +143,12 @@ static z_stream *initdecompress(ssh_session session) {
return stream;
}
static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t maxlen) {
static BUFFER *gzip_decompress(SSH_SESSION *session, BUFFER *source) {
z_stream *zin = session->current_crypto->compress_in_ctx;
void *in_ptr = buffer_get_rest(source);
unsigned long in_size = buffer_get_rest_len(source);
static unsigned char out_buf[BLOCKSIZE] = {0};
ssh_buffer dest = NULL;
BUFFER *dest = NULL;
unsigned long len;
int status;
@@ -185,21 +183,17 @@ static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t
buffer_free(dest);
return NULL;
}
if (buffer_get_len(dest) > maxlen){
/* Size of packet exceded, avoid a denial of service attack */
buffer_free(dest);
return NULL;
}
zin->next_out = out_buf;
} while (zin->avail_out == 0);
return dest;
}
int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen){
ssh_buffer dest = NULL;
int decompress_buffer(SSH_SESSION *session,BUFFER *buf){
BUFFER *dest = NULL;
dest = gzip_decompress(session,buf, maxlen);
dest = gzip_decompress(session,buf);
if (dest == NULL) {
return -1;
}

View File

@@ -3,7 +3,7 @@
*
* This file is part of the SSH Library
*
* Copyright (c) 2003-2009 by Aris Adamantiadis
* Copyright (c) 2003-2006 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
@@ -21,11 +21,7 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include "libssh/priv.h"
#include "libssh/socket.h"
#include "libssh/dh.h"
#ifdef _WIN32
#include <winsock2.h>
#endif
@@ -35,37 +31,15 @@
* @{
*/
/**
* @brief initialize global cryptographic data structures.
*
* This function should only be called once, at the beginning of the program, in
* the main thread. It may be omitted if your program is not multithreaded.
*
* @returns 0
*/
int ssh_init(void) {
if(ssh_crypto_init())
return -1;
if(ssh_socket_init())
return -1;
if(ssh_regex_init())
return -1;
return 0;
}
/**
* @brief Finalize and cleanup all libssh and cryptographic data structures.
*
* This function should only be called once, at the end of the program!
*
* @returns -1 in case of error
@returns 0 otherwise
* @returns 0
*/
int ssh_finalize(void) {
ssh_regex_finalize();
ssh_crypto_finalize();
ssh_socket_cleanup();
#ifdef HAVE_LIBGCRYPT
gcry_control(GCRYCTL_TERM_SECMEM);
#elif defined HAVE_LIBCRYPTO

View File

@@ -21,8 +21,6 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -31,20 +29,14 @@
#include <arpa/inet.h>
#endif
#include "config.h"
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/ssh1.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/wrapper.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/string.h"
#ifdef HAVE_LIBGCRYPT
#define BLOWFISH "blowfish-cbc,"
#define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
#define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
#define DES "3des-cbc"
#elif defined HAVE_LIBCRYPTO
#ifdef HAVE_OPENSSL_BLOWFISH_H
@@ -53,15 +45,10 @@
#define BLOWFISH ""
#endif
#ifdef HAVE_OPENSSL_AES_H
#ifdef BROKEN_AES_CTR
#define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
#else
#define AES "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,"
#endif /* BROKEN_AES_CTR */
#else
#define AES ""
#endif
#define DES "3des-cbc"
#endif
@@ -73,7 +60,7 @@
const char *default_methods[] = {
"diffie-hellman-group1-sha1",
"ssh-rsa,ssh-dss",
"ssh-dss,ssh-rsa",
AES BLOWFISH DES,
AES BLOWFISH DES,
"hmac-sha1",
@@ -87,7 +74,7 @@ const char *default_methods[] = {
const char *supported_methods[] = {
"diffie-hellman-group1-sha1",
"ssh-rsa,ssh-dss",
"ssh-dss,ssh-rsa",
AES BLOWFISH DES,
AES BLOWFISH DES,
"hmac-sha1",
@@ -200,53 +187,53 @@ char **space_tokenize(const char *chain){
return tokens;
}
/* find_matching gets 2 parameters : a list of available objects (available_d), separated by colons,*/
/* and a list of preferred objects (preferred_d) */
/* find_matching gets 2 parameters : a list of available objects (in_d), separated by colons,*/
/* and a list of prefered objects (what_d) */
/* it will return a strduped pointer on the first prefered object found in the available objects list */
char *ssh_find_matching(const char *available_d, const char *preferred_d){
char ** tok_available, **tok_preferred;
int i_avail, i_pref;
char *ssh_find_matching(const char *in_d, const char *what_d){
char ** tok_in, **tok_what;
int i_in, i_what;
char *ret;
if ((available_d == NULL) || (preferred_d == NULL)) {
if ((in_d == NULL) || (what_d == NULL)) {
return NULL; /* don't deal with null args */
}
tok_available = tokenize(available_d);
if (tok_available == NULL) {
tok_in = tokenize(in_d);
if (tok_in == NULL) {
return NULL;
}
tok_preferred = tokenize(preferred_d);
if (tok_preferred == NULL) {
SAFE_FREE(tok_available[0]);
SAFE_FREE(tok_available);
tok_what = tokenize(what_d);
if (tok_what == NULL) {
SAFE_FREE(tok_in[0]);
SAFE_FREE(tok_in);
}
for(i_pref=0; tok_preferred[i_pref] ; ++i_pref){
for(i_avail=0; tok_available[i_avail]; ++i_avail){
if(!strcmp(tok_available[i_avail],tok_preferred[i_pref])){
/* match */
ret=strdup(tok_available[i_avail]);
/* free the tokens */
free(tok_available[0]);
free(tok_preferred[0]);
free(tok_available);
free(tok_preferred);
return ret;
for(i_in=0; tok_in[i_in]; ++i_in){
for(i_what=0; tok_what[i_what] ; ++i_what){
if(!strcmp(tok_in[i_in],tok_what[i_what])){
/* match */
ret=strdup(tok_in[i_in]);
/* free the tokens */
free(tok_in[0]);
free(tok_what[0]);
free(tok_in);
free(tok_what);
return ret;
}
}
}
}
free(tok_available[0]);
free(tok_preferred[0]);
free(tok_available);
free(tok_preferred);
free(tok_in[0]);
free(tok_what[0]);
free(tok_in);
free(tok_what);
return NULL;
}
int ssh_get_kex(ssh_session session, int server_kex) {
ssh_string str = NULL;
int ssh_get_kex(SSH_SESSION *session, int server_kex) {
STRING *str = NULL;
char *strings[10];
int i;
@@ -324,7 +311,7 @@ error:
return -1;
}
void ssh_list_kex(ssh_session session, KEX *kex) {
void ssh_list_kex(struct ssh_session *session, KEX *kex) {
int i = 0;
#ifdef DEBUG_CRYPTO
@@ -341,13 +328,18 @@ void ssh_list_kex(ssh_session session, KEX *kex) {
/* it must be aware of the server kex message */
/* it can fail if option is null, not any user specified kex method matches the server one, if not any default kex matches */
int set_kex(ssh_session session){
int set_kex(SSH_SESSION *session){
KEX *server = &session->server_kex;
KEX *client=&session->client_kex;
SSH_OPTIONS *options=session->options;
int i;
const char *wanted;
enter_function();
ssh_get_random(client->cookie,16,0);
/* the client might ask for a specific cookie to be sent. useful for server debugging */
if(options->wanted_cookie)
memcpy(client->cookie,options->wanted_cookie,16);
else
ssh_get_random(client->cookie,16,0);
client->methods=malloc(10 * sizeof(char **));
if (client->methods == NULL) {
ssh_set_error(session, SSH_FATAL, "No space left");
@@ -356,7 +348,7 @@ int set_kex(ssh_session session){
}
memset(client->methods,0,10*sizeof(char **));
for (i=0;i<10;i++){
if(!(wanted=session->wanted_methods[i]))
if(!(wanted=options->wanted_methods[i]))
wanted=default_methods[i];
client->methods[i]=ssh_find_matching(server->methods[i],wanted);
if(!client->methods[i] && i < SSH_LANG_C_S){
@@ -379,9 +371,9 @@ int set_kex(ssh_session session){
}
/* this function only sends the predefined set of kex methods */
int ssh_send_kex(ssh_session session, int server_kex) {
int ssh_send_kex(SSH_SESSION *session, int server_kex) {
KEX *kex = (server_kex ? &session->server_kex : &session->client_kex);
ssh_string str = NULL;
STRING *str = NULL;
int i;
enter_function();
@@ -429,8 +421,8 @@ int ssh_send_kex(ssh_session session, int server_kex) {
leave_function();
return 0;
error:
buffer_reinit(session->out_buffer);
buffer_reinit(session->out_hashbuf);
buffer_free(session->out_buffer);
buffer_free(session->out_hashbuf);
string_free(str);
leave_function();
@@ -452,10 +444,10 @@ int verify_existing_algo(int algo, const char *name){
/* makes a STRING contating 3 strings : ssh-rsa1,e and n */
/* this is a public key in openssh's format */
static ssh_string make_rsa1_string(ssh_string e, ssh_string n){
ssh_buffer buffer = NULL;
ssh_string rsa = NULL;
ssh_string ret = NULL;
static STRING *make_rsa1_string(STRING *e, STRING *n){
BUFFER *buffer = NULL;
STRING *rsa = NULL;
STRING *ret = NULL;
buffer = buffer_new();
rsa = string_from_char("ssh-rsa1");
@@ -483,8 +475,8 @@ error:
return ret;
}
static int build_session_id1(ssh_session session, ssh_string servern,
ssh_string hostn) {
static int build_session_id1(SSH_SESSION *session, STRING *servern,
STRING *hostn) {
MD5CTX md5 = NULL;
md5 = md5_init();
@@ -493,11 +485,11 @@ static int build_session_id1(ssh_session session, ssh_string servern,
}
#ifdef DEBUG_CRYPTO
ssh_print_hexa("host modulus",string_data(hostn),string_len(hostn));
ssh_print_hexa("server modulus",string_data(servern),string_len(servern));
ssh_print_hexa("host modulus",hostn->string,string_len(hostn));
ssh_print_hexa("server modulus",servern->string,string_len(servern));
#endif
md5_update(md5,string_data(hostn),string_len(hostn));
md5_update(md5,string_data(servern),string_len(servern));
md5_update(md5,hostn->string,string_len(hostn));
md5_update(md5,servern->string,string_len(servern));
md5_update(md5,session->server_kex.cookie,8);
md5_final(session->next_crypto->session_id,md5);
#ifdef DEBUG_CRYPTO
@@ -508,7 +500,7 @@ static int build_session_id1(ssh_session session, ssh_string servern,
}
/* returns 1 if the modulus of k1 is < than the one of k2 */
static int modulus_smaller(ssh_public_key k1, ssh_public_key k2){
static int modulus_smaller(PUBLIC_KEY *k1, PUBLIC_KEY *k2){
bignum n1;
bignum n2;
int res;
@@ -537,12 +529,12 @@ static int modulus_smaller(ssh_public_key k1, ssh_public_key k2){
}
#define ABS(A) ( (A)<0 ? -(A):(A) )
static ssh_string encrypt_session_key(ssh_session session, ssh_public_key srvkey,
ssh_public_key hostkey, int slen, int hlen) {
static STRING *encrypt_session_key(SSH_SESSION *session, PUBLIC_KEY *srvkey,
PUBLIC_KEY *hostkey, int slen, int hlen) {
unsigned char buffer[32] = {0};
int i;
ssh_string data1 = NULL;
ssh_string data2 = NULL;
STRING *data1 = NULL;
STRING *data2 = NULL;
/* first, generate a session key */
ssh_get_random(session->next_crypto->encryptkey, 32, 1);
@@ -614,22 +606,22 @@ static ssh_string encrypt_session_key(ssh_session session, ssh_public_key srvkey
* 32-bit int supported_authentications_mask
*/
int ssh_get_kex1(ssh_session session) {
ssh_string server_exp = NULL;
ssh_string server_mod = NULL;
ssh_string host_exp = NULL;
ssh_string host_mod = NULL;
ssh_string serverkey = NULL;
ssh_string hostkey = NULL;
ssh_string enc_session = NULL;
ssh_public_key srv = NULL;
ssh_public_key host = NULL;
uint32_t server_bits;
uint32_t host_bits;
uint32_t protocol_flags;
uint32_t supported_ciphers_mask;
uint32_t supported_authentications_mask;
uint16_t bits;
int ssh_get_kex1(SSH_SESSION *session) {
STRING *server_exp = NULL;
STRING *server_mod = NULL;
STRING *host_exp = NULL;
STRING *host_mod = NULL;
STRING *serverkey = NULL;
STRING *hostkey = NULL;
STRING *enc_session = NULL;
PUBLIC_KEY *srv = NULL;
PUBLIC_KEY *host = NULL;
u32 server_bits;
u32 host_bits;
u32 protocol_flags;
u32 supported_ciphers_mask;
u32 supported_authentications_mask;
u16 bits;
int rc = -1;
int ko;
@@ -669,7 +661,7 @@ int ssh_get_kex1(ssh_session session) {
buffer_get_u32(session->in_buffer, &supported_ciphers_mask);
ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask);
if ((ko != sizeof(uint32_t)) || !host_mod || !host_exp
if ((ko != sizeof(u32)) || !host_mod || !host_exp
|| !server_mod || !server_exp) {
ssh_log(session, SSH_LOG_RARE, "Invalid SSH_SMSG_PUBLIC_KEY packet");
ssh_set_error(session, SSH_FATAL, "Invalid SSH_SMSG_PUBLIC_KEY packet");
@@ -746,10 +738,10 @@ int ssh_get_kex1(ssh_session session) {
bits, string_len(enc_session));
bits = htons(bits);
/* the encrypted mpint */
if (buffer_add_data(session->out_buffer, &bits, sizeof(uint16_t)) < 0) {
if (buffer_add_data(session->out_buffer, &bits, sizeof(u16)) < 0) {
goto error;
}
if (buffer_add_data(session->out_buffer, string_data(enc_session),
if (buffer_add_data(session->out_buffer, enc_session->string,
string_len(enc_session)) < 0) {
goto error;
}

View File

@@ -22,32 +22,19 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ctype.h>
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/buffer.h"
#include "libssh/keyfiles.h"
#include "libssh/session.h"
#include "libssh/wrapper.h"
#include "libssh/misc.h"
#include "libssh/keys.h"
/*todo: remove this include */
#include "libssh/string.h"
#ifdef HAVE_LIBGCRYPT
#include <gcrypt.h>
@@ -59,15 +46,15 @@
#endif /* HAVE_LIBCRYPTO */
#define MAXLINESIZE 80
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
#ifdef HAVE_LIBGCRYPT
#define MAX_KEY_SIZE 32
#define MAX_PASSPHRASE_SIZE 1024
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
#define ASN1_INTEGER 2
#define ASN1_SEQUENCE 48
#define PKCS5_SALT_LEN 8
@@ -100,17 +87,17 @@ static int load_iv(char *header, unsigned char *iv, int iv_len) {
return 0;
}
static uint32_t char_to_u32(unsigned char *data, uint32_t size) {
uint32_t ret;
uint32_t i;
static u32 char_to_u32(unsigned char *data, u32 size) {
u32 ret;
u32 i;
for (i = 0, ret = 0; i < size; ret = ret << 8, ret += data[i++])
;
return ret;
}
static uint32_t asn1_get_len(ssh_buffer buffer) {
uint32_t len;
static u32 asn1_get_len(BUFFER *buffer) {
u32 len;
unsigned char tmp[4];
if (buffer_get_data(buffer,tmp,1) == 0) {
@@ -133,10 +120,10 @@ static uint32_t asn1_get_len(ssh_buffer buffer) {
return len;
}
static ssh_string asn1_get_int(ssh_buffer buffer) {
ssh_string str;
static STRING *asn1_get_int(BUFFER *buffer) {
STRING *str;
unsigned char type;
uint32_t size;
u32 size;
if (buffer_get_data(buffer, &type, 1) == 0 || type != ASN1_INTEGER) {
return NULL;
@@ -159,12 +146,12 @@ static ssh_string asn1_get_int(ssh_buffer buffer) {
return str;
}
static int asn1_check_sequence(ssh_buffer buffer) {
static int asn1_check_sequence(BUFFER *buffer) {
unsigned char *j = NULL;
unsigned char tmp;
int i;
uint32_t size;
uint32_t padding;
u32 size;
u32 padding;
if (buffer_get_data(buffer, &tmp, 1) == 0 || tmp != ASN1_SEQUENCE) {
return 0;
@@ -173,7 +160,7 @@ static int asn1_check_sequence(ssh_buffer buffer) {
size = asn1_get_len(buffer);
if ((padding = buffer_get_len(buffer) - buffer->pos - size) > 0) {
for (i = buffer_get_len(buffer) - buffer->pos - size,
j = (unsigned char*)buffer_get(buffer) + size + buffer->pos;
j = buffer_get(buffer) + size + buffer->pos;
i;
i--, j++)
{
@@ -241,7 +228,7 @@ static int passphrase_to_key(char *data, unsigned int datalen,
static int privatekey_decrypt(int algo, int mode, unsigned int key_len,
unsigned char *iv, unsigned int iv_len,
ssh_buffer data, ssh_auth_callback cb,
BUFFER *data, ssh_auth_callback cb,
void *userdata,
const char *desc)
{
@@ -342,10 +329,10 @@ static int privatekey_dek_header(char *header, unsigned int header_len,
return load_iv(header + iv_pos, *iv, *iv_len);
}
static ssh_buffer privatekey_file_to_buffer(FILE *fp, int type,
static BUFFER *privatekey_file_to_buffer(FILE *fp, int type,
ssh_auth_callback cb, void *userdata, const char *desc) {
ssh_buffer buffer = NULL;
ssh_buffer out = NULL;
BUFFER *buffer = NULL;
BUFFER *out = NULL;
char buf[MAXLINESIZE] = {0};
unsigned char *iv = NULL;
const char *header_begin;
@@ -456,16 +443,16 @@ static ssh_buffer privatekey_file_to_buffer(FILE *fp, int type,
static int read_rsa_privatekey(FILE *fp, gcry_sexp_t *r,
ssh_auth_callback cb, void *userdata, const char *desc) {
ssh_string n = NULL;
ssh_string e = NULL;
ssh_string d = NULL;
ssh_string p = NULL;
ssh_string q = NULL;
ssh_string unused1 = NULL;
ssh_string unused2 = NULL;
ssh_string u = NULL;
ssh_string v = NULL;
ssh_buffer buffer = NULL;
STRING *n = NULL;
STRING *e = NULL;
STRING *d = NULL;
STRING *p = NULL;
STRING *q = NULL;
STRING *unused1 = NULL;
STRING *unused2 = NULL;
STRING *u = NULL;
STRING *v = NULL;
BUFFER *buffer = NULL;
int rc = 1;
buffer = privatekey_file_to_buffer(fp, TYPE_RSA, cb, userdata, desc);
@@ -528,13 +515,13 @@ error:
static int read_dsa_privatekey(FILE *fp, gcry_sexp_t *r, ssh_auth_callback cb,
void *userdata, const char *desc) {
ssh_buffer buffer = NULL;
ssh_string p = NULL;
ssh_string q = NULL;
ssh_string g = NULL;
ssh_string y = NULL;
ssh_string x = NULL;
ssh_string v = NULL;
BUFFER *buffer = NULL;
STRING *p = NULL;
STRING *q = NULL;
STRING *g = NULL;
STRING *y = NULL;
STRING *x = NULL;
STRING *v = NULL;
int rc = 1;
buffer = privatekey_file_to_buffer(fp, TYPE_DSS, cb, userdata, desc);
@@ -589,18 +576,16 @@ error:
#ifdef HAVE_LIBCRYPTO
static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
ssh_session session = userdata;
SSH_SESSION *session = userdata;
/* unused flag */
(void) rwflag;
ZERO_STRUCTP(buf);
ssh_log(session, SSH_LOG_RARE,
"Trying to call external authentication function");
if (session && session->callbacks->auth_function) {
if (session->callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0,
session->callbacks->userdata) < 0) {
if (session && session->options->auth_function) {
if ((*session->options->auth_function)("Passphrase for private key:", buf, size, 0, 0,
session->options->auth_userdata ? session->options->auth_userdata : NULL) < 0) {
return 0;
}
@@ -611,22 +596,6 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
}
#endif /* HAVE_LIBCRYPTO */
static int privatekey_type_from_file(FILE *fp) {
char buffer[MAXLINESIZE] = {0};
if (!fgets(buffer, MAXLINESIZE, fp)) {
return 0;
}
fseek(fp, 0, SEEK_SET);
if (strncmp(buffer, DSA_HEADER_BEGIN, strlen(DSA_HEADER_BEGIN)) == 0) {
return TYPE_DSS;
}
if (strncmp(buffer, RSA_HEADER_BEGIN, strlen(RSA_HEADER_BEGIN)) == 0) {
return TYPE_RSA;
}
return 0;
}
/** \addtogroup ssh_auth
* @{
*/
@@ -634,16 +603,16 @@ static int privatekey_type_from_file(FILE *fp) {
/** \brief Reads a SSH private key from a file
* \param session SSH Session
* \param filename Filename containing the private key
* \param type Type of the private key. One of TYPE_DSS or TYPE_RSA. Pass 0 to automatically detect the type.
* \param type Type of the private key. One of TYPE_DSS or TYPE_RSA.
* \param passphrase Passphrase to decrypt the private key. Set to null if none is needed or it is unknown.
* \returns a PRIVATE_KEY object containing the private key, or NULL if it failed.
* \see privatekey_free()
* \see publickey_from_privatekey()
*/
ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session, const char *filename,
int type, const char *passphrase) {
ssh_auth_callback auth_cb = NULL;
ssh_private_key privkey = NULL;
PRIVATE_KEY *privkey = NULL;
void *auth_ud = NULL;
FILE *file = NULL;
#ifdef HAVE_LIBGCRYPT
@@ -654,7 +623,6 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
DSA *dsa = NULL;
RSA *rsa = NULL;
#endif
ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename);
file = fopen(filename,"r");
if (file == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED,
@@ -662,25 +630,14 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
return NULL;
}
ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
filename, passphrase ? "true" : "false",
session->callbacks && session->callbacks->auth_function ? "true" : "false");
if (type == 0) {
type = privatekey_type_from_file(file);
if (type == 0) {
fclose(file);
ssh_set_error(session, SSH_FATAL, "Invalid private key file.");
return NULL;
}
}
switch (type) {
case TYPE_DSS:
if (passphrase == NULL) {
if (session->callbacks && session->callbacks->auth_function) {
auth_cb = session->callbacks->auth_function;
auth_ud = session->callbacks->userdata;
if (session->options->auth_function) {
auth_cb = session->options->auth_function;
if (session->options->auth_userdata) {
auth_ud = session->options->auth_userdata;
}
#ifdef HAVE_LIBGCRYPT
valid = read_dsa_privatekey(file, &dsa, auth_cb, auth_ud,
"Passphrase for private key:");
@@ -717,9 +674,11 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
break;
case TYPE_RSA:
if (passphrase == NULL) {
if (session->callbacks && session->callbacks->auth_function) {
auth_cb = session->callbacks->auth_function;
auth_ud = session->callbacks->userdata;
if (session->options->auth_function) {
auth_cb = session->options->auth_function;
if (session->options->auth_userdata) {
auth_ud = session->options->auth_userdata;
}
#ifdef HAVE_LIBGCRYPT
valid = read_rsa_privatekey(file, &rsa, auth_cb, auth_ud,
"Passphrase for private key:");
@@ -756,12 +715,11 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
}
break;
default:
fclose(file);
ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
return NULL;
} /* switch */
privkey = malloc(sizeof(struct ssh_private_key_struct));
privkey = malloc(sizeof(PRIVATE_KEY));
if (privkey == NULL) {
#ifdef HAVE_LIBGCRYPT
gcry_sexp_release(dsa);
@@ -780,24 +738,10 @@ ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
return privkey;
}
/**
* @brief returns the type of a private key
* @param privatekey[in] the private key handle
* @returns one of TYPE_RSA,TYPE_DSS,TYPE_RSA1
* @returns 0 if the type is unknown
* @see privatekey_from_file
* @see ssh_userauth_offer_pubkey
*/
int ssh_privatekey_type(ssh_private_key privatekey){
if (privatekey==NULL)
return 0;
return privatekey->type;
}
/* same that privatekey_from_file() but without any passphrase things. */
ssh_private_key _privatekey_from_file(void *session, const char *filename,
PRIVATE_KEY *_privatekey_from_file(void *session, const char *filename,
int type) {
ssh_private_key privkey = NULL;
PRIVATE_KEY *privkey = NULL;
FILE *file = NULL;
#ifdef HAVE_LIBGCRYPT
gcry_sexp_t dsa = NULL;
@@ -863,7 +807,7 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
return NULL;
}
privkey = malloc(sizeof(struct ssh_private_key_struct));
privkey = malloc(sizeof(PRIVATE_KEY));
if (privkey == NULL) {
#ifdef HAVE_LIBGCRYPT
gcry_sexp_release(dsa);
@@ -885,7 +829,7 @@ ssh_private_key _privatekey_from_file(void *session, const char *filename,
/** \brief deallocate a private key
* \param prv a PRIVATE_KEY object
*/
void privatekey_free(ssh_private_key prv) {
void privatekey_free(PRIVATE_KEY *prv) {
if (prv == NULL) {
return;
}
@@ -897,96 +841,23 @@ void privatekey_free(ssh_private_key prv) {
DSA_free(prv->dsa_priv);
RSA_free(prv->rsa_priv);
#endif
memset(prv, 0, sizeof(struct ssh_private_key_struct));
memset(prv, 0, sizeof(PRIVATE_KEY));
SAFE_FREE(prv);
}
/**
* @brief Write a public key to a file.
*
* @param[in] session The ssh session to use.
*
* @param[in] file The filename to write the key into.
*
* @param[in] pubkey The public key to write.
*
* @param[in] type The type of the public key.
*
* @return 0 on success, -1 on error.
*/
int ssh_publickey_to_file(ssh_session session, const char *file,
ssh_string pubkey, int type) {
FILE *fp;
char *user;
char buffer[1024];
char host[256];
unsigned char *pubkey_64;
size_t len;
int rc;
pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey));
if (pubkey_64 == NULL) {
return -1;
}
user = ssh_get_local_username(session);
if (user == NULL) {
SAFE_FREE(pubkey_64);
return -1;
}
rc = gethostname(host, sizeof(host));
if (rc < 0) {
SAFE_FREE(user);
SAFE_FREE(pubkey_64);
return -1;
}
snprintf(buffer, sizeof(buffer), "%s %s %s@%s\n",
ssh_type_to_char(type),
pubkey_64,
user,
host);
SAFE_FREE(pubkey_64);
SAFE_FREE(user);
ssh_log(session, SSH_LOG_RARE, "Trying to write public key file: %s", file);
ssh_log(session, SSH_LOG_PACKET, "public key file content: %s", buffer);
fp = fopen(file, "w+");
if (fp == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Error opening %s: %s", file, strerror(errno));
return -1;
}
len = strlen(buffer);
if (fwrite(buffer, len, 1, fp) != 1 || ferror(fp)) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Unable to write to %s", file);
fclose(fp);
unlink(file);
return -1;
}
fclose(fp);
return 0;
}
/** \brief Retrieve a public key from a file
* \param session the SSH session
* \param filename Filename of the key
* \param type Pointer to a integer. If it is not null, it contains the type of the key after execution.
* \param _type Pointer to a integer. If it is not null, it contains the type of the key after execution.
* \return a SSH String containing the public key, or NULL if it failed.
* \see string_free()
* \see publickey_from_privatekey()
*/
ssh_string publickey_from_file(ssh_session session, const char *filename,
STRING *publickey_from_file(SSH_SESSION *session, const char *filename,
int *type) {
ssh_buffer buffer = NULL;
BUFFER *buffer = NULL;
char buf[4096] = {0};
ssh_string str = NULL;
STRING *str = NULL;
char *ptr = NULL;
int key_type;
int fd = -1;
@@ -1051,89 +922,24 @@ ssh_string publickey_from_file(ssh_session session, const char *filename,
return str;
}
/**
* @brief Try to read the public key from a given file.
*
* @param[in] session The ssh session to use.
*
* @param[in] keyfile The name of the private keyfile.
*
* @param[out] publickey A ssh_string to store the public key.
*
* @param[out] type A pointer to an integer to store the type.
*
* @return 0 on success, -1 on error or the private key doesn't
* exist, 1 if the public key doesn't exist.
*/
int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
ssh_string *publickey, int *type) {
char *pubkey_file;
size_t len;
ssh_string pubkey_string;
int pubkey_type;
if (session == NULL || keyfile == NULL || publickey == NULL || type == NULL) {
return -1;
}
if (session->sshdir == NULL) {
if (ssh_options_apply(session) < 0) {
return -1;
}
}
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", keyfile);
if (!ssh_file_readaccess_ok(keyfile)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", keyfile);
return -1;
}
len = strlen(keyfile) + 5;
pubkey_file = malloc(len);
if (pubkey_file == NULL) {
return -1;
}
snprintf(pubkey_file, len, "%s.pub", keyfile);
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s",
pubkey_file);
if (!ssh_file_readaccess_ok(pubkey_file)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s",
pubkey_file);
SAFE_FREE(pubkey_file);
return 1;
}
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
/*
* We are sure both the private and public key file is readable. We return
* the public as a string, and the private filename as an argument
*/
pubkey_string = publickey_from_file(session, pubkey_file, &pubkey_type);
if (pubkey_string == NULL) {
ssh_log(session, SSH_LOG_PACKET,
"Wasn't able to open public key file %s: %s",
pubkey_file,
ssh_get_error(session));
SAFE_FREE(pubkey_file);
return -1;
}
SAFE_FREE(pubkey_file);
*publickey = pubkey_string;
*type = pubkey_type;
return 0;
}
ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct keytab,
STRING *try_publickey_from_file(SSH_SESSION *session, struct keys_struct keytab,
char **privkeyfile, int *type) {
static char *home = NULL;
char public[256] = {0};
char private[256] = {0};
const char *priv;
const char *pub;
char *new;
ssh_string pubkey=NULL;
STRING *pubkey;
if (home == NULL) {
home = ssh_get_user_home_dir();
if (home == NULL) {
ssh_set_error(session,SSH_FATAL,"User home dir impossible to guess");
return NULL;
}
}
pub = keytab.publickey;
if (pub == NULL) {
@@ -1144,48 +950,45 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k
return NULL;
}
if (session->sshdir == NULL) {
if (ssh_options_apply(session) < 0) {
return NULL;
}
/* are them readable ? */
snprintf(public, sizeof(public), pub, home);
ssh_log(session, SSH_LOG_PACKET, "Trying to open public key %s", public);
if (!ssh_file_readaccess_ok(public)) {
ssh_log(session, SSH_LOG_PACKET, "Failed");
return NULL;
}
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub);
if (!ssh_file_readaccess_ok(pub)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub);
goto error;
snprintf(private, sizeof(private), priv, home);
ssh_log(session, SSH_LOG_PACKET, "Trying to open private key %s", private);
if (!ssh_file_readaccess_ok(private)) {
ssh_log(session, SSH_LOG_PACKET, "Failed");
return NULL;
}
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv);
if (!ssh_file_readaccess_ok(priv)) {
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv);
goto error;
}
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
ssh_log(session, SSH_LOG_PACKET, "Success reading public and private key");
/*
* We are sure both the private and public key file is readable. We return
* the public as a string, and the private filename as an argument
*/
pubkey = publickey_from_file(session, pub, type);
pubkey = publickey_from_file(session, public, type);
if (pubkey == NULL) {
ssh_log(session, SSH_LOG_PACKET,
"Wasn't able to open public key file %s: %s",
pub,
public,
ssh_get_error(session));
goto error;
return NULL;
}
new = realloc(*privkeyfile, strlen(priv) + 1);
new = realloc(*privkeyfile, strlen(private) + 1);
if (new == NULL) {
string_free(pubkey);
goto error;
return NULL;
}
strcpy(new, priv);
strcpy(new, private);
*privkeyfile = new;
error:
return pubkey;
}
@@ -1214,14 +1017,10 @@ static int alldigits(const char *s) {
* \internal
*/
static char *lowercase(const char* str) {
char *new, *p;
char *p = 0;
char *new = strdup(str);
if (str == NULL) {
return NULL;
}
new = strdup(str);
if (new == NULL) {
if((str == NULL) || (new == NULL)) {
return NULL;
}
@@ -1256,7 +1055,7 @@ static void tokens_free(char **tokens) {
* \returns NULL if no match was found or the file was not found
* \returns found_type type of key (ie "dsa","ssh-rsa1"). Don't free that value.
*/
static char **ssh_get_knownhost_line(ssh_session session, FILE **file,
static char **ssh_get_knownhost_line(SSH_SESSION *session, FILE **file,
const char *filename, const char **found_type) {
char buffer[4096] = {0};
char *ptr;
@@ -1275,7 +1074,6 @@ static char **ssh_get_knownhost_line(ssh_session session, FILE **file,
while (fgets(buffer, sizeof(buffer), *file)) {
ptr = strchr(buffer, '\n');
if (ptr) {
*ptr = '\0';
}
ptr = strchr(buffer,'\r');
@@ -1338,16 +1136,16 @@ static char **ssh_get_knownhost_line(ssh_session session, FILE **file,
* \return 0 if the key doesn't match
* \return -1 on error
*/
static int check_public_key(ssh_session session, char **tokens) {
ssh_string pubkey = session->current_crypto->server_pubkey;
ssh_buffer pubkey_buffer;
static int check_public_key(SSH_SESSION *session, char **tokens) {
STRING *pubkey = session->current_crypto->server_pubkey;
BUFFER *pubkey_buffer;
char *pubkey_64;
/* ok we found some public key in known hosts file. now un-base64it */
if (alldigits(tokens[1])) {
/* openssh rsa1 format */
bignum tmpbn;
ssh_string tmpstring;
STRING *tmpstring;
unsigned int len;
int i;
@@ -1387,7 +1185,6 @@ static int check_public_key(ssh_session session, char **tokens) {
bignum_free(tmpbn);
return -1;
}
/* TODO: fix the hardcoding */
tmpstring->size = htonl(len);
#ifdef HAVE_LIBGCRYPT
bignum_bn2bin(tmpbn, len, tmpstring->string);
@@ -1438,7 +1235,7 @@ static int check_public_key(ssh_session session, char **tokens) {
* \returns 1 if it matches
* \returns 0 otherwise
*/
static int match_hashed_host(ssh_session session, const char *host,
static int match_hashed_host(SSH_SESSION *session, const char *host,
const char *sourcehash) {
/* Openssh hash structure :
* |1|base64 encoded salt|base64 encoded hash
@@ -1446,8 +1243,8 @@ static int match_hashed_host(ssh_session session, const char *host,
* hash := HMAC_SHA1(key=salt,data=host)
*/
unsigned char buffer[256] = {0};
ssh_buffer salt;
ssh_buffer hash;
BUFFER *salt;
BUFFER *hash;
HMACCTX mac;
char *source;
char *b64hash;
@@ -1550,66 +1347,56 @@ static int match_hashed_host(ssh_session session, const char *host,
* if host key is accepted\n
* SSH_SERVER_ERROR: Some error happened
*
* \see ssh_options_set_wanted_algo()
* \see ssh_get_pubkey_hash()
*
* \bug There is no current way to remove or modify an entry into the known
* host table.
*/
int ssh_is_server_known(ssh_session session) {
int ssh_is_server_known(SSH_SESSION *session) {
FILE *file = NULL;
char **tokens;
char *host;
char *hostport;
const char *type;
int match;
int ret = SSH_SERVER_NOT_KNOWN;
enter_function();
if (session->knownhosts == NULL) {
if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't find a known_hosts file");
leave_function();
return SSH_SERVER_FILE_NOT_FOUND;
}
if (ssh_options_default_known_hosts_file(session->options) < 0) {
ssh_set_error(session, SSH_REQUEST_DENIED,
"Can't find a known_hosts file");
leave_function();
return SSH_SERVER_FILE_NOT_FOUND;
}
if (session->host == NULL) {
if (session->options->host == NULL) {
ssh_set_error(session, SSH_FATAL,
"Can't verify host in known hosts if the hostname isn't known");
leave_function();
return SSH_SERVER_ERROR;
}
host = lowercase(session->host);
hostport = ssh_hostport(host,session->port);
if (host == NULL || hostport == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(host);
SAFE_FREE(hostport);
host = lowercase(session->options->host);
if (host == NULL) {
ssh_set_error(session, SSH_FATAL, "Not enough space!");
leave_function();
return SSH_SERVER_ERROR;
}
do {
tokens = ssh_get_knownhost_line(session, &file,
session->knownhosts, &type);
session->options->known_hosts_file, &type);
/* End of file, return the current state */
if (tokens == NULL) {
break;
}
match = match_hashed_host(session, host, tokens[0]);
if (match == 0){
match = match_hostname(hostport, tokens[0], strlen(tokens[0]));
}
if (match == 0) {
match = match_hostname(host, tokens[0], strlen(tokens[0]));
}
if (match == 0) {
match = match_hashed_host(session, hostport, tokens[0]);
}
if (match) {
/* We got a match. Now check the key type */
if (strcmp(session->current_crypto->server_pubkey_type, type) != 0) {
@@ -1640,7 +1427,6 @@ int ssh_is_server_known(ssh_session session) {
} while (1);
SAFE_FREE(host);
SAFE_FREE(hostport);
if (file != NULL) {
fclose(file);
}
@@ -1650,77 +1436,41 @@ int ssh_is_server_known(ssh_session session) {
return ret;
}
/**
* @brief Write the current server as known in the known hosts file.
*
* This will create the known hosts file if it does not exist. You generaly use
* it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN.
*
* @param[in] session The ssh session to use.
*
* @return SSH_OK on success, SSH_ERROR on error.
/** You generaly use it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN
* \brief write the current server as known in the known hosts file. This will create the known hosts file if it does not exist.
* \param session ssh session
* \return 0 on success, -1 on error
*/
int ssh_write_knownhost(ssh_session session) {
ssh_string pubkey = session->current_crypto->server_pubkey;
int ssh_write_knownhost(SSH_SESSION *session) {
STRING *pubkey = session->current_crypto->server_pubkey;
unsigned char *pubkey_64;
char buffer[4096] = {0};
FILE *file;
char *dir;
char *host;
char *hostport;
size_t len = 0;
if (session->host == NULL) {
ssh_set_error(session, SSH_FATAL,
"Can't write host in known hosts if the hostname isn't known");
return SSH_ERROR;
}
host = lowercase(session->host);
/* If using a nonstandard port, save the host in the [host]:port format */
if(session->port != 22){
hostport = ssh_hostport(host,session->port);
SAFE_FREE(host);
host=hostport;
hostport=NULL;
}
if (session->knownhosts == NULL) {
if (ssh_options_apply(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file");
return -1;
}
}
/* Check if ~/.ssh exists and create it if not */
dir = ssh_dirname(session->knownhosts);
if (dir == NULL) {
ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
if (ssh_options_default_known_hosts_file(session->options) < 0) {
ssh_set_error(session, SSH_FATAL, "Cannot find known_hosts file.");
return -1;
}
if (! ssh_file_readaccess_ok(dir)) {
if (ssh_mkdir(dir, 0700) < 0) {
ssh_set_error(session, SSH_FATAL,
"Cannot create %s directory.", dir);
SAFE_FREE(dir);
return -1;
}
}
SAFE_FREE(dir);
file = fopen(session->knownhosts, "a");
if (session->options->host == NULL) {
ssh_set_error(session, SSH_FATAL,
"Cannot write host in known hosts if the hostname is unknown");
return -1;
}
file = fopen(session->options->known_hosts_file, "a");
if (file == NULL) {
ssh_set_error(session, SSH_FATAL,
"Couldn't open known_hosts file %s for appending: %s",
session->knownhosts, strerror(errno));
SAFE_FREE(host);
session->options->known_hosts_file, strerror(errno));
return -1;
}
if (strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1") == 0) {
/* openssh uses a different format for ssh-rsa1 keys.
Be compatible --kv */
ssh_public_key key;
PUBLIC_KEY *key;
char *e_string = NULL;
char *n_string = NULL;
bignum e = NULL;
@@ -1733,7 +1483,6 @@ int ssh_write_knownhost(ssh_session session) {
key = publickey_from_string(session, pubkey);
if (key == NULL) {
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1742,7 +1491,6 @@ int ssh_write_knownhost(ssh_session session) {
if (sexp == NULL) {
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
@@ -1750,7 +1498,6 @@ int ssh_write_knownhost(ssh_session session) {
if (e == NULL) {
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1759,7 +1506,6 @@ int ssh_write_knownhost(ssh_session session) {
publickey_free(key);
bignum_free(e);
fclose(file);
SAFE_FREE(host);
return -1;
}
n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
@@ -1768,7 +1514,6 @@ int ssh_write_knownhost(ssh_session session) {
publickey_free(key);
bignum_free(e);
fclose(file);
SAFE_FREE(host);
return -1;
}
@@ -1793,13 +1538,12 @@ int ssh_write_knownhost(ssh_session session) {
#endif
publickey_free(key);
fclose(file);
SAFE_FREE(host);
return -1;
}
snprintf(buffer, sizeof(buffer),
"%s %d %s %s\n",
host,
session->options->host,
rsa_size << 3,
e_string,
n_string);
@@ -1819,21 +1563,20 @@ int ssh_write_knownhost(ssh_session session) {
pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey));
if (pubkey_64 == NULL) {
fclose(file);
SAFE_FREE(host);
return -1;
}
snprintf(buffer, sizeof(buffer),
"%s %s %s\n",
host,
session->options->host,
session->current_crypto->server_pubkey_type,
pubkey_64);
SAFE_FREE(pubkey_64);
}
SAFE_FREE(host);
len = strlen(buffer);
if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) {
if (fwrite(buffer, len, 1, file) != len || ferror(file)) {
fclose(file);
return -1;
}

View File

@@ -28,15 +28,6 @@
#include <openssl/rsa.h>
#endif
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/server.h"
#include "libssh/buffer.h"
#include "libssh/agent.h"
#include "libssh/session.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
#include "libssh/string.h"
/** \addtogroup ssh_auth
* @{
@@ -74,14 +65,14 @@ int ssh_type_from_name(const char *name) {
return -1;
}
ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
ssh_string p = NULL;
ssh_string q = NULL;
ssh_string g = NULL;
ssh_string pubkey = NULL;
ssh_public_key key = NULL;
PUBLIC_KEY *publickey_make_dss(SSH_SESSION *session, BUFFER *buffer) {
STRING *p = NULL;
STRING *q = NULL;
STRING *g = NULL;
STRING *pubkey = NULL;
PUBLIC_KEY *key = NULL;
key = malloc(sizeof(struct ssh_public_key_struct));
key = malloc(sizeof(PUBLIC_KEY));
if (key == NULL) {
buffer_free(buffer);
return NULL;
@@ -105,10 +96,10 @@ ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
#ifdef HAVE_LIBGCRYPT
gcry_sexp_build(&key->dsa_pub, NULL,
"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",
string_len(p), string_data(p),
string_len(q), string_data(q),
string_len(g), string_data(g),
string_len(pubkey), string_data(pubkey));
string_len(p), p->string,
string_len(q), q->string,
string_len(g), g->string,
string_len(pubkey), pubkey->string);
if (key->dsa_pub == NULL) {
goto error;
}
@@ -131,9 +122,9 @@ ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
#endif /* HAVE_LIBCRYPTO */
#ifdef DEBUG_CRYPTO
ssh_print_hexa("p", string_data(p), string_len(p));
ssh_print_hexa("q", string_data(q), string_len(q));
ssh_print_hexa("g", string_data(g), string_len(g));
ssh_print_hexa("p", p->string, string_len(p));
ssh_print_hexa("q", q->string, string_len(q));
ssh_print_hexa("g", g->string, string_len(g));
#endif
string_burn(p);
@@ -160,13 +151,13 @@ error:
return NULL;
}
ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
PUBLIC_KEY *publickey_make_rsa(SSH_SESSION *session, BUFFER *buffer,
int type) {
ssh_string e = NULL;
ssh_string n = NULL;
ssh_public_key key = NULL;
STRING *e = NULL;
STRING *n = NULL;
PUBLIC_KEY *key = NULL;
key = malloc(sizeof(struct ssh_public_key_struct));
key = malloc(sizeof(PUBLIC_KEY));
if (key == NULL) {
buffer_free(buffer);
return NULL;
@@ -187,8 +178,8 @@ ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
#ifdef HAVE_LIBGCRYPT
gcry_sexp_build(&key->rsa_pub, NULL,
"(public-key(rsa(n %b)(e %b)))",
string_len(n), string_data(n),
string_len(e),string_data(e));
string_len(n), n->string,
string_len(e),e->string);
if (key->rsa_pub == NULL) {
goto error;
}
@@ -207,8 +198,8 @@ ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
#endif
#ifdef DEBUG_CRYPTO
ssh_print_hexa("e", string_data(e), string_len(e));
ssh_print_hexa("n", string_data(n), string_len(n));
ssh_print_hexa("e", e->string, string_len(e));
ssh_print_hexa("n", n->string, string_len(n));
#endif
string_burn(e);
@@ -227,7 +218,7 @@ error:
return NULL;
}
void publickey_free(ssh_public_key key) {
void publickey_free(PUBLIC_KEY *key) {
if (key == NULL) {
return;
}
@@ -254,9 +245,9 @@ void publickey_free(ssh_public_key key) {
SAFE_FREE(key);
}
ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) {
ssh_buffer tmpbuf = NULL;
ssh_string type_s = NULL;
PUBLIC_KEY *publickey_from_string(SSH_SESSION *session, STRING *pubkey_s) {
BUFFER *tmpbuf = NULL;
STRING *type_s = NULL;
char *type_c = NULL;
int type;
@@ -265,7 +256,7 @@ ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) {
return NULL;
}
if (buffer_add_data(tmpbuf, string_data(pubkey_s), string_len(pubkey_s)) < 0) {
if (buffer_add_data(tmpbuf, pubkey_s->string, string_len(pubkey_s)) < 0) {
goto error;
}
@@ -305,21 +296,21 @@ error:
* \returns the public key
* \see publickey_to_string()
*/
ssh_public_key publickey_from_privatekey(ssh_private_key prv) {
ssh_public_key key = NULL;
PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv) {
PUBLIC_KEY *key = NULL;
#ifdef HAVE_LIBGCRYPT
gcry_sexp_t sexp;
const char *tmp = NULL;
size_t size;
ssh_string p = NULL;
ssh_string q = NULL;
ssh_string g = NULL;
ssh_string y = NULL;
ssh_string e = NULL;
ssh_string n = NULL;
STRING *p = NULL;
STRING *q = NULL;
STRING *g = NULL;
STRING *y = NULL;
STRING *e = NULL;
STRING *n = NULL;
#endif /* HAVE_LIBGCRYPT */
key = malloc(sizeof(struct ssh_public_key_struct));
key = malloc(sizeof(PUBLIC_KEY));
if (key == NULL) {
return NULL;
}
@@ -378,10 +369,10 @@ ssh_public_key publickey_from_privatekey(ssh_private_key prv) {
gcry_sexp_build(&key->dsa_pub, NULL,
"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",
string_len(p), string_data(p),
string_len(q), string_data(q),
string_len(g), string_data(g),
string_len(y), string_data(y));
string_len(p), p->string,
string_len(q), q->string,
string_len(g), g->string,
string_len(y), y->string);
string_burn(p);
string_free(p);
@@ -437,8 +428,8 @@ ssh_public_key publickey_from_privatekey(ssh_private_key prv) {
gcry_sexp_build(&key->rsa_pub, NULL,
"(public-key(rsa(n %b)(e %b)))",
string_len(n), string_data(n),
string_len(e), string_data(e));
string_len(n), n->string,
string_len(e), e->string);
if (key->rsa_pub == NULL) {
goto error;
}
@@ -487,14 +478,14 @@ error:
}
#ifdef HAVE_LIBGCRYPT
static int dsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
static int dsa_public_to_string(gcry_sexp_t key, BUFFER *buffer) {
#elif defined HAVE_LIBCRYPTO
static int dsa_public_to_string(DSA *key, ssh_buffer buffer) {
static int dsa_public_to_string(DSA *key, BUFFER *buffer) {
#endif
ssh_string p = NULL;
ssh_string q = NULL;
ssh_string g = NULL;
ssh_string n = NULL;
STRING *p = NULL;
STRING *q = NULL;
STRING *g = NULL;
STRING *n = NULL;
int rc = -1;
@@ -549,6 +540,7 @@ static int dsa_public_to_string(DSA *key, ssh_buffer buffer) {
goto error;
}
string_fill(n, (char *) tmp, size);
gcry_sexp_release(sexp);
#elif defined HAVE_LIBCRYPTO
p = make_bignum_string(key->p);
@@ -591,13 +583,13 @@ error:
}
#ifdef HAVE_LIBGCRYPT
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
static int rsa_public_to_string(gcry_sexp_t key, BUFFER *buffer) {
#elif defined HAVE_LIBCRYPTO
static int rsa_public_to_string(RSA *key, ssh_buffer buffer) {
static int rsa_public_to_string(RSA *key, BUFFER *buffer) {
#endif
ssh_string e = NULL;
ssh_string n = NULL;
STRING *e = NULL;
STRING *n = NULL;
int rc = -1;
@@ -663,10 +655,10 @@ error:
* \returns a SSH String containing the public key
* \see string_free()
*/
ssh_string publickey_to_string(ssh_public_key key) {
ssh_string type = NULL;
ssh_string ret = NULL;
ssh_buffer buf = NULL;
STRING *publickey_to_string(PUBLIC_KEY *key) {
STRING *type = NULL;
STRING *ret = NULL;
BUFFER *buf = NULL;
buf = buffer_new();
if (buf == NULL) {
@@ -710,12 +702,12 @@ error:
}
/* Signature decoding functions */
static ssh_string signature_to_string(SIGNATURE *sign) {
static STRING *signature_to_string(SIGNATURE *sign) {
unsigned char buffer[40] = {0};
ssh_buffer tmpbuf = NULL;
ssh_string str = NULL;
ssh_string tmp = NULL;
ssh_string rs = NULL;
BUFFER *tmpbuf = NULL;
STRING *str = NULL;
STRING *tmp = NULL;
STRING *rs = NULL;
int rc = -1;
#ifdef HAVE_LIBGCRYPT
const char *r = NULL;
@@ -723,8 +715,8 @@ static ssh_string signature_to_string(SIGNATURE *sign) {
gcry_sexp_t sexp;
size_t size = 0;
#elif defined HAVE_LIBCRYPTO
ssh_string r = NULL;
ssh_string s = NULL;
STRING *r = NULL;
STRING *s = NULL;
#endif
tmpbuf = buffer_new();
@@ -785,8 +777,8 @@ static ssh_string signature_to_string(SIGNATURE *sign) {
return NULL;
}
memcpy(buffer, (char *)string_data(r) + string_len(r) - 20, 20);
memcpy(buffer + 20, (char *)string_data(s) + string_len(s) - 20, 20);
memcpy(buffer, r->string + string_len(r) - 20, 20);
memcpy(buffer + 20, s->string + string_len(s) - 20, 20);
string_free(r);
string_free(s);
@@ -854,13 +846,13 @@ static ssh_string signature_to_string(SIGNATURE *sign) {
}
/* TODO : split this function in two so it becomes smaller */
SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
ssh_public_key pubkey, int needed_type) {
SIGNATURE *signature_from_string(SSH_SESSION *session, STRING *signature,
PUBLIC_KEY *pubkey, int needed_type) {
SIGNATURE *sign = NULL;
ssh_buffer tmpbuf = NULL;
ssh_string rs = NULL;
ssh_string type_s = NULL;
ssh_string e = NULL;
BUFFER *tmpbuf = NULL;
STRING *rs = NULL;
STRING *type_s = NULL;
STRING *e = NULL;
char *type_c = NULL;
int type;
int len;
@@ -869,8 +861,8 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
gcry_sexp_t sig;
#elif defined HAVE_LIBCRYPTO
DSA_SIG *sig = NULL;
ssh_string r = NULL;
ssh_string s = NULL;
STRING *r = NULL;
STRING *s = NULL;
#endif
sign = malloc(sizeof(SIGNATURE));
@@ -886,7 +878,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
return NULL;
}
if (buffer_add_data(tmpbuf, string_data(signature), string_len(signature)) < 0) {
if (buffer_add_data(tmpbuf, signature->string, string_len(signature)) < 0) {
signature_free(sign);
buffer_free(tmpbuf);
return NULL;
@@ -934,7 +926,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
* them to bignums (ou pas ;) */
#ifdef HAVE_LIBGCRYPT
if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
20 ,string_data(rs), 20,(unsigned char *)string_data(rs) + 20)) {
20 ,rs->string, 20, rs->string + 20)) {
string_free(rs);
signature_free(sign);
return NULL;
@@ -950,8 +942,8 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
return NULL;
}
string_fill(r, string_data(rs), 20);
string_fill(s, (char *)string_data(rs) + 20, 20);
string_fill(r, rs->string, 20);
string_fill(s, rs->string + 20, 20);
sig = DSA_SIG_new();
if (sig == NULL) {
@@ -975,8 +967,8 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
#endif
#ifdef DEBUG_CRYPTO
ssh_print_hexa("r", string_data(rs), 20);
ssh_print_hexa("s", (const unsigned char *)string_data(rs) + 20, 20);
ssh_print_hexa("r", rs->string, 20);
ssh_print_hexa("s", rs->string + 20, 20);
#endif
string_free(rs);
@@ -1012,7 +1004,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
sign->type = TYPE_RSA;
#ifdef HAVE_LIBGCRYPT
if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
string_len(e), string_data(e))) {
string_len(e), e->string)) {
signature_free(sign);
string_free(e);
return NULL;
@@ -1025,7 +1017,7 @@ SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
#ifdef DEBUG_CRYPTO
ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len);
ssh_print_hexa("RSA signature", string_data(e), len);
ssh_print_hexa("RSA signature", e->string, len);
#endif
#ifdef HAVE_LIBGCRYPT
@@ -1078,8 +1070,8 @@ void signature_free(SIGNATURE *sign) {
* I think now, maybe it's a bad idea to name it has it should have be
* named in libcrypto
*/
static ssh_string RSA_do_sign(const unsigned char *payload, int len, RSA *privkey) {
ssh_string sign = NULL;
static STRING *RSA_do_sign(const unsigned char *payload, int len, RSA *privkey) {
STRING *sign = NULL;
unsigned char *buffer = NULL;
unsigned int size;
@@ -1107,11 +1099,11 @@ static ssh_string RSA_do_sign(const unsigned char *payload, int len, RSA *privke
#endif
#ifndef _WIN32
ssh_string ssh_do_sign_with_agent(ssh_session session,
struct ssh_buffer_struct *buf, struct ssh_public_key_struct *publickey) {
struct ssh_buffer_struct *sigbuf = NULL;
struct ssh_string_struct *signature = NULL;
struct ssh_string_struct *session_id = NULL;
STRING *ssh_do_sign_with_agent(struct ssh_session *session,
struct buffer_struct *buf, struct public_key_struct *publickey) {
struct buffer_struct *sigbuf = NULL;
struct string_struct *signature = NULL;
struct string_struct *session_id = NULL;
struct ssh_crypto_struct *crypto = NULL;
if (session->current_crypto) {
@@ -1155,80 +1147,16 @@ ssh_string ssh_do_sign_with_agent(ssh_session session,
}
#endif /* _WIN32 */
/*
* This function concats in a buffer the values needed to do a signature
* verification. */
ssh_buffer ssh_userauth_build_digest(ssh_session session, ssh_message msg, char *service) {
/*
The value of 'signature' is a signature by the corresponding private
key over the following data, in the following order:
string session identifier
byte SSH_MSG_USERAUTH_REQUEST
string user name
string service name
string "publickey"
boolean TRUE
string public key algorithm name
string public key to be used for authentication
*/
struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto :
session->next_crypto;
ssh_buffer buffer = NULL;
ssh_string session_id = NULL;
uint8_t type = SSH2_MSG_USERAUTH_REQUEST;
ssh_string username = string_from_char(msg->auth_request.username);
ssh_string servicename = string_from_char(service);
ssh_string method = string_from_char("publickey");
uint8_t has_sign = 1;
ssh_string algo = string_from_char(msg->auth_request.public_key->type_c);
ssh_string publickey = publickey_to_string(msg->auth_request.public_key);
buffer = buffer_new();
if (buffer == NULL) {
goto error;
}
session_id = string_new(SHA_DIGEST_LEN);
if (session_id == NULL) {
buffer_free(buffer);
buffer = NULL;
goto error;
}
string_fill(session_id, crypto->session_id, SHA_DIGEST_LEN);
if(buffer_add_ssh_string(buffer, session_id) < 0 ||
buffer_add_u8(buffer, type) < 0 ||
buffer_add_ssh_string(buffer, username) < 0 ||
buffer_add_ssh_string(buffer, servicename) < 0 ||
buffer_add_ssh_string(buffer, method) < 0 ||
buffer_add_u8(buffer, has_sign) < 0 ||
buffer_add_ssh_string(buffer, algo) < 0 ||
buffer_add_ssh_string(buffer, publickey) < 0) {
buffer_free(buffer);
buffer = NULL;
goto error;
}
error:
if(session_id) string_free(session_id);
if(username) string_free(username);
if(servicename) string_free(servicename);
if(method) string_free(method);
if(algo) string_free(algo);
if(publickey) string_free(publickey);
return buffer;
}
/*
* This function signs the session id (known as H) as a string then
* the content of sigbuf */
ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
ssh_private_key privatekey) {
struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto :
STRING *ssh_do_sign(SSH_SESSION *session, BUFFER *sigbuf,
PRIVATE_KEY *privatekey) {
CRYPTO *crypto = session->current_crypto ? session->current_crypto :
session->next_crypto;
unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
ssh_string session_str = NULL;
ssh_string signature = NULL;
STRING *session_str = NULL;
STRING *signature = NULL;
SIGNATURE *sign = NULL;
SHACTX ctx = NULL;
#ifdef HAVE_LIBGCRYPT
@@ -1321,8 +1249,8 @@ ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
return signature;
}
ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key key) {
ssh_string str = NULL;
STRING *ssh_encrypt_rsa1(SSH_SESSION *session, STRING *data, PUBLIC_KEY *key) {
STRING *str = NULL;
size_t len = string_len(data);
size_t size = 0;
#ifdef HAVE_LIBGCRYPT
@@ -1331,7 +1259,7 @@ ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key
gcry_sexp_t data_sexp;
if (gcry_sexp_build(&data_sexp, NULL, "(data(flags pkcs1)(value %b))",
len, string_data(data))) {
len, data->string)) {
ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
return NULL;
}
@@ -1375,7 +1303,7 @@ ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key
return NULL;
}
if (RSA_public_encrypt(len, string_data(data), string_data(str), key->rsa_pub,
if (RSA_public_encrypt(len, data->string, str->string, key->rsa_pub,
RSA_PKCS1_PADDING) < 0) {
string_free(str);
return NULL;
@@ -1387,11 +1315,11 @@ ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key
/* this function signs the session id */
ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key privatekey) {
struct ssh_crypto_struct *crypto=session->current_crypto ? session->current_crypto :
STRING *ssh_sign_session_id(SSH_SESSION *session, PRIVATE_KEY *privatekey) {
CRYPTO *crypto=session->current_crypto ? session->current_crypto :
session->next_crypto;
unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
ssh_string signature = NULL;
STRING *signature = NULL;
SIGNATURE *sign = NULL;
SHACTX ctx = NULL;
#ifdef HAVE_LIBGCRYPT

61
libssh/libssh.map Normal file
View File

@@ -0,0 +1,61 @@
SSH_0.3 {
global:
ssh_get_error; ssh_get_error_code;
ssh_new; ssh_set_options; ssh_get_fd; ssh_silent_disconnect;
ssh_connect; ssh_disconnect; ssh_service_request; ssh_get_issue_banner;
ssh_copyright; ssh_get_version; ssh_finalize;
ssh_set_fd_toread; ssh_set_fd_towrite; ssh_set_fd_except;
string_from_char; string_len; string_new; string_fill; string_to_char;
string_copy; string_burn; string_data;
ssh_crypto_init;
ssh_get_hexa; ssh_print_hexa; ssh_get_random;
ssh_get_pubkey_hash; ssh_get_pubkey;
ssh_fd_poll; ssh_select; publickey_free;
privatekey_from_file; publickey_to_string; publickey_from_privatekey;
private_key_free; publickey_from_file; try_publickey_from_file;
ssh_is_server_known; ssh_write_knownhost;
channel_new; channel_open_forward; channel_open_session; channel_free;
channel_request_pty; channel_request_pty_size; channel_change_pty_size;
channel_request_shell; channel_request_subsystem; channel_request_env;
channel_request_exec; channel_request_sftp; channel_write;
channel_send_eof; channel_read_buffer; channel_read; channel_read_nonblocking;
channel_poll; channel_close; channel_is_open;
channel_is_closed; channel_is_eof; channel_select;
ssh_options_new; ssh_options_copy; ssh_options_free; ssh_options_set_wanted_algos;
ssh_options_set_username; ssh_options_set_port; ssh_options_getopt;
ssh_options_set_host; ssh_options_set_fd; ssh_options_set_bind;
ssh_options_set_identity; ssh_options_set_status_callback;
ssh_options_set_timeout; ssh_options_set_ssh_dir;
ssh_options_set_known_hosts_file; ssh_options_allow_ssh1;
ssh_options_allow_ssh2; ssh_options_set_dsa_server_key;
ssh_options_set_rsa_server_key;
buffer_new; buffer_free; buffer_get; buffer_get_len;
ssh_userauth_none; ssh_userauth_password; ssh_userauth_offer_pubkey;
ssh_userauth_pubkey; ssh_userauth_autopubkey; ssh_userauth_kbdint;
ssh_userauth_kbdint_getnprompts; ssh_userauth_kbdint_getname;
ssh_userauth_kbdint_getinstruction; ssh_userauth_kbdint_getprompt;
ssh_userauth_kbdint_setanswer;
sftp_new; sftp_free; sftp_init; sftp_opendir; sftp_readdir; sftp_dir_eof;
sftp_stat; sftp_lstat; sftp_fstat; sftp_attributes_free; sftp_dir_close;
sftp_file_close; sftp_open; sftp_read; sftp_write; sftp_seek; sftp_tell;
sftp_rewind; sftp_rm; sftp_rmdir; sftp_mkdir; sftp_rename; sftp_setstat;
sftp_canonicalize_path; sftp_server_new; sftp_server_init;
sftp_get_client_message; sftp_client_message_free; sftp_reply_name;
sftp_reply_handle; sftp_handle_alloc; sftp_reply_attr; sftp_handle;
sftp_reply_status; sftp_reply_names_add; sftp_reply_names;
sftp_reply_data; sftp_handle_remove;
ssh_bind_new; ssh_bind_set_options; ssh_bind_listen; ssh_bind_set_blocking;
ssh_bind_get_fd; ssh_bind_set_toaccept; ssh_bind_accept; ssh_bind_free;
ssh_accept;
ssh_message_get; ssh_message_type; ssh_message_subtype;
ssh_message_reply_default; ssh_message_free; ssh_message_auth_user;
ssh_message_auth_password; ssh_message_auth_reply_success;
ssh_message_auth_set_methods;
ssh_message_channel_request_open_reply_accept;
ssh_message_channel_request_channel; ssh_message_channel_request_pty_term;
ssh_message_channel_request_subsystem;
ssh_message_channel_request_reply_success;
set_encrypt_key; set_decrypt_key; cbc_encrypt; cbc_decrypt;
local:
*;
};

View File

@@ -26,7 +26,6 @@
#include <string.h>
#include "libssh/priv.h"
#include "libssh/session.h"
/**
* @defgroup ssh_log SSH Logging
@@ -45,7 +44,7 @@
*
* @param format The format string of the log entry.
*/
void ssh_log(ssh_session session, int verbosity, const char *format, ...) {
void ssh_log(SSH_SESSION *session, int verbosity, const char *format, ...) {
char buffer[1024];
char indent[256];
int min;
@@ -56,9 +55,8 @@ void ssh_log(ssh_session session, int verbosity, const char *format, ...) {
vsnprintf(buffer, sizeof(buffer), format, va);
va_end(va);
if (session->callbacks && session->callbacks->log_function) {
session->callbacks->log_function(session, verbosity, buffer,
session->callbacks->userdata);
if (session->options->log_function) {
session->options->log_function(buffer, session, verbosity);
} else if (verbosity == SSH_LOG_FUNCTIONS) {
if (session->log_indent > 255) {
min = 255;

View File

@@ -3,7 +3,7 @@
*
* This file is part of the SSH Library
*
* Copyright (c) 2003-2009 by Aris Adamantiadis
* Copyright (c) 2003-2005 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
@@ -41,59 +41,68 @@
#include "libssh/libssh.h"
#include "libssh/priv.h"
#include "libssh/server.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
static ssh_message message_new(ssh_session session){
ssh_message msg = malloc(sizeof(struct ssh_message_struct));
static SSH_MESSAGE *message_new(SSH_SESSION *session){
SSH_MESSAGE *msg = session->ssh_message;
if (msg == NULL) {
return NULL;
msg = malloc(sizeof(SSH_MESSAGE));
if (msg == NULL) {
return NULL;
}
session->ssh_message = msg;
}
ZERO_STRUCTP(msg);
memset(msg, 0, sizeof(*msg));
msg->session = session;
return msg;
}
static ssh_message handle_service_request(ssh_session session) {
ssh_string service = NULL;
static int handle_service_request(SSH_SESSION *session) {
STRING *service = NULL;
char *service_c = NULL;
ssh_message msg=NULL;
int rc = -1;
enter_function();
service = buffer_get_ssh_string(session->in_buffer);
if (service == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_SERVICE_REQUEST packet");
goto error;
leave_function();
return -1;
}
service_c = string_to_char(service);
if (service_c == NULL) {
goto error;
}
ssh_log(session, SSH_LOG_PACKET,
"Received a SERVICE_REQUEST for service %s", service_c);
msg=message_new(session);
if(!msg){
SAFE_FREE(service_c);
"Sending a SERVICE_ACCEPT for service %s", service_c);
SAFE_FREE(service_c);
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {
goto error;
}
msg->type=SSH_REQUEST_SERVICE;
msg->service_request.service=service_c;
error:
if (buffer_add_ssh_string(session->out_buffer, service) < 0) {
goto error;
}
if (packet_send(session) != SSH_OK) {
goto error;
}
rc = 0;
error:
string_free(service);
leave_function();
return msg;
return rc;
}
static int handle_unimplemented(ssh_session session) {
static int handle_unimplemented(SSH_SESSION *session) {
if (buffer_add_u32(session->out_buffer, htonl(session->recv_seq - 1)) < 0) {
return -1;
}
@@ -105,14 +114,13 @@ static int handle_unimplemented(ssh_session session) {
return 0;
}
static ssh_message handle_userauth_request(ssh_session session){
ssh_string user = NULL;
ssh_string service = NULL;
ssh_string method = NULL;
ssh_message msg = NULL;
static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){
STRING *user = NULL;
STRING *service = NULL;
STRING *method = NULL;
SSH_MESSAGE *msg = NULL;
char *service_c = NULL;
char *method_c = NULL;
uint32_t method_size = 0;
enter_function();
@@ -134,13 +142,12 @@ static ssh_message handle_userauth_request(ssh_session session){
goto error;
}
msg->type = SSH_REQUEST_AUTH;
msg->type = SSH_AUTH_REQUEST;
msg->auth_request.username = string_to_char(user);
if (msg->auth_request.username == NULL) {
goto error;
}
string_free(user);
user = NULL;
service_c = string_to_char(service);
if (service_c == NULL) {
@@ -150,33 +157,29 @@ static ssh_message handle_userauth_request(ssh_session session){
if (method_c == NULL) {
goto error;
}
method_size = string_len(method);
string_free(service);
service = NULL;
string_free(method);
method = NULL;
ssh_log(session, SSH_LOG_PACKET,
"Auth request for service %s, method %s for user '%s'",
service_c, method_c,
msg->auth_request.username);
SAFE_FREE(service_c);
if (strncmp(method_c, "none", method_size) == 0) {
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
SAFE_FREE(service_c);
if (strcmp(method_c, "none") == 0) {
msg->auth_request.method = SSH_AUTH_NONE;
SAFE_FREE(method_c);
leave_function();
return msg;
}
if (strncmp(method_c, "password", method_size) == 0) {
ssh_string pass = NULL;
uint8_t tmp;
if (strcmp(method_c, "password") == 0) {
STRING *pass = NULL;
u8 tmp;
msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD;
SAFE_FREE(service_c);
msg->auth_request.method = SSH_AUTH_PASSWORD;
SAFE_FREE(method_c);
buffer_get_u8(session->in_buffer, &tmp);
pass = buffer_get_ssh_string(session->in_buffer);
@@ -184,9 +187,7 @@ static ssh_message handle_userauth_request(ssh_session session){
goto error;
}
msg->auth_request.password = string_to_char(pass);
string_burn(pass);
string_free(pass);
pass = NULL;
if (msg->auth_request.password == NULL) {
goto error;
}
@@ -194,83 +195,7 @@ static ssh_message handle_userauth_request(ssh_session session){
return msg;
}
if (strncmp(method_c, "publickey", method_size) == 0) {
ssh_string algo = NULL;
ssh_string publickey = NULL;
uint8_t has_sign;
msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY;
SAFE_FREE(method_c);
buffer_get_u8(session->in_buffer, &has_sign);
algo = buffer_get_ssh_string(session->in_buffer);
if (algo == NULL) {
goto error;
}
publickey = buffer_get_ssh_string(session->in_buffer);
if (publickey == NULL) {
string_free(algo);
algo = NULL;
goto error;
}
msg->auth_request.public_key = publickey_from_string(session, publickey);
string_free(algo);
algo = NULL;
string_free(publickey);
publickey = NULL;
if (msg->auth_request.public_key == NULL) {
goto error;
}
msg->auth_request.signature_state = 0;
// has a valid signature ?
if(has_sign) {
SIGNATURE *signature = NULL;
ssh_public_key public_key = msg->auth_request.public_key;
ssh_string sign = NULL;
ssh_buffer digest = NULL;
sign = buffer_get_ssh_string(session->in_buffer);
if(sign == NULL) {
ssh_log(session, SSH_LOG_PACKET, "Invalid signature packet from peer");
msg->auth_request.signature_state = -2;
goto error;
}
signature = signature_from_string(session, sign, public_key,
public_key->type);
digest = ssh_userauth_build_digest(session, msg, service_c);
if ((digest == NULL || signature == NULL) ||
(digest != NULL && signature != NULL &&
sig_verify(session, public_key, signature,
buffer_get(digest), buffer_get_len(digest)) < 0)) {
ssh_log(session, SSH_LOG_PACKET, "Invalid signature from peer");
string_free(sign);
sign = NULL;
buffer_free(digest);
digest = NULL;
signature_free(signature);
signature = NULL;
msg->auth_request.signature_state = -1;
goto error;
}
else
ssh_log(session, SSH_LOG_PACKET, "Valid signature received");
buffer_free(digest);
digest = NULL;
string_free(sign);
sign = NULL;
signature_free(signature);
signature = NULL;
msg->auth_request.signature_state = 1;
}
SAFE_FREE(service_c);
leave_function();
return msg;
}
msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN;
msg->auth_request.method = SSH_AUTH_UNKNOWN;
SAFE_FREE(method_c);
leave_function();
@@ -289,36 +214,137 @@ error:
return NULL;
}
static ssh_message handle_channel_request_open(ssh_session session) {
ssh_message msg = NULL;
ssh_string type = NULL, originator = NULL, destination = NULL;
char *ssh_message_auth_user(SSH_MESSAGE *msg) {
if (msg == NULL) {
return NULL;
}
return msg->auth_request.username;
}
char *ssh_message_auth_password(SSH_MESSAGE *msg){
if (msg == NULL) {
return NULL;
}
return msg->auth_request.password;
}
int ssh_message_auth_set_methods(SSH_MESSAGE *msg, int methods) {
if (msg == NULL || msg->session == NULL) {
return -1;
}
msg->session->auth_methods = methods;
return 0;
}
static int ssh_message_auth_reply_default(SSH_MESSAGE *msg,int partial) {
SSH_SESSION *session = msg->session;
char methods_c[128] = {0};
STRING *methods = NULL;
int rc = SSH_ERROR;
enter_function();
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_FAILURE) < 0) {
return rc;
}
if (session->auth_methods == 0) {
session->auth_methods = SSH_AUTH_PUBLICKEY | SSH_AUTH_PASSWORD;
}
if (session->auth_methods & SSH_AUTH_PUBLICKEY) {
strcat(methods_c, "publickey,");
}
if (session->auth_methods & SSH_AUTH_KEYBINT) {
strcat(methods_c, "keyboard-interactive,");
}
if (session->auth_methods & SSH_AUTH_PASSWORD) {
strcat(methods_c, "password,");
}
if (session->auth_methods & SSH_AUTH_HOSTBASED) {
strcat(methods_c, "hostbased,");
}
/* Strip the comma. */
methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at
ssh_log(session, SSH_LOG_PACKET,
"Sending a auth failure. methods that can continue: %s", methods_c);
methods = string_from_char(methods_c);
if (methods == NULL) {
goto error;
}
if (buffer_add_ssh_string(msg->session->out_buffer, methods) < 0) {
goto error;
}
if (partial) {
if (buffer_add_u8(session->out_buffer, 1) < 0) {
goto error;
}
} else {
if (buffer_add_u8(session->out_buffer, 0) < 0) {
goto error;
}
}
rc = packet_send(msg->session);
error:
string_free(methods);
leave_function();
return rc;
}
int ssh_message_auth_reply_success(SSH_MESSAGE *msg, int partial) {
if (msg == NULL) {
return SSH_ERROR;
}
if (partial) {
return ssh_message_auth_reply_default(msg, partial);
}
if (buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session) {
SSH_MESSAGE *msg = NULL;
STRING *type = NULL;
char *type_c = NULL;
uint32_t sender, window, packet, originator_port, destination_port;
u32 sender, window, packet;
enter_function();
msg = message_new(session);
if (msg == NULL) {
ssh_set_error_oom(session);
leave_function();
return NULL;
}
msg->type = SSH_REQUEST_CHANNEL_OPEN;
msg->type = SSH_CHANNEL_REQUEST_OPEN;
type = buffer_get_ssh_string(session->in_buffer);
if (type == NULL) {
ssh_set_error_oom(session);
goto error;
}
type_c = string_to_char(type);
if (type_c == NULL) {
ssh_set_error_oom(session);
goto error;
}
ssh_log(session, SSH_LOG_PACKET,
"Clients wants to open a %s channel", type_c);
string_free(type);
buffer_get_u32(session->in_buffer, &sender);
buffer_get_u32(session->in_buffer, &window);
@@ -330,118 +356,12 @@ static ssh_message handle_channel_request_open(ssh_session session) {
if (strcmp(type_c,"session") == 0) {
msg->channel_request_open.type = SSH_CHANNEL_SESSION;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
}
if (strcmp(type_c,"direct-tcpip") == 0) {
destination = buffer_get_ssh_string(session->in_buffer);
if (destination == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.destination = string_to_char(type);
if (msg->channel_request_open.destination == NULL) {
ssh_set_error_oom(session);
string_free(destination);
goto error;
}
string_free(destination);
buffer_get_u32(session->in_buffer, &destination_port);
msg->channel_request_open.destination_port = ntohl(destination_port);
originator = buffer_get_ssh_string(session->in_buffer);
if (originator == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
string_free(originator);
goto error;
}
string_free(originator);
buffer_get_u32(session->in_buffer, &originator_port);
msg->channel_request_open.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_DIRECT_TCPIP;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
}
if (strcmp(type_c,"forwarded-tcpip") == 0) {
destination = buffer_get_ssh_string(session->in_buffer);
if (destination == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.destination = string_to_char(type);
if (msg->channel_request_open.destination == NULL) {
ssh_set_error_oom(session);
string_free(destination);
goto error;
}
string_free(destination);
buffer_get_u32(session->in_buffer, &destination_port);
msg->channel_request_open.destination_port = ntohl(destination_port);
originator = buffer_get_ssh_string(session->in_buffer);
if (originator == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
string_free(originator);
goto error;
}
string_free(originator);
buffer_get_u32(session->in_buffer, &originator_port);
msg->channel_request_open.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_FORWARDED_TCPIP;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
}
if (strcmp(type_c,"x11") == 0) {
originator = buffer_get_ssh_string(session->in_buffer);
if (originator == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
string_free(originator);
goto error;
}
string_free(originator);
buffer_get_u32(session->in_buffer, &originator_port);
msg->channel_request_open.originator_port = ntohl(originator_port);
msg->channel_request_open.type = SSH_CHANNEL_X11;
string_free(type);
SAFE_FREE(type_c);
leave_function();
return msg;
}
msg->channel_request_open.type = SSH_CHANNEL_UNKNOWN;
string_free(type);
SAFE_FREE(type_c);
leave_function();
@@ -455,9 +375,9 @@ error:
return NULL;
}
ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg) {
ssh_session session = msg->session;
ssh_channel chan = NULL;
CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg) {
SSH_SESSION *session = msg->session;
CHANNEL *chan = NULL;
enter_function();
@@ -512,18 +432,46 @@ error:
return NULL;
}
static ssh_message handle_channel_request(ssh_session session) {
ssh_message msg = NULL;
ssh_string type = NULL;
static int ssh_message_channel_request_open_reply_default(SSH_MESSAGE *msg) {
ssh_log(msg->session, SSH_LOG_FUNCTIONS, "Refusing a channel");
if (buffer_add_u8(msg->session->out_buffer
, SSH2_MSG_CHANNEL_OPEN_FAILURE) < 0) {
goto error;
}
if (buffer_add_u32(msg->session->out_buffer,
htonl(msg->channel_request_open.sender)) < 0) {
goto error;
}
if (buffer_add_u32(msg->session->out_buffer,
htonl(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) < 0) {
goto error;
}
/* reason is an empty string */
if (buffer_add_u32(msg->session->out_buffer, 0) < 0) {
goto error;
}
/* language too */
if (buffer_add_u32(msg->session->out_buffer, 0) < 0) {
goto error;
}
return packet_send(msg->session);
error:
return SSH_ERROR;
}
static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session) {
SSH_MESSAGE *msg = NULL;
STRING *type = NULL;
char *type_c = NULL;
uint32_t channel;
uint8_t want_reply;
u32 channel;
u8 want_reply;
enter_function();
msg = message_new(session);
if (msg == NULL) {
ssh_set_error_oom(session);
return NULL;
}
@@ -532,12 +480,10 @@ static ssh_message handle_channel_request(ssh_session session) {
type = buffer_get_ssh_string(session->in_buffer);
if (type == NULL) {
ssh_set_error_oom(session);
goto error;
}
type_c = string_to_char(type);
if (type_c == NULL) {
ssh_set_error_oom(session);
goto error;
}
string_free(type);
@@ -548,28 +494,21 @@ static ssh_message handle_channel_request(ssh_session session) {
"Received a %s channel_request for channel %d (want_reply=%hhd)",
type_c, channel, want_reply);
msg->type = SSH_REQUEST_CHANNEL;
msg->type = SSH_CHANNEL_REQUEST;
msg->channel_request.channel = ssh_channel_from_local(session, channel);
if (msg->channel_request.channel == NULL) {
ssh_set_error(session, SSH_FATAL, "There are no channels with the id %u.",
channel);
goto error;
}
msg->channel_request.want_reply = want_reply;
if (strcmp(type_c, "pty-req") == 0) {
ssh_string term = NULL;
STRING *term = NULL;
char *term_c = NULL;
SAFE_FREE(type_c);
term = buffer_get_ssh_string(session->in_buffer);
if (term == NULL) {
ssh_set_error_oom(session);
goto error;
}
term_c = string_to_char(term);
if (term_c == NULL) {
ssh_set_error_oom(session);
string_free(term);
goto error;
}
@@ -597,39 +536,18 @@ static ssh_message handle_channel_request(ssh_session session) {
return msg;
}
if (strcmp(type_c, "window-change") == 0) {
SAFE_FREE(type_c);
msg->channel_request.type = SSH_CHANNEL_REQUEST_WINDOW_CHANGE;
buffer_get_u32(session->in_buffer, &msg->channel_request.width);
buffer_get_u32(session->in_buffer, &msg->channel_request.height);
buffer_get_u32(session->in_buffer, &msg->channel_request.pxwidth);
buffer_get_u32(session->in_buffer, &msg->channel_request.pxheight);
msg->channel_request.width = ntohl(msg->channel_request.width);
msg->channel_request.height = ntohl(msg->channel_request.height);
msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth);
msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight);
leave_function();
return msg;
}
if (strcmp(type_c, "subsystem") == 0) {
ssh_string subsys = NULL;
STRING *subsys = NULL;
char *subsys_c = NULL;
SAFE_FREE(type_c);
subsys = buffer_get_ssh_string(session->in_buffer);
if (subsys == NULL) {
ssh_set_error_oom(session);
goto error;
}
subsys_c = string_to_char(subsys);
if (subsys_c == NULL) {
ssh_set_error_oom(session);
string_free(subsys);
goto error;
}
@@ -649,15 +567,13 @@ static ssh_message handle_channel_request(ssh_session session) {
leave_function();
return msg;
}
if (strcmp(type_c, "exec") == 0) {
ssh_string cmd = NULL;
STRING *cmd = NULL;
SAFE_FREE(type_c);
cmd = buffer_get_ssh_string(session->in_buffer);
if (cmd == NULL) {
ssh_set_error_oom(session);
goto error;
}
@@ -673,40 +589,6 @@ static ssh_message handle_channel_request(ssh_session session) {
return msg;
}
if (strcmp(type_c, "env") == 0) {
ssh_string name = NULL;
ssh_string value = NULL;
SAFE_FREE(type_c);
name = buffer_get_ssh_string(session->in_buffer);
if (name == NULL) {
ssh_set_error_oom(session);
goto error;
}
value = buffer_get_ssh_string(session->in_buffer);
if (value == NULL) {
ssh_set_error_oom(session);
string_free(name);
goto error;
}
msg->channel_request.type = SSH_CHANNEL_REQUEST_ENV;
msg->channel_request.var_name = string_to_char(name);
msg->channel_request.var_value = string_to_char(value);
if (msg->channel_request.var_name == NULL ||
msg->channel_request.var_value == NULL) {
string_free(name);
string_free(value);
goto error;
}
string_free(name);
string_free(value);
leave_function();
return msg;
}
msg->channel_request.type = SSH_CHANNEL_UNKNOWN;
SAFE_FREE(type_c);
@@ -721,8 +603,12 @@ error:
return NULL;
}
int ssh_message_channel_request_reply_success(ssh_message msg) {
uint32_t channel;
char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg){
return msg->channel_request.subsystem;
}
int ssh_message_channel_request_reply_success(SSH_MESSAGE *msg) {
u32 channel;
if (msg == NULL) {
return SSH_ERROR;
@@ -750,51 +636,80 @@ int ssh_message_channel_request_reply_success(ssh_message msg) {
return SSH_OK;
}
ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype){
ssh_message msg=NULL;
enter_function();
switch(packettype) {
case SSH2_MSG_SERVICE_REQUEST:
msg=handle_service_request(session);
break;
case SSH2_MSG_USERAUTH_REQUEST:
msg = handle_userauth_request(session);
break;
case SSH2_MSG_CHANNEL_OPEN:
msg = handle_channel_request_open(session);
break;
case SSH2_MSG_CHANNEL_REQUEST:
msg = handle_channel_request(session);
break;
default:
if (handle_unimplemented(session) == 0) {
ssh_set_error(session, SSH_FATAL,
"Unhandled message %d\n", session->in_packet.type);
}
static int ssh_message_channel_request_reply_default(SSH_MESSAGE *msg) {
u32 channel;
if (msg->channel_request.want_reply) {
channel = msg->channel_request.channel->remote_channel;
ssh_log(msg->session, SSH_LOG_PACKET,
"Sending a default channel_request denied to channel %d", channel);
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_CHANNEL_FAILURE) < 0) {
return SSH_ERROR;
}
if (buffer_add_u32(msg->session->out_buffer, htonl(channel)) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
leave_function();
return msg;
ssh_log(msg->session, SSH_LOG_PACKET,
"The client doesn't want to know the request failed!");
return SSH_OK;
}
/* \brief blocking message retrieval
* \bug does anything that is not a message, like a channel read/write
*/
ssh_message ssh_message_get(ssh_session session) {
ssh_message msg = NULL;
SSH_MESSAGE *ssh_message_get(SSH_SESSION *session) {
SSH_MESSAGE *msg = NULL;
enter_function();
do {
if ((packet_read(session) != SSH_OK) ||
(packet_translate(session) != SSH_OK)) {
leave_function();
return NULL;
goto error;
}
} while(session->in_packet.type==SSH2_MSG_IGNORE || session->in_packet.type==SSH2_MSG_DEBUG);
msg=ssh_message_retrieve(session,session->in_packet.type);
switch(session->in_packet.type) {
case SSH2_MSG_SERVICE_REQUEST:
if (handle_service_request(session) < 0) {
goto error;
}
break;
case SSH2_MSG_IGNORE:
case SSH2_MSG_DEBUG:
break;
case SSH2_MSG_USERAUTH_REQUEST:
msg = handle_userauth_request(session);
leave_function();
return msg;
case SSH2_MSG_CHANNEL_OPEN:
msg = handle_channel_request_open(session);
leave_function();
return msg;
case SSH2_MSG_CHANNEL_REQUEST:
msg = handle_channel_request(session);
leave_function();
return msg;
default:
if (handle_unimplemented(session) == 0) {
ssh_set_error(session, SSH_FATAL,
"Unhandled message %d\n", session->in_packet.type);
}
goto error;
}
} while(1);
error:
leave_function();
return msg;
return NULL;
}
int ssh_message_type(ssh_message msg) {
int ssh_message_type(SSH_MESSAGE *msg) {
if (msg == NULL) {
return -1;
}
@@ -802,43 +717,64 @@ int ssh_message_type(ssh_message msg) {
return msg->type;
}
int ssh_message_subtype(ssh_message msg) {
int ssh_message_subtype(SSH_MESSAGE *msg) {
if (msg == NULL) {
return -1;
}
switch(msg->type) {
case SSH_REQUEST_AUTH:
case SSH_AUTH_REQUEST:
return msg->auth_request.method;
case SSH_REQUEST_CHANNEL_OPEN:
case SSH_CHANNEL_REQUEST_OPEN:
return msg->channel_request_open.type;
case SSH_REQUEST_CHANNEL:
case SSH_CHANNEL_REQUEST:
return msg->channel_request.type;
}
return -1;
}
void ssh_message_free(ssh_message msg){
int ssh_message_reply_default(SSH_MESSAGE *msg) {
if (msg == NULL) {
return -1;
}
switch(msg->type) {
case SSH_AUTH_REQUEST:
return ssh_message_auth_reply_default(msg, 0);
case SSH_CHANNEL_REQUEST_OPEN:
return ssh_message_channel_request_open_reply_default(msg);
case SSH_CHANNEL_REQUEST:
return ssh_message_channel_request_reply_default(msg);
default:
ssh_log(msg->session, SSH_LOG_PACKET,
"Don't know what to default reply to %d type",
msg->type);
break;
}
return -1;
}
void ssh_message_free(SSH_MESSAGE *msg){
if (msg == NULL) {
return;
}
switch(msg->type) {
case SSH_REQUEST_AUTH:
case SSH_AUTH_REQUEST:
SAFE_FREE(msg->auth_request.username);
if (msg->auth_request.password) {
memset(msg->auth_request.password, 0,
strlen(msg->auth_request.password));
SAFE_FREE(msg->auth_request.password);
}
publickey_free(msg->auth_request.public_key);
break;
case SSH_REQUEST_CHANNEL_OPEN:
case SSH_CHANNEL_REQUEST_OPEN:
SAFE_FREE(msg->channel_request_open.originator);
SAFE_FREE(msg->channel_request_open.destination);
break;
case SSH_REQUEST_CHANNEL:
case SSH_CHANNEL_REQUEST:
SAFE_FREE(msg->channel_request.TERM);
SAFE_FREE(msg->channel_request.modes);
SAFE_FREE(msg->channel_request.var_name);
@@ -846,31 +782,12 @@ void ssh_message_free(ssh_message msg){
SAFE_FREE(msg->channel_request.command);
SAFE_FREE(msg->channel_request.subsystem);
break;
case SSH_REQUEST_SERVICE:
SAFE_FREE(msg->service_request.service);
break;
}
ZERO_STRUCTP(msg);
SAFE_FREE(msg);
}
/** \internal
* \brief handle various SSH request messages and stack them for callback
* \param session SSH session
* \param type packet type
* \returns nothing
*/
void message_handle(ssh_session session, uint32_t type){
ssh_message msg=ssh_message_retrieve(session,type);
ssh_log(session,SSH_LOG_PROTOCOL,"Stacking message from packet type %d",type);
if(msg){
if(!session->ssh_message_list){
session->ssh_message_list=ssh_list_new();
}
ssh_list_append(session->ssh_message_list,msg);
}
}
/**
* @}
*/

View File

@@ -3,7 +3,7 @@
*
* This file is part of the SSH Library
*
* Copyright (c) 2003-2009 by Aris Adamantiadis
* Copyright (c) 2003 by Aris Adamantiadis
* Copyright (c) 2008-2009 by Andreas Schneider <mail@cynapses.org>
*
* The SSH Library is free software; you can redistribute it and/or modify
@@ -22,32 +22,25 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "config.h"
#ifdef _WIN32
#define _WIN32_IE 0x0501 //SHGetSpecialFolderPath
#include <winsock2.h> // Must be the first to include
#include <ws2tcpip.h>
#define _WIN32_IE 0x0400 //SHGetSpecialFolderPath
#include <shlobj.h>
#include <direct.h>
#include <winsock2.h>
#else
/* This is needed for a standard getpwuid_r on opensolaris */
#define _POSIX_PTHREAD_SEMANTICS
#include <pwd.h>
#include <arpa/inet.h>
#endif
#include "libssh/priv.h"
#include "libssh/misc.h"
#include "libssh/session.h"
#ifdef HAVE_LIBGCRYPT
#define GCRYPT_STRING "/gnutls"
@@ -74,69 +67,34 @@
* @{ */
#ifdef _WIN32
char *ssh_get_user_home_dir(void) {
char tmp[MAX_PATH] = {0};
char *szPath = NULL;
static char szPath[MAX_PATH] = {0};
if (SHGetSpecialFolderPathA(NULL, tmp, CSIDL_PROFILE, TRUE)) {
szPath = malloc(strlen(tmp) + 1);
if (szPath == NULL) {
return NULL;
}
strcpy(szPath, tmp);
if (SHGetSpecialFolderPathA(NULL, szPath, CSIDL_PROFILE, TRUE)) {
return szPath;
}
return NULL;
}
/* we have read access on file */
int ssh_file_readaccess_ok(const char *file) {
if (_access(file, 4) < 0) {
return 0;
}
return 1;
}
#define SSH_USEC_IN_SEC 1000000LL
#define SSH_SECONDS_SINCE_1601 11644473600LL
int gettimeofday(struct timeval *__p, void *__t) {
union {
unsigned long long ns100; /* time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} now;
GetSystemTimeAsFileTime (&now.ft);
__p->tv_usec = (long) ((now.ns100 / 10LL) % SSH_USEC_IN_SEC);
__p->tv_sec = (long)(((now.ns100 / 10LL ) / SSH_USEC_IN_SEC) - SSH_SECONDS_SINCE_1601);
return (0);
}
#else /* _WIN32 */
#ifndef NSS_BUFLEN_PASSWD
#define NSS_BUFLEN_PASSWD 4096
#endif
char *ssh_get_user_home_dir(void) {
char *szPath = NULL;
struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
int rc;
static char szPath[PATH_MAX] = {0};
struct passwd *pwd = NULL;
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) {
pwd = getpwuid(getuid());
if (pwd == NULL) {
return NULL;
}
szPath = strdup(pwd.pw_dir);
snprintf(szPath, PATH_MAX - 1, "%s", pwd->pw_dir);
return szPath;
}
#endif
/* we have read access on file */
int ssh_file_readaccess_ok(const char *file) {
if (access(file, R_OK) < 0) {
@@ -145,81 +103,20 @@ int ssh_file_readaccess_ok(const char *file) {
return 1;
}
#endif
char *ssh_hostport(const char *host, int port){
char *dest;
size_t len;
if(host==NULL)
return NULL;
/* 3 for []:, 5 for 65536 and 1 for nul */
len=strlen(host) + 3 + 5 + 1;
dest=malloc(len);
if(dest==NULL)
return NULL;
snprintf(dest,len,"[%s]:%d",host,port);
return dest;
}
uint64_t ntohll(uint64_t a) {
u64 ntohll(u64 a) {
#ifdef WORDS_BIGENDIAN
return a;
#else
uint32_t low = (uint32_t)(a & 0xffffffff);
uint32_t high = (uint32_t)(a >> 32);
u32 low = a & 0xffffffff;
u32 high = a >> 32 ;
low = ntohl(low);
high = ntohl(high);
return ((((uint64_t) low) << 32) | ( high));
return ((((u64) low) << 32) | ( high));
#endif
}
#ifdef _WIN32
char *ssh_get_local_username(ssh_session session) {
DWORD size = 0;
char *user;
/* get the size */
GetUserName(NULL, &size);
user = malloc(size);
if (user == NULL) {
ssh_set_error_oom(session);
return NULL;
}
if (GetUserName(user, &size)) {
return user;
}
return NULL;
}
#else
char *ssh_get_local_username(ssh_session session) {
struct passwd pwd;
struct passwd *pwdbuf;
char buf[NSS_BUFLEN_PASSWD];
char *name;
int rc;
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Couldn't retrieve information for current user!");
return NULL;
}
name = strdup(pwd.pw_name);
if (name == NULL) {
ssh_set_error_oom(session);
return NULL;
}
return name;
}
#endif
/**
* @brief Check if libssh is the required version or get the version
* string.
@@ -252,397 +149,5 @@ const char *ssh_version(int req_version) {
return NULL;
}
struct ssh_list *ssh_list_new(){
struct ssh_list *ret=malloc(sizeof(struct ssh_list));
if(!ret)
return NULL;
ret->root=ret->end=NULL;
return ret;
}
void ssh_list_free(struct ssh_list *list){
struct ssh_iterator *ptr,*next;
ptr=list->root;
while(ptr){
next=ptr->next;
SAFE_FREE(ptr);
ptr=next;
}
SAFE_FREE(list);
}
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list){
return list->root;
}
static struct ssh_iterator *ssh_iterator_new(const void *data){
struct ssh_iterator *iterator=malloc(sizeof(struct ssh_iterator));
if(!iterator)
return NULL;
iterator->next=NULL;
iterator->data=data;
return iterator;
}
int ssh_list_append(struct ssh_list *list,const void *data){
struct ssh_iterator *iterator=ssh_iterator_new(data);
if(!iterator)
return SSH_ERROR;
if(!list->end){
/* list is empty */
list->root=list->end=iterator;
} else {
/* put it on end of list */
list->end->next=iterator;
list->end=iterator;
}
return SSH_OK;
}
int ssh_list_prepend(struct ssh_list *list, const void *data){
struct ssh_iterator *it = ssh_iterator_new(data);
if (it == NULL) {
return SSH_ERROR;
}
if (list->end == NULL) {
/* list is empty */
list->root = list->end = it;
} else {
/* set as new root */
it->next = list->root;
list->root = it;
}
return SSH_OK;
}
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
struct ssh_iterator *ptr,*prev;
prev=NULL;
ptr=list->root;
while(ptr && ptr != iterator){
prev=ptr;
ptr=ptr->next;
}
if(!ptr){
/* we did not find the element */
return;
}
/* unlink it */
if(prev)
prev->next=ptr->next;
/* if iterator was the head */
if(list->root == iterator)
list->root=iterator->next;
/* if iterator was the tail */
if(list->end == iterator)
list->end = prev;
SAFE_FREE(iterator);
}
/** @internal
* @brief Removes the top element of the list and returns the data value attached
* to it
* @param list the ssh_list
* @returns pointer to the element being stored in head, or
* NULL if the list is empty.
*/
const void *_ssh_list_pop_head(struct ssh_list *list){
struct ssh_iterator *iterator=list->root;
const void *data;
if(!list->root)
return NULL;
data=iterator->data;
list->root=iterator->next;
if(list->end==iterator)
list->end=NULL;
SAFE_FREE(iterator);
return data;
}
/**
* @brief Parse directory component.
*
* dirname breaks a null-terminated pathname string into a directory component.
* In the usual case, ssh_dirname() returns the string up to, but not including,
* the final '/'. Trailing '/' characters are not counted as part of the
* pathname. The caller must free the memory.
*
* @param path The path to parse.
*
* @return The dirname of path or NULL if we can't allocate memory. If path
* does not contain a slash, c_dirname() returns the string ".". If
* path is the string "/", it returns the string "/". If path is
* NULL or an empty string, "." is returned.
*/
char *ssh_dirname (const char *path) {
char *new = NULL;
unsigned int len;
if (path == NULL || *path == '\0') {
return strdup(".");
}
len = strlen(path);
/* Remove trailing slashes */
while(len > 0 && path[len - 1] == '/') --len;
/* We have only slashes */
if (len == 0) {
return strdup("/");
}
/* goto next slash */
while(len > 0 && path[len - 1] != '/') --len;
if (len == 0) {
return strdup(".");
} else if (len == 1) {
return strdup("/");
}
/* Remove slashes again */
while(len > 0 && path[len - 1] == '/') --len;
new = malloc(len + 1);
if (new == NULL) {
return NULL;
}
strncpy(new, path, len);
new[len] = '\0';
return new;
}
/**
* @brief basename - parse filename component.
*
* basename breaks a null-terminated pathname string into a filename component.
* ssh_basename() returns the component following the final '/'. Trailing '/'
* characters are not counted as part of the pathname.
*
* @param path The path to parse.
*
* @return The filename of path or NULL if we can't allocate memory. If path
* is a the string "/", basename returns the string "/". If path is
* NULL or an empty string, "." is returned.
*/
char *ssh_basename (const char *path) {
char *new = NULL;
const char *s;
unsigned int len;
if (path == NULL || *path == '\0') {
return strdup(".");
}
len = strlen(path);
/* Remove trailing slashes */
while(len > 0 && path[len - 1] == '/') --len;
/* We have only slashes */
if (len == 0) {
return strdup("/");
}
while(len > 0 && path[len - 1] != '/') --len;
if (len > 0) {
s = path + len;
len = strlen(s);
while(len > 0 && s[len - 1] == '/') --len;
} else {
return strdup(path);
}
new = malloc(len + 1);
if (new == NULL) {
return NULL;
}
strncpy(new, s, len);
new[len] = '\0';
return new;
}
/**
* @brief Attempts to create a directory with the given pathname.
*
* This is the portable version of mkdir, mode is ignored on Windows systems.
*
* @param pathname The path name to create the directory.
*
* @param mode The permissions to use.
*
* @return 0 on success, < 0 on error with errno set.
*/
int ssh_mkdir(const char *pathname, mode_t mode) {
int r;
#ifdef _WIN32
r = _mkdir(pathname);
#else
r = mkdir(pathname, mode);
#endif
return r;
}
/**
* @brief Expand a directory starting with a tilde '~'
*
* @param[in] session The ssh session to use.
*
* @param[in] d The directory to expand.
*
* @return The expanded directory, NULL on error.
*/
char *ssh_path_expand_tilde(const char *d) {
char *h, *r;
const char *p;
size_t ld;
size_t lh = 0;
if (d[0] != '~') {
return strdup(d);
}
d++;
/* handle ~user/path */
p = strchr(d, '/');
if (p != NULL && p > d) {
#ifdef _WIN32
return strdup(d);
#else
struct passwd *pw;
size_t s = p - d;
char u[128];
if (s > sizeof(u)) {
return NULL;
}
memcpy(u, d, s);
u[s] = '\0';
pw = getpwnam(u);
if (pw == NULL) {
return NULL;
}
ld = strlen(p);
h = strdup(pw->pw_dir);
#endif
} else {
ld = strlen(d);
p = (char *) d;
h = ssh_get_user_home_dir();
}
if (h == NULL) {
return NULL;
}
lh = strlen(h);
r = malloc(ld + lh + 1);
if (r == NULL) {
return NULL;
}
if (lh > 0) {
memcpy(r, h, lh);
}
memcpy(r + lh, p, ld + 1);
return r;
}
char *ssh_path_expand_escape(ssh_session session, const char *s) {
#define MAX_BUF_SIZE 4096
char host[NI_MAXHOST];
char buf[MAX_BUF_SIZE];
char *r, *x = NULL;
const char *p;
size_t i, l;
if (strlen(s) > MAX_BUF_SIZE) {
ssh_set_error(session, SSH_FATAL, "string to expand too long");
return NULL;
}
r = ssh_path_expand_tilde(s);
if (r == NULL) {
ssh_set_error_oom(session);
return NULL;
}
p = r;
buf[0] = '\0';
for (i = 0; *p != '\0'; p++) {
if (*p != '%') {
buf[i] = *p;
i++;
if (i > MAX_BUF_SIZE) {
return NULL;
}
buf[i] = '\0';
continue;
}
p++;
if (*p == '\0') {
break;
}
switch (*p) {
case 'd':
x = strdup(session->sshdir);
break;
case 'u':
x = ssh_get_local_username(session);
break;
case 'l':
if (gethostname(host, sizeof(host) == 0)) {
x = strdup(host);
}
break;
case 'h':
x = strdup(session->host);
break;
case 'r':
x = strdup(session->username);
break;
default:
ssh_set_error(session, SSH_FATAL,
"Wrong escape sequence detected");
return NULL;
}
if (x == NULL) {
ssh_set_error_oom(session);
return NULL;
}
i += strlen(x);
if (i > MAX_BUF_SIZE) {
ssh_set_error(session, SSH_FATAL,
"String too long");
return NULL;
}
l = strlen(buf);
strcat(buf + l, x);
buf[i] = '\0';
SAFE_FREE(x);
}
free(r);
return strdup(buf);
#undef MAX_BUF_SIZE
}
/* @} */
/* vim: set ts=4 sw=4 et cindent: */
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

File diff suppressed because it is too large Load Diff

View File

@@ -21,10 +21,9 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
@@ -32,17 +31,11 @@
#include <arpa/inet.h>
#endif
#include "config.h"
#include "libssh/priv.h"
#include "libssh/ssh2.h"
#include "libssh/ssh1.h"
#include "libssh/crypto.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/socket.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#include "libssh/messages.h"
#include "libssh/pcap.h"
/* XXX include selected mac size */
static int macsize=SHA_DIGEST_LEN;
@@ -55,7 +48,7 @@ static int macsize=SHA_DIGEST_LEN;
#define PACKET_STATE_INIT 0
#define PACKET_STATE_SIZEREAD 1
static int packet_read2(ssh_session session) {
static int packet_read2(SSH_SESSION *session) {
unsigned int blocksize = (session->current_crypto ?
session->current_crypto->in_cipher->blocksize : 8);
int current_macsize = session->current_crypto ? macsize : 0;
@@ -65,8 +58,8 @@ static int packet_read2(ssh_session session) {
int to_be_read;
int rc = SSH_ERROR;
uint32_t len;
uint8_t padding;
u32 len;
u8 padding;
enter_function();
@@ -110,7 +103,7 @@ static int packet_read2(ssh_session session) {
goto error;
}
to_be_read = len - blocksize + sizeof(uint32_t);
to_be_read = len - blocksize + sizeof(u32);
if (to_be_read < 0) {
/* remote sshd sends invalid sizes? */
ssh_set_error(session, SSH_FATAL,
@@ -123,7 +116,7 @@ static int packet_read2(ssh_session session) {
session->packet_state = PACKET_STATE_SIZEREAD;
case PACKET_STATE_SIZEREAD:
len = session->in_packet.len;
to_be_read = len - blocksize + sizeof(uint32_t) + current_macsize;
to_be_read = len - blocksize + sizeof(u32) + current_macsize;
/* if to_be_read is zero, the whole packet was blocksize bytes. */
if (to_be_read != 0) {
rc = ssh_socket_wait_for_data(session->socket,session,to_be_read);
@@ -155,19 +148,11 @@ static int packet_read2(ssh_session session) {
* have been decrypted)
*/
if (packet_decrypt(session,
((uint8_t*)buffer_get(session->in_buffer) + blocksize),
buffer_get(session->in_buffer) + blocksize,
buffer_get_len(session->in_buffer) - blocksize) < 0) {
ssh_set_error(session, SSH_FATAL, "Decrypt error");
goto error;
}
#ifdef WITH_PCAP
if(session->pcap_ctx){
ssh_pcap_context_write(session->pcap_ctx,
SSH_PCAP_DIR_IN, buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer),
buffer_get_len(session->in_buffer));
}
#endif
ssh_socket_read(session->socket, mac, macsize);
if (packet_hmac_verify(session, session->in_buffer, mac) < 0) {
@@ -175,19 +160,8 @@ static int packet_read2(ssh_session session) {
goto error;
}
}
#ifdef WITH_PCAP
else {
/* No crypto */
if(session->pcap_ctx){
ssh_pcap_context_write(session->pcap_ctx,
SSH_PCAP_DIR_IN, buffer_get(session->in_buffer),
buffer_get_len(session->in_buffer),
buffer_get_len(session->in_buffer));
}
}
#endif
buffer_pass_bytes(session->in_buffer, sizeof(uint32_t));
buffer_pass_bytes(session->in_buffer, sizeof(u32));
/* pass the size which has been processed before */
if (buffer_get_u8(session->in_buffer, &padding) == 0) {
@@ -195,7 +169,7 @@ static int packet_read2(ssh_session session) {
goto error;
}
ssh_log(session, SSH_LOG_PACKET,
ssh_log(session, SSH_LOG_RARE,
"%hhd bytes padding, %d bytes left in buffer",
padding, buffer_get_rest_len(session->in_buffer));
@@ -213,13 +187,13 @@ static int packet_read2(ssh_session session) {
}
buffer_pass_bytes_end(session->in_buffer, padding);
ssh_log(session, SSH_LOG_PACKET,
ssh_log(session, SSH_LOG_RARE,
"After padding, %d bytes left in buffer",
buffer_get_rest_len(session->in_buffer));
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if (session->current_crypto && session->current_crypto->do_compress_in) {
ssh_log(session, SSH_LOG_PACKET, "Decompressing in_buffer ...");
if (decompress_buffer(session, session->in_buffer, MAX_PACKET_LEN) < 0) {
ssh_log(session, SSH_LOG_RARE, "Decompressing in_buffer ...");
if (decompress_buffer(session, session->in_buffer) < 0) {
goto error;
}
}
@@ -240,15 +214,15 @@ error:
return rc;
}
#ifdef WITH_SSH1
#ifdef HAVE_SSH1
/* a slighty modified packet_read2() for SSH-1 protocol */
static int packet_read1(ssh_session session) {
static int packet_read1(SSH_SESSION *session) {
void *packet = NULL;
int rc = SSH_ERROR;
int to_be_read;
uint32_t padding;
uint32_t crc;
uint32_t len;
u32 padding;
u32 crc;
u32 len;
enter_function();
@@ -271,7 +245,7 @@ static int packet_read1(ssh_session session) {
}
}
rc = ssh_socket_read(session->socket, &len, sizeof(uint32_t));
rc = ssh_socket_read(session->socket, &len, sizeof(u32));
if (rc != SSH_OK) {
goto error;
}
@@ -338,29 +312,29 @@ static int packet_read1(ssh_session session) {
#endif
ssh_log(session, SSH_LOG_PACKET, "%d bytes padding", padding);
if(((len + padding) != buffer_get_rest_len(session->in_buffer)) ||
((len + padding) < sizeof(uint32_t))) {
((len + padding) < sizeof(u32))) {
ssh_log(session, SSH_LOG_RARE, "no crc32 in packet");
ssh_set_error(session, SSH_FATAL, "no crc32 in packet");
goto error;
}
memcpy(&crc,
(unsigned char *)buffer_get_rest(session->in_buffer) + (len+padding) - sizeof(uint32_t),
sizeof(uint32_t));
buffer_pass_bytes_end(session->in_buffer, sizeof(uint32_t));
buffer_get_rest(session->in_buffer) + (len+padding) - sizeof(u32),
sizeof(u32));
buffer_pass_bytes_end(session->in_buffer, sizeof(u32));
crc = ntohl(crc);
if (ssh_crc32(buffer_get_rest(session->in_buffer),
(len + padding) - sizeof(uint32_t)) != crc) {
(len + padding) - sizeof(u32)) != crc) {
#ifdef DEBUG_CRYPTO
ssh_print_hexa("crc32 on",buffer_get_rest(session->in_buffer),
len + padding - sizeof(uint32_t));
len + padding - sizeof(u32));
#endif
ssh_log(session, SSH_LOG_RARE, "Invalid crc32");
ssh_set_error(session, SSH_FATAL,
"Invalid crc32: expected %.8x, got %.8x",
crc,
ssh_crc32(buffer_get_rest(session->in_buffer),
len + padding - sizeof(uint32_t)));
len + padding - sizeof(u32)));
goto error;
}
/* pass the padding */
@@ -389,11 +363,11 @@ error:
return rc;
}
#endif /* WITH_SSH1 */
#endif /* HAVE_SSH1 */
/* that's where i'd like C to be object ... */
int packet_read(ssh_session session) {
#ifdef WITH_SSH1
int packet_read(SSH_SESSION *session) {
#ifdef HAVE_SSH1
if (session->version == 1) {
return packet_read1(session);
}
@@ -401,7 +375,7 @@ int packet_read(ssh_session session) {
return packet_read2(session);
}
int packet_translate(ssh_session session) {
int packet_translate(SSH_SESSION *session) {
enter_function();
memset(&session->in_packet, 0, sizeof(PACKET));
@@ -410,7 +384,7 @@ int packet_translate(ssh_session session) {
return SSH_ERROR;
}
ssh_log(session, SSH_LOG_PACKET, "Final size %d",
ssh_log(session, SSH_LOG_RARE, "Final size %d",
buffer_get_rest_len(session->in_buffer));
if(buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) {
@@ -419,7 +393,7 @@ int packet_translate(ssh_session session) {
return SSH_ERROR;
}
ssh_log(session, SSH_LOG_PACKET, "Type %hhd", session->in_packet.type);
ssh_log(session, SSH_LOG_RARE, "Type %hhd", session->in_packet.type);
session->in_packet.valid = 1;
leave_function();
@@ -432,7 +406,7 @@ int packet_translate(ssh_session session) {
* Return SSH_OK if everything has been sent, SSH_AGAIN if there are still
* things to send on buffer, SSH_ERROR if there is an error.
*/
int packet_flush(ssh_session session, int enforce_blocking) {
int packet_flush(SSH_SESSION *session, int enforce_blocking) {
if (enforce_blocking || session->blocking) {
return ssh_socket_blocking_flush(session->socket);
}
@@ -444,7 +418,7 @@ int packet_flush(ssh_session session, int enforce_blocking) {
* This function places the outgoing packet buffer into an outgoing
* socket buffer
*/
static int packet_write(ssh_session session) {
static int packet_write(SSH_SESSION *session) {
int rc = SSH_ERROR;
enter_function();
@@ -459,24 +433,24 @@ static int packet_write(ssh_session session) {
return rc;
}
static int packet_send2(ssh_session session) {
static int packet_send2(SSH_SESSION *session) {
unsigned int blocksize = (session->current_crypto ?
session->current_crypto->out_cipher->blocksize : 8);
uint32_t currentlen = buffer_get_len(session->out_buffer);
u32 currentlen = buffer_get_len(session->out_buffer);
unsigned char *hmac = NULL;
char padstring[32] = {0};
int rc = SSH_ERROR;
uint32_t finallen;
uint8_t padding;
u32 finallen;
u8 padding;
enter_function();
ssh_log(session, SSH_LOG_PACKET,
ssh_log(session, SSH_LOG_RARE,
"Writing on the wire a packet having %u bytes before", currentlen);
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if (session->current_crypto && session->current_crypto->do_compress_out) {
ssh_log(session, SSH_LOG_PACKET, "Compressing in_buffer ...");
ssh_log(session, SSH_LOG_RARE, "Compressing in_buffer ...");
if (compress_buffer(session,session->out_buffer) < 0) {
goto error;
}
@@ -495,26 +469,20 @@ static int packet_send2(ssh_session session) {
}
finallen = htonl(currentlen + padding + 1);
ssh_log(session, SSH_LOG_PACKET,
ssh_log(session, SSH_LOG_RARE,
"%d bytes after comp + %d padding bytes = %lu bytes packet",
currentlen, padding, (long unsigned int) ntohl(finallen));
if (buffer_prepend_data(session->out_buffer, &padding, sizeof(uint8_t)) < 0) {
if (buffer_prepend_data(session->out_buffer, &padding, sizeof(u8)) < 0) {
goto error;
}
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(u32)) < 0) {
goto error;
}
if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
goto error;
}
#ifdef WITH_PCAP
if(session->pcap_ctx){
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,
buffer_get(session->out_buffer),buffer_get_len(session->out_buffer)
,buffer_get_len(session->out_buffer));
}
#endif
hmac = packet_encrypt(session, buffer_get(session->out_buffer),
buffer_get_len(session->out_buffer));
if (hmac) {
@@ -534,16 +502,16 @@ error:
return rc; /* SSH_OK, AGAIN or ERROR */
}
#ifdef WITH_SSH1
static int packet_send1(ssh_session session) {
#ifdef HAVE_SSH1
static int packet_send1(SSH_SESSION *session) {
unsigned int blocksize = (session->current_crypto ?
session->current_crypto->out_cipher->blocksize : 8);
uint32_t currentlen = buffer_get_len(session->out_buffer) + sizeof(uint32_t);
u32 currentlen = buffer_get_len(session->out_buffer) + sizeof(u32);
char padstring[32] = {0};
int rc = SSH_ERROR;
uint32_t finallen;
uint32_t crc;
uint8_t padding;
u32 finallen;
u32 crc;
u8 padding;
enter_function();
ssh_log(session,SSH_LOG_PACKET,"Sending a %d bytes long packet",currentlen);
@@ -573,12 +541,12 @@ static int packet_send1(ssh_session session) {
if (buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) {
goto error;
}
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(u32)) < 0) {
goto error;
}
crc = ssh_crc32((char *)buffer_get(session->out_buffer) + sizeof(uint32_t),
buffer_get_len(session->out_buffer) - sizeof(uint32_t));
crc = ssh_crc32(buffer_get(session->out_buffer) + sizeof(u32),
buffer_get_len(session->out_buffer) - sizeof(u32));
if (buffer_add_u32(session->out_buffer, ntohl(crc)) < 0) {
goto error;
@@ -589,8 +557,8 @@ static int packet_send1(ssh_session session) {
buffer_get_len(session->out_buffer));
#endif
packet_encrypt(session, (unsigned char *)buffer_get(session->out_buffer) + sizeof(uint32_t),
buffer_get_len(session->out_buffer) - sizeof(uint32_t));
packet_encrypt(session, buffer_get(session->out_buffer) + sizeof(u32),
buffer_get_len(session->out_buffer) - sizeof(u32));
#ifdef DEBUG_CRYPTO
ssh_print_hexa("encrypted packet",buffer_get(session->out_buffer),
@@ -612,10 +580,10 @@ error:
return rc; /* SSH_OK, AGAIN or ERROR */
}
#endif /* WITH_SSH1 */
#endif /* HAVE_SSH1 */
int packet_send(ssh_session session) {
#ifdef WITH_SSH1
int packet_send(SSH_SESSION *session) {
#ifdef HAVE_SSH1
if (session->version == 1) {
return packet_send1(session);
}
@@ -623,13 +591,13 @@ int packet_send(ssh_session session) {
return packet_send2(session);
}
void packet_parse(ssh_session session) {
ssh_string error_s = NULL;
void packet_parse(SSH_SESSION *session) {
STRING *error_s = NULL;
char *error = NULL;
uint32_t type = session->in_packet.type;
uint32_t tmp;
int type = session->in_packet.type;
u32 tmp;
#ifdef WITH_SSH1
#ifdef HAVE_SSH1
if (session->version == 1) {
/* SSH-1 */
switch(type) {
@@ -654,7 +622,7 @@ void packet_parse(ssh_session session) {
}
return;
} else {
#endif /* WITH_SSH1 */
#endif /* HAVE_SSH1 */
switch(type) {
case SSH2_MSG_DISCONNECT:
buffer_get_u32(session->in_buffer, &tmp);
@@ -684,28 +652,19 @@ void packet_parse(ssh_session session) {
case SSH2_MSG_CHANNEL_EOF:
case SSH2_MSG_CHANNEL_CLOSE:
channel_handle(session,type);
return;
case SSH2_MSG_IGNORE:
case SSH2_MSG_DEBUG:
return;
case SSH2_MSG_SERVICE_REQUEST:
case SSH2_MSG_USERAUTH_REQUEST:
case SSH2_MSG_CHANNEL_OPEN:
message_handle(session,type);
return;
case SSH2_MSG_GLOBAL_REQUEST:
ssh_global_request_handle(session);
return;
default:
ssh_log(session, SSH_LOG_RARE, "Received unhandled packet %d", type);
}
#ifdef WITH_SSH1
#ifdef HAVE_SSH1
}
#endif
}
#ifdef WITH_SSH1
static int packet_wait1(ssh_session session, int type, int blocking) {
#ifdef HAVE_SSH1
static int packet_wait1(SSH_SESSION *session, int type, int blocking) {
enter_function();
@@ -760,9 +719,9 @@ static int packet_wait1(ssh_session session, int type, int blocking) {
leave_function();
return SSH_OK;
}
#endif /* WITH_SSH1 */
#endif /* HAVE_SSH1 */
static int packet_wait2(ssh_session session, int type, int blocking) {
static int packet_wait2(SSH_SESSION *session, int type, int blocking) {
int rc = SSH_ERROR;
enter_function();
@@ -782,20 +741,15 @@ static int packet_wait2(ssh_session session, int type, int blocking) {
ssh_log(session, SSH_LOG_PACKET, "received disconnect packet");
leave_function();
return SSH_ERROR;
case SSH2_MSG_GLOBAL_REQUEST:
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
case SSH2_MSG_CHANNEL_REQUEST:
case SSH2_MSG_CHANNEL_EOF:
case SSH2_MSG_CHANNEL_CLOSE:
case SSH2_MSG_SERVICE_REQUEST:
case SSH2_MSG_USERAUTH_REQUEST:
case SSH2_MSG_CHANNEL_OPEN:
packet_parse(session);
break;
case SSH2_MSG_IGNORE:
case SSH2_MSG_DEBUG:
break;
default:
if (type && (type != session->in_packet.type)) {
@@ -818,8 +772,8 @@ static int packet_wait2(ssh_session session, int type, int blocking) {
return SSH_OK;
}
int packet_wait(ssh_session session, int type, int block) {
#ifdef WITH_SSH1
int packet_wait(SSH_SESSION *session, int type, int block) {
#ifdef HAVE_SSH1
if (session->version == 1) {
return packet_wait1(session, type, block);
}

View File

@@ -1,388 +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.
*/
/* pcap.c */
/** \defgroup ssh_pcap SSH-pcap
* \brief libssh pcap file generation
*
* \addtogroup ssh_pcap
* @{ */
#include "config.h"
#ifdef WITH_PCAP
#include <stdio.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/time.h>
#include <sys/socket.h>
#endif
#include <errno.h>
#include "libssh/libssh.h"
#include "libssh/pcap.h"
#include "libssh/session.h"
#include "libssh/buffer.h"
#include "libssh/socket.h"
/* The header of a pcap file is the following. We are not going to make it
* very complicated.
* Just for information.
*/
struct pcap_hdr_s {
uint32_t magic_number; /* magic number */
uint16_t version_major; /* major version number */
uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
};
#define PCAP_MAGIC 0xa1b2c3d4
#define PCAP_VERSION_MAJOR 2
#define PCAP_VERSION_MINOR 4
#define DLT_RAW 12 /* raw IP */
/* TCP flags */
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
/* The header of a pcap packet.
* Just for information.
*/
struct pcaprec_hdr_s {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
};
/** @private
* @brief a pcap context expresses the state of a pcap dump
* in a SSH session only. Multiple pcap contexts may be used into
* a single pcap file.
*/
struct ssh_pcap_context_struct {
ssh_session session;
ssh_pcap_file file;
int connected;
/* All of these information are useful to generate
* the dummy IP and TCP packets
*/
uint32_t ipsource;
uint32_t ipdest;
uint16_t portsource;
uint16_t portdest;
uint32_t outsequence;
uint32_t insequence;
};
/** @private
* @brief a pcap file expresses the state of a pcap file which may
* contain several streams.
*/
struct ssh_pcap_file_struct {
FILE *output;
uint16_t ipsequence;
};
/**
* @brief create a new ssh_pcap_file object
*/
ssh_pcap_file ssh_pcap_file_new(){
return malloc(sizeof(struct ssh_pcap_file_struct));
}
/** @internal
* @brief writes a packet on file
*/
static int ssh_pcap_file_write(ssh_pcap_file pcap, ssh_buffer packet){
int err;
uint32_t len;
if(pcap == NULL || pcap->output==NULL)
return SSH_ERROR;
len=buffer_get_len(packet);
err=fwrite(buffer_get(packet),len,1,pcap->output);
if(err<0)
return SSH_ERROR;
else
return SSH_OK;
}
/** @internal
* @brief prepends a packet with the pcap header and writes packet
* on file
*/
int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len){
ssh_buffer header=buffer_new();
struct timeval now;
int err;
if(header == NULL)
return SSH_ERROR;
gettimeofday(&now,NULL);
buffer_add_u32(header,htonl(now.tv_sec));
buffer_add_u32(header,htonl(now.tv_usec));
buffer_add_u32(header,htonl(buffer_get_len(packet)));
buffer_add_u32(header,htonl(original_len));
buffer_add_buffer(header,packet);
err=ssh_pcap_file_write(pcap,header);
buffer_free(header);
return err;
}
/**
* @brief opens a new pcap file and create header
*/
int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename){
ssh_buffer header;
int err;
if(pcap == NULL)
return SSH_ERROR;
if(pcap->output){
fclose(pcap->output);
pcap->output=NULL;
}
pcap->output=fopen(filename,"wb");
if(pcap->output==NULL)
return SSH_ERROR;
header=buffer_new();
if(header==NULL)
return SSH_ERROR;
buffer_add_u32(header,htonl(PCAP_MAGIC));
buffer_add_u16(header,htons(PCAP_VERSION_MAJOR));
buffer_add_u16(header,htons(PCAP_VERSION_MINOR));
/* currently hardcode GMT to 0 */
buffer_add_u32(header,htonl(0));
/* accuracy */
buffer_add_u32(header,htonl(0));
/* size of the biggest packet */
buffer_add_u32(header,htonl(MAX_PACKET_LEN));
/* we will write sort-of IP */
buffer_add_u32(header,htonl(DLT_RAW));
err=ssh_pcap_file_write(pcap,header);
buffer_free(header);
return err;
}
int ssh_pcap_file_close(ssh_pcap_file pcap){
int err;
if(pcap ==NULL || pcap->output==NULL)
return SSH_ERROR;
err=fclose(pcap->output);
pcap->output=NULL;
if(err != 0)
return SSH_ERROR;
else
return SSH_OK;
}
void ssh_pcap_file_free(ssh_pcap_file pcap){
ssh_pcap_file_close(pcap);
SAFE_FREE(pcap);
}
/** @internal
* @brief allocates a new ssh_pcap_context object
*/
ssh_pcap_context ssh_pcap_context_new(ssh_session session){
ssh_pcap_context ctx=malloc(sizeof(struct ssh_pcap_context_struct));
if(ctx==NULL){
ssh_set_error_oom(session);
return NULL;
}
ZERO_STRUCTP(ctx);
ctx->session=session;
return ctx;
}
void ssh_pcap_context_free(ssh_pcap_context ctx){
SAFE_FREE(ctx);
}
void ssh_pcap_context_set_file(ssh_pcap_context ctx, ssh_pcap_file pcap){
ctx->file=pcap;
}
/** @internal
* @brief sets the IP and port parameters in the connection
*/
static int ssh_pcap_context_connect(ssh_pcap_context ctx){
ssh_session session=ctx->session;
struct sockaddr_in local, remote;
socket_t fd;
socklen_t len;
if(session==NULL)
return SSH_ERROR;
if(session->socket==NULL)
return SSH_ERROR;
fd=ssh_socket_get_fd(session->socket);
/* TODO: adapt for windows */
if(fd<0)
return SSH_ERROR;
len=sizeof(local);
if(getsockname(fd,(struct sockaddr *)&local,&len)<0){
ssh_set_error(session,SSH_REQUEST_DENIED,"Getting local IP address: %s",strerror(errno));
return SSH_ERROR;
}
len=sizeof(remote);
if(getpeername(fd,(struct sockaddr *)&remote,&len)<0){
ssh_set_error(session,SSH_REQUEST_DENIED,"Getting remote IP address: %s",strerror(errno));
return SSH_ERROR;
}
if(local.sin_family != AF_INET){
ssh_set_error(session,SSH_REQUEST_DENIED,"Only IPv4 supported for pcap logging");
return SSH_ERROR;
}
memcpy(&ctx->ipsource,&local.sin_addr,sizeof(ctx->ipsource));
memcpy(&ctx->ipdest,&remote.sin_addr,sizeof(ctx->ipdest));
memcpy(&ctx->portsource,&local.sin_port,sizeof(ctx->portsource));
memcpy(&ctx->portdest,&remote.sin_port,sizeof(ctx->portdest));
ctx->connected=1;
return SSH_OK;
}
#define IPHDR_LEN 20
#define TCPHDR_LEN 20
#define TCPIPHDR_LEN (IPHDR_LEN + TCPHDR_LEN)
/** @internal
* @brief write a SSH packet as a TCP over IP in a pcap file
* @param ctx open pcap context
* @param direction SSH_PCAP_DIRECTION_IN if the packet has been received
* @param direction SSH_PCAP_DIRECTION_OUT if the packet has been emitted
* @param data pointer to the data to write
* @param len data to write in the pcap file. May be smaller than origlen.
* @param origlen number of bytes of complete data.
* @returns SSH_OK write is successful
* @returns SSH_ERROR an error happened.
*/
int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction direction
, void *data, uint32_t len, uint32_t origlen){
ssh_buffer ip;
int err;
if(ctx==NULL || ctx->file ==NULL)
return SSH_ERROR;
if(ctx->connected==0)
if(ssh_pcap_context_connect(ctx)==SSH_ERROR)
return SSH_ERROR;
ip=buffer_new();
if(ip==NULL){
ssh_set_error_oom(ctx->session);
return SSH_ERROR;
}
/* build an IP packet */
/* V4, 20 bytes */
buffer_add_u8(ip,4 << 4 | 5);
/* tos */
buffer_add_u8(ip,0);
/* total len */
buffer_add_u16(ip,htons(origlen + TCPIPHDR_LEN));
/* IP id number */
buffer_add_u16(ip,htons(ctx->file->ipsequence));
ctx->file->ipsequence++;
/* fragment offset */
buffer_add_u16(ip,htons(0));
/* TTL */
buffer_add_u8(ip,64);
/* protocol TCP=6 */
buffer_add_u8(ip,6);
/* checksum */
buffer_add_u16(ip,0);
if(direction==SSH_PCAP_DIR_OUT){
buffer_add_u32(ip,ctx->ipsource);
buffer_add_u32(ip,ctx->ipdest);
} else {
buffer_add_u32(ip,ctx->ipdest);
buffer_add_u32(ip,ctx->ipsource);
}
/* TCP */
if(direction==SSH_PCAP_DIR_OUT){
buffer_add_u16(ip,ctx->portsource);
buffer_add_u16(ip,ctx->portdest);
} else {
buffer_add_u16(ip,ctx->portdest);
buffer_add_u16(ip,ctx->portsource);
}
/* sequence number */
if(direction==SSH_PCAP_DIR_OUT){
buffer_add_u32(ip,ntohl(ctx->outsequence));
ctx->outsequence+=origlen;
} else {
buffer_add_u32(ip,ntohl(ctx->insequence));
ctx->insequence+=origlen;
}
/* ack number */
if(direction==SSH_PCAP_DIR_OUT){
buffer_add_u32(ip,ntohl(ctx->insequence));
} else {
buffer_add_u32(ip,ntohl(ctx->outsequence));
}
/* header len = 20 = 5 * 32 bits, at offset 4*/
buffer_add_u8(ip,5 << 4);
/* flags */
buffer_add_u8(ip,TH_PUSH | TH_ACK);
/* window */
buffer_add_u16(ip,htons(65535));
/* checksum */
buffer_add_u16(ip,htons(0));
/* urgent data ptr */
buffer_add_u16(ip,0);
/* actual data */
buffer_add_data(ip,data,len);
err=ssh_pcap_file_write_packet(ctx->file,ip,origlen + TCPIPHDR_LEN);
buffer_free(ip);
return err;
}
/** @brief sets the pcap file used to trace the session
* @param current session
* @param pcap an handler to a pcap file. A pcap file may be used in several
* sessions.
* @returns SSH_ERROR in case of error, SSH_OK otherwise.
*/
int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcap){
ssh_pcap_context ctx=ssh_pcap_context_new(session);
if(ctx==NULL){
ssh_set_error_oom(session);
return SSH_ERROR;
}
ctx->file=pcap;
if(session->pcap_ctx)
ssh_pcap_context_free(session->pcap_ctx);
session->pcap_ctx=ctx;
return SSH_OK;
}
#endif /* WITH_PCAP */
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -3,9 +3,7 @@
*
* This file is part of the SSH Library
*
* Copyright (c) 2009-2010 by Andreas Schneider <mail@cynapses.org>
* Copyright (c) 2003-2009 by Aris Adamantiadis
* Copyright (c) 2009 Aleksandar Kanchev
* 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
@@ -25,565 +23,184 @@
* vim: ts=2 sw=2 et cindent
*/
#include "config.h"
/* This code is based on glib's gpoll */
#include <errno.h>
#include "config.h"
#include "libssh/priv.h"
#include "libssh/libssh.h"
#include "libssh/poll.h"
#ifndef SSH_POLL_CTX_CHUNK
#define SSH_POLL_CTX_CHUNK 5
#endif
struct ssh_poll_handle_struct {
ssh_poll_ctx ctx;
union {
socket_t fd;
size_t idx;
} x;
short events;
ssh_poll_callback cb;
void *cb_data;
};
struct ssh_poll_ctx_struct {
ssh_poll_handle *pollptrs;
ssh_pollfd_t *pollfds;
size_t polls_allocated;
size_t polls_used;
size_t chunk_size;
};
#ifdef HAVE_POLL
#include <poll.h>
void ssh_poll_init(void) {
return;
}
void ssh_poll_cleanup(void) {
return;
}
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
int ssh_poll(pollfd_t *fds, nfds_t nfds, int timeout) {
return poll((struct pollfd *) fds, nfds, timeout);
}
#else /* HAVE_POLL */
typedef int (*poll_fn)(ssh_pollfd_t *, nfds_t, int);
static poll_fn ssh_poll_emu;
#include <sys/types.h>
#ifdef _WIN32
#ifndef STRICT
#define STRICT
#endif /* STRICT */
#include <time.h>
#include <windows.h>
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
#include <winsock2.h>
#if (_WIN32_WINNT < 0x0600)
typedef struct ssh_pollfd_struct WSAPOLLFD;
#endif
typedef int (WSAAPI* WSAPoll_FunctionType)(WSAPOLLFD fdarray[],
ULONG nfds,
INT timeout
);
static WSAPoll_FunctionType wsa_poll;
int win_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
if (wsa_poll) {
return (wsa_poll)(fds, nfds, timeout);
}
return SOCKET_ERROR;
int ssh_poll(pollfd_t *fds, nfds_t nfds, int timeout) {
return WSAPoll(fds, nfds, timeout);
}
#define WS2_LIBRARY "ws2_32.dll"
static HINSTANCE hlib;
#else /* _WIN32_WINNT */
#else /* _WIN32 */
#include <sys/select.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/time.h>
#endif /* _WIN32 */
#ifndef STRICT
#define STRICT
#endif
#include <stdio.h>
#include <windows.h>
/*
* This is a poll(2)-emulation using select for systems not providing a native
* poll implementation.
*
* Keep in mind that select is terribly inefficient. The interface is simply not
* meant to be used with maximum descriptor value greater, say, 32 or so. With
* a value as high as 1024 on Linux you'll pay dearly in every single call.
* poll() will be orders of magnitude faster.
*/
static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
fd_set readfds, writefds, exceptfds;
struct timeval tv, *ptv;
socket_t max_fd;
int rc;
nfds_t i;
static int poll_rest (HANDLE *handles, int nhandles,
pollfd_t *fds, nfds_t nfds, int timeout) {
DWORD ready;
pollfd_t *f;
int recursed_result;
if (nhandles == 0) {
/* No handles to wait for, just the timeout */
if (timeout == INFINITE) {
ready = WAIT_FAILED;
} else {
SleepEx(timeout, 1);
ready = WAIT_TIMEOUT;
}
} else {
/* Wait for just handles */
ready = WaitForMultipleObjectsEx(nhandles, handles, FALSE, timeout, TRUE);
#if 0
if (ready == WAIT_FAILED) {
fprintf(stderr, "WaitForMultipleObjectsEx failed: %d\n", GetLastError());
}
#endif
}
if (ready == WAIT_FAILED) {
return -1;
} else if (ready == WAIT_TIMEOUT || ready == WAIT_IO_COMPLETION) {
return 0;
} else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles) {
for (f = fds; f < &fds[nfds]; f++) {
if ((HANDLE) f->fd == handles[ready - WAIT_OBJECT_0]) {
f->revents = f->events;
}
}
/*
* If no timeout and polling several handles, recurse to poll
* the rest of them.
*/
if (timeout == 0 && nhandles > 1) {
/* Remove the handle that fired */
int i;
if (ready < nhandles - 1) {
for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
handles[i-1] = handles[i];
}
}
nhandles--;
recursed_result = poll_rest(handles, nhandles, fds, nfds, 0);
if (recursed_result < 0) {
return -1;
}
return recursed_result + 1;
}
return 1;
}
return 0;
}
int ssh_poll(pollfd_t *fds, nfds_t nfds, int timeout) {
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
pollfd_t *f;
int nhandles = 0;
int rc = -1;
if (fds == NULL) {
errno = EFAULT;
return -1;
errno = EFAULT;
return -1;
}
FD_ZERO (&readfds);
FD_ZERO (&writefds);
FD_ZERO (&exceptfds);
if (nfds >= MAXIMUM_WAIT_OBJECTS) {
errno = EINVAL;
return -1;
}
/* compute fd_sets and find largest descriptor */
for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
if (fds[i].fd == SSH_INVALID_SOCKET) {
continue;
}
#ifndef _WIN32
if (fds[i].fd >= FD_SETSIZE) {
rc = -1;
for (f = fds; f < &fds[nfds]; f++) {
if (f->fd > 0) {
int i;
/*
* Don't add the same handle several times into the array, as
* docs say that is not allowed, even if it actually does seem
* to work.
*/
for (i = 0; i < nhandles; i++) {
if (handles[i] == (HANDLE) f->fd) {
break;
}
#endif
if (fds[i].events & (POLLIN | POLLRDNORM)) {
FD_SET (fds[i].fd, &readfds);
}
if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
FD_SET (fds[i].fd, &writefds);
}
if (fds[i].events & (POLLPRI | POLLRDBAND)) {
FD_SET (fds[i].fd, &exceptfds);
}
if (fds[i].fd > max_fd &&
(fds[i].events & (POLLIN | POLLOUT | POLLPRI |
POLLRDNORM | POLLRDBAND |
POLLWRNORM | POLLWRBAND))) {
max_fd = fds[i].fd;
rc = 0;
}
}
if (max_fd == SSH_INVALID_SOCKET || rc == -1) {
errno = EINVAL;
return -1;
}
if (timeout < 0) {
ptv = NULL;
} else {
ptv = &tv;
if (timeout == 0) {
tv.tv_sec = 0;
tv.tv_usec = 0;
} else {
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
}
}
rc = select (max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
if (rc < 0) {
return -1;
}
for (rc = 0, i = 0; i < nfds; i++)
if (fds[i].fd >= 0) {
fds[i].revents = 0;
if (FD_ISSET(fds[i].fd, &readfds)) {
int save_errno = errno;
char data[64] = {0};
int ret;
/* support for POLLHUP */
ret = recv(fds[i].fd, data, 64, MSG_PEEK);
#ifdef _WIN32
if ((ret == -1) &&
(errno == WSAESHUTDOWN || errno == WSAECONNRESET ||
errno == WSAECONNABORTED || errno == WSAENETRESET)) {
#else
if ((ret == -1) &&
(errno == ESHUTDOWN || errno == ECONNRESET ||
errno == ECONNABORTED || errno == ENETRESET)) {
#endif
fds[i].revents |= POLLHUP;
} else {
fds[i].revents |= fds[i].events & (POLLIN | POLLRDNORM);
}
errno = save_errno;
}
if (FD_ISSET(fds[i].fd, &writefds)) {
fds[i].revents |= fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND);
}
}
if (FD_ISSET(fds[i].fd, &exceptfds)) {
fds[i].revents |= fds[i].events & (POLLPRI | POLLRDBAND);
if (i == nhandles) {
if (nhandles == MAXIMUM_WAIT_OBJECTS) {
break;
} else {
handles[nhandles++] = (HANDLE) f->fd;
}
if (fds[i].revents & ~POLLHUP) {
rc++;
}
} else {
fds[i].revents = POLLNVAL;
}
}
}
if (timeout == -1) {
timeout = INFINITE;
}
if (nhandles > 1) {
/*
* First check if one or several of them are immediately
* available.
*/
rc = poll_rest(handles, nhandles, fds, nfds, 0);
/*
* If not, and we have a significant timeout, poll again with
* timeout then. Note that this will return indication for only
* one event, or only for messages. We ignore timeouts less than
* ten milliseconds as they are mostly pointless on Windows, the
* MsgWaitForMultipleObjectsEx() call will timeout right away
* anyway.
*/
if (rc == 0 && (timeout == INFINITE || timeout >= 10)) {
rc = poll_rest(handles, nhandles, fds, nfds, timeout);
}
} else {
/*
* Just polling for one thing, so no need to check first if
* available immediately
*/
rc = poll_rest(handles, nhandles, fds, nfds, timeout);
}
if (rc < 0) {
for (f = fds; f < &fds[nfds]; f++) {
f->revents = 0;
}
errno = EBADF;
}
return rc;
}
void ssh_poll_init(void) {
ssh_poll_emu = bsd_poll;
#endif /* _WIN32_WINNT */
#ifdef _WIN32
hlib = LoadLibrary(WS2_LIBRARY);
if (hlib != NULL) {
wsa_poll = (WSAPoll_FunctionType) (void *) GetProcAddress(hlib, "WSAPoll");
}
#endif /* _WIN32 */
if (wsa_poll != NULL) {
ssh_poll_emu = bsd_poll;
}
}
void ssh_poll_cleanup(void) {
ssh_poll_emu = bsd_poll;
#ifdef _WIN32
wsa_poll = NULL;
FreeLibrary(hlib);
hlib = NULL;
#endif /* _WIN32 */
}
int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
return (ssh_poll_emu)(fds, nfds, timeout);
}
#endif /* HAVE_POLL */
/**
* @brief Allocate a new poll object, which could be used within a poll context.
*
* @param fd Socket that will be polled.
* @param events Poll events that will be monitored for the socket. i.e.
* POLLIN, POLLPRI, POLLOUT, POLLERR, POLLHUP, POLLNVAL
* @param cb Function to be called if any of the events are set.
* @param userdata Userdata to be passed to the callback function. NULL if
* not needed.
*
* @return A new poll object, NULL on error
*/
ssh_poll_handle ssh_poll_new(socket_t fd, short events, ssh_poll_callback cb,
void *userdata) {
ssh_poll_handle p;
p = malloc(sizeof(struct ssh_poll_handle_struct));
if (p != NULL) {
p->ctx = NULL;
p->x.fd = fd;
p->events = events;
p->cb = cb;
p->cb_data = userdata;
}
return p;
}
/**
* @brief Free a poll object.
*
* @param p Pointer to an already allocated poll object.
*/
void ssh_poll_free(ssh_poll_handle p) {
SAFE_FREE(p);
}
/**
* @brief Get the poll context of a poll object.
*
* @param p Pointer to an already allocated poll object.
*
* @return Poll context or NULL if the poll object isn't attached.
*/
ssh_poll_ctx ssh_poll_get_ctx(ssh_poll_handle p) {
return p->ctx;
}
/**
* @brief Get the events of a poll object.
*
* @param p Pointer to an already allocated poll object.
*
* @return Poll events.
*/
short ssh_poll_get_events(ssh_poll_handle p) {
return p->events;
}
/**
* @brief Set the events of a poll object. The events will also be propagated
* to an associated poll context.
*
* @param p Pointer to an already allocated poll object.
* @param events Poll events.
*/
void ssh_poll_set_events(ssh_poll_handle p, short events) {
p->events = events;
if (p->ctx != NULL) {
p->ctx->pollfds[p->x.idx].events = events;
}
}
/**
* @brief Add extra events to a poll object. Duplicates are ignored.
* The events will also be propagated to an associated poll context.
*
* @param p Pointer to an already allocated poll object.
* @param events Poll events.
*/
void ssh_poll_add_events(ssh_poll_handle p, short events) {
ssh_poll_set_events(p, ssh_poll_get_events(p) | events);
}
/**
* @brief Remove events from a poll object. Non-existent are ignored.
* The events will also be propagated to an associated poll context.
*
* @param p Pointer to an already allocated poll object.
* @param events Poll events.
*/
void ssh_poll_remove_events(ssh_poll_handle p, short events) {
ssh_poll_set_events(p, ssh_poll_get_events(p) & ~events);
}
/**
* @brief Get the raw socket of a poll object.
*
* @param p Pointer to an already allocated poll object.
*
* @return Raw socket.
*/
socket_t ssh_poll_get_fd(ssh_poll_handle p) {
if (p->ctx != NULL) {
return p->ctx->pollfds[p->x.idx].fd;
}
return p->x.fd;
}
/**
* @brief Set the callback of a poll object.
*
* @param p Pointer to an already allocated poll object.
* @param cb Function to be called if any of the events are set.
* @param userdata Userdata to be passed to the callback function. NULL if
* not needed.
*/
void ssh_poll_set_callback(ssh_poll_handle p, ssh_poll_callback cb, void *userdata) {
if (cb != NULL) {
p->cb = cb;
p->cb_data = userdata;
}
}
/**
* @brief Create a new poll context. It could be associated with many poll object
* which are going to be polled at the same time as the poll context. You
* would need a single poll context per thread.
*
* @param chunk_size The size of the memory chunk that will be allocated, when
* more memory is needed. This is for efficiency reasons,
* i.e. don't allocate memory for each new poll object, but
* for the next 5. Set it to 0 if you want to use the
* library's default value.
*/
ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size) {
ssh_poll_ctx ctx;
ctx = malloc(sizeof(struct ssh_poll_ctx_struct));
if (ctx != NULL) {
if (!chunk_size) {
chunk_size = SSH_POLL_CTX_CHUNK;
}
ctx->chunk_size = chunk_size;
ctx->pollptrs = NULL;
ctx->pollfds = NULL;
ctx->polls_allocated = 0;
ctx->polls_used = 0;
}
return ctx;
}
/**
* @brief Free a poll context.
*
* @param ctx Pointer to an already allocated poll context.
*/
void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
if (ctx->polls_allocated > 0) {
register size_t i, used;
used = ctx->polls_used;
for (i = 0; i < used; ) {
ssh_poll_handle p = ctx->pollptrs[i];
socket_t fd = ctx->pollfds[i].fd;
/* force poll object removal */
if (p->cb(p, fd, POLLERR, p->cb_data) < 0) {
used = ctx->polls_used;
} else {
i++;
}
}
SAFE_FREE(ctx->pollptrs);
SAFE_FREE(ctx->pollfds);
}
SAFE_FREE(ctx);
}
static int ssh_poll_ctx_resize(ssh_poll_ctx ctx, size_t new_size) {
ssh_poll_handle *pollptrs;
ssh_pollfd_t *pollfds;
pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle *) * new_size);
if (pollptrs == NULL) {
return -1;
}
pollfds = realloc(ctx->pollfds, sizeof(ssh_pollfd_t) * new_size);
if (pollfds == NULL) {
ctx->pollptrs = realloc(pollptrs, sizeof(ssh_poll_handle *) * ctx->polls_allocated);
return -1;
}
ctx->pollptrs = pollptrs;
ctx->pollfds = pollfds;
ctx->polls_allocated = new_size;
return 0;
}
/**
* @brief Add a poll object to a poll context.
*
* @param ctx Pointer to an already allocated poll context.
* @param p Pointer to an already allocated poll object.
*
* @return 0 on success, < 0 on error
*/
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) {
socket_t fd;
if (p->ctx != NULL) {
/* already attached to a context */
return -1;
}
if (ctx->polls_used == ctx->polls_allocated &&
ssh_poll_ctx_resize(ctx, ctx->polls_allocated + ctx->chunk_size) < 0) {
return -1;
}
fd = p->x.fd;
p->x.idx = ctx->polls_used++;
ctx->pollptrs[p->x.idx] = p;
ctx->pollfds[p->x.idx].fd = fd;
ctx->pollfds[p->x.idx].events = p->events;
ctx->pollfds[p->x.idx].revents = 0;
p->ctx = ctx;
return 0;
}
/**
* @brief Remove a poll object from a poll context.
*
* @param ctx Pointer to an already allocated poll context.
* @param p Pointer to an already allocated poll object.
*/
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) {
size_t i;
i = p->x.idx;
p->x.fd = ctx->pollfds[i].fd;
p->ctx = NULL;
ctx->polls_used--;
/* fill the empty poll slot with the last one */
if (ctx->polls_used > 0 && ctx->polls_used != i) {
ctx->pollfds[i] = ctx->pollfds[ctx->polls_used];
ctx->pollptrs[i] = ctx->pollptrs[ctx->polls_used];
}
/* this will always leave at least chunk_size polls allocated */
if (ctx->polls_allocated - ctx->polls_used > ctx->chunk_size) {
ssh_poll_ctx_resize(ctx, ctx->polls_allocated - ctx->chunk_size);
}
}
/**
* @brief Poll all the sockets associated through a poll object with a
* poll context. If any of the events are set after the poll, the
* call back function of the socket will be called.
* This function should be called once within the programs main loop.
*
* @param ctx Pointer to an already allocated poll context.
* @param timeout An upper limit on the time for which ssh_poll_ctx() will
* block, in milliseconds. Specifying a negative value
* means an infinite timeout. This parameter is passed to
* the poll() function.
*/
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
int rc;
if (!ctx->polls_used)
return 0;
rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout);
if (rc > 0) {
register size_t i, used;
used = ctx->polls_used;
for (i = 0; i < used && rc > 0; ) {
if (!ctx->pollfds[i].revents) {
i++;
} else {
ssh_poll_handle p = ctx->pollptrs[i];
socket_t fd = ctx->pollfds[i].fd;
int revents = ctx->pollfds[i].revents;
if (p->cb(p, fd, revents, p->cb_data) < 0) {
/* the poll was removed, reload the used counter and stall the loop */
used = ctx->polls_used;
} else {
ctx->pollfds[i].revents = 0;
i++;
}
rc--;
}
}
}
return rc;
}

View File

@@ -1,631 +0,0 @@
/*
* scp - SSH scp wrapper functions
*
* This file is part of the SSH Library
*
* Copyright (c) 2009 by 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.
*/
#include <stdio.h>
#include <string.h>
#include "libssh/priv.h"
#include "libssh/scp.h"
/** @defgroup ssh_scp SSH-scp
* @brief SCP protocol over SSH functions
* @addtogroup ssh_scp
* @{
*/
/** @brief Creates a new scp session
* @param session the SSH session to use
* @param mode one of SSH_SCP_WRITE or SSH_SCP_READ, depending if you need to drop files remotely or read them.
* It is not possible to combine read and write.
* @param location The directory in which write or read will be done. Any push or pull will be relative
* to this place
* @returns NULL if the creation was impossible.
* @returns a ssh_scp handle if it worked.
*/
ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location){
ssh_scp scp=malloc(sizeof(struct ssh_scp_struct));
if(scp == NULL){
ssh_set_error(session,SSH_FATAL,"Error allocating memory for ssh_scp");
return NULL;
}
ZERO_STRUCTP(scp);
if((mode&~SSH_SCP_RECURSIVE) != SSH_SCP_WRITE && (mode &~SSH_SCP_RECURSIVE) != SSH_SCP_READ){
ssh_set_error(session,SSH_FATAL,"Invalid mode %d for ssh_scp_new()",mode);
ssh_scp_free(scp);
return NULL;
}
scp->location=strdup(location);
if (scp->location == NULL) {
ssh_set_error(session,SSH_FATAL,"Error allocating memory for ssh_scp");
ssh_scp_free(scp);
return NULL;
}
scp->session=session;
scp->mode=mode & ~SSH_SCP_RECURSIVE;
scp->recursive = (mode & SSH_SCP_RECURSIVE) != 0;
scp->channel=NULL;
scp->state=SSH_SCP_NEW;
return scp;
}
int ssh_scp_init(ssh_scp scp){
int r;
char execbuffer[1024];
uint8_t code;
if(scp->state != SSH_SCP_NEW){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_init called under invalid state");
return SSH_ERROR;
}
ssh_log(scp->session,SSH_LOG_PROTOCOL,"Initializing scp session %s %son location '%s'",
scp->mode==SSH_SCP_WRITE?"write":"read",
scp->recursive?"recursive ":"",
scp->location);
scp->channel=channel_new(scp->session);
if(scp->channel == NULL){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
r= channel_open_session(scp->channel);
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
if(scp->mode == SSH_SCP_WRITE)
snprintf(execbuffer,sizeof(execbuffer),"scp -t %s %s",
scp->recursive ? "-r":"", scp->location);
else
snprintf(execbuffer,sizeof(execbuffer),"scp -f %s %s",
scp->recursive ? "-r":"", scp->location);
if(channel_request_exec(scp->channel,execbuffer) == SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
if(scp->mode == SSH_SCP_WRITE){
r=channel_read(scp->channel,&code,1,0);
if(code != 0){
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
} else {
channel_write(scp->channel,"",1);
}
if(scp->mode == SSH_SCP_WRITE)
scp->state=SSH_SCP_WRITE_INITED;
else
scp->state=SSH_SCP_READ_INITED;
return SSH_OK;
}
int ssh_scp_close(ssh_scp scp){
char buffer[128];
int err;
if(scp->channel != NULL){
if(channel_send_eof(scp->channel) == SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
/* avoid situations where data are buffered and
* not yet stored on disk. This can happen if the close is sent
* before we got the EOF back
*/
while(!channel_is_eof(scp->channel)){
err=channel_read(scp->channel,buffer,sizeof(buffer),0);
if(err==SSH_ERROR)
break;
}
if(channel_close(scp->channel) == SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
channel_free(scp->channel);
scp->channel=NULL;
}
scp->state=SSH_SCP_NEW;
return SSH_OK;
}
void ssh_scp_free(ssh_scp scp){
if(scp->state != SSH_SCP_NEW)
ssh_scp_close(scp);
if(scp->channel)
channel_free(scp->channel);
SAFE_FREE(scp->location);
SAFE_FREE(scp->request_name);
SAFE_FREE(scp->warning);
SAFE_FREE(scp);
}
/** @brief creates a directory in a scp in sink mode
* @param scp the scp handle.
* @param dirname Name of the directory being created.
* @param mode Unix permissions for the new directory, e.g. 0755.
* @returns SSH_OK if the directory was created.
* @returns SSH_ERROR if an error happened.
* @see ssh_scp_leave_directory
*/
int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode){
char buffer[1024];
int r;
uint8_t code;
char *dir;
char *perms;
if(scp->state != SSH_SCP_WRITE_INITED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_directory called under invalid state");
return SSH_ERROR;
}
dir=ssh_basename(dirname);
perms=ssh_scp_string_mode(mode);
snprintf(buffer, sizeof(buffer), "D%s 0 %s\n", perms, dir);
SAFE_FREE(dir);
SAFE_FREE(perms);
r=channel_write(scp->channel,buffer,strlen(buffer));
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
r=channel_read(scp->channel,&code,1,0);
if(code != 0){
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
return SSH_OK;
}
/**
* @brief Leaves a directory
* @returns SSH_OK if the directory was created.
* @returns SSH_ERROR if an error happened.
* @see ssh_scp_push_directory
*/
int ssh_scp_leave_directory(ssh_scp scp){
char buffer[]="E\n";
int r;
uint8_t code;
if(scp->state != SSH_SCP_WRITE_INITED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_leave_directory called under invalid state");
return SSH_ERROR;
}
r=channel_write(scp->channel,buffer,strlen(buffer));
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
r=channel_read(scp->channel,&code,1,0);
if(code != 0){
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
return SSH_OK;
}
/** @brief initializes the sending of a file to a scp in sink mode
* @param scp the scp handle.
* @param filename Name of the file being sent. It should not contain any path indicator
* @param size Exact size in bytes of the file being sent.
* @param mode Unix permissions for the new file, e.g. 0644
* @returns SSH_OK if the file is ready to be sent.
* @returns SSH_ERROR if an error happened.
*/
int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode){
char buffer[1024];
int r;
uint8_t code;
char *file;
char *perms;
if(scp->state != SSH_SCP_WRITE_INITED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_file called under invalid state");
return SSH_ERROR;
}
file=ssh_basename(filename);
perms=ssh_scp_string_mode(mode);
ssh_log(scp->session,SSH_LOG_PROTOCOL,"SCP pushing file %s, size %" PRIdS " with permissions '%s'",file,size,perms);
snprintf(buffer, sizeof(buffer), "C%s %" PRIdS " %s\n", perms, size, file);
SAFE_FREE(file);
SAFE_FREE(perms);
r=channel_write(scp->channel,buffer,strlen(buffer));
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
r=channel_read(scp->channel,&code,1,0);
if(code != 0){
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
scp->filelen = size;
scp->processed = 0;
scp->state=SSH_SCP_WRITE_WRITING;
return SSH_OK;
}
/** @brief waits for a response of the scp server
* @internal
* @param response pointer where the response message must be
* copied if any. This pointer must then be free'd.
* @returns the return code.
* @returns SSH_ERROR a error occured
*/
int ssh_scp_response(ssh_scp scp, char **response){
unsigned char code;
int r;
char msg[128];
r=channel_read(scp->channel,&code,1,0);
if(r == SSH_ERROR)
return SSH_ERROR;
if(code == 0)
return 0;
if(code > 2){
ssh_set_error(scp->session,SSH_FATAL, "SCP: invalid status code %ud received", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
r=ssh_scp_read_string(scp,msg,sizeof(msg));
if(r==SSH_ERROR)
return r;
/* Warning */
if(code == 1){
ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Warning: status code 1 received: %s", msg);
ssh_log(scp->session,SSH_LOG_RARE,"SCP: Warning: status code 1 received: %s", msg);
if(response)
*response=strdup(msg);
return 1;
}
if(code == 2){
ssh_set_error(scp->session,SSH_FATAL, "SCP: Error: status code 2 received: %s", msg);
if(response)
*response=strdup(msg);
return 2;
}
/* Not reached */
return SSH_ERROR;
}
/** @brief Write into a remote scp file
* @param scp the scp handle.
* @param buffer the buffer to write
* @param len the number of bytes to write
* @returns SSH_OK the write was successful
* @returns SSH_ERROR an error happened while writing
*/
int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
int w;
//int r;
//uint8_t code;
if(scp->state != SSH_SCP_WRITE_WRITING){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_write called under invalid state");
return SSH_ERROR;
}
if(scp->processed + len > scp->filelen)
len = scp->filelen - scp->processed;
/* hack to avoid waiting for window change */
channel_poll(scp->channel,0);
w=channel_write(scp->channel,buffer,len);
if(w != SSH_ERROR)
scp->processed += w;
else {
scp->state=SSH_SCP_ERROR;
//return=channel_get_exit_status(scp->channel);
return SSH_ERROR;
}
/* Check if we arrived at end of file */
if(scp->processed == scp->filelen) {
/* r=channel_read(scp->channel,&code,1,0);
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
if(code != 0){
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
*/
scp->processed=scp->filelen=0;
scp->state=SSH_SCP_WRITE_INITED;
}
return SSH_OK;
}
/**
* @brief reads a string on a channel, terminated by '\n'
* @param scp the scp handle.
* @param buffer pointer to a buffer to place the string
* @param len size of the buffer in bytes. If the string is bigger
* than len-1, only len-1 bytes are read and the string
* is null-terminated.
* @returns SSH_OK The string was read
* @returns SSH_ERROR Error happened while reading
*/
int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){
size_t r=0;
int err=SSH_OK;
while(r<len-1){
err=channel_read(scp->channel,&buffer[r],1,0);
if(err==SSH_ERROR){
break;
}
if(err==0){
ssh_set_error(scp->session,SSH_FATAL,"End of file while reading string");
err=SSH_ERROR;
break;
}
r++;
if(buffer[r-1] == '\n')
break;
}
buffer[r]=0;
return err;
}
/** @brief waits for a scp request (file, directory)
* @returns SSH_ERROR Some error happened
* @returns SSH_SCP_REQUEST_NEWFILE The other side is sending a file
* @returns SSH_SCP_REQUEST_NEWDIRECTORY The other side is sending a directory
* @returns SSH_SCP_REQUEST_END_DIRECTORY The other side has finished with the current directory
* @see ssh_scp_read
* @see ssh_scp_deny_request
* @see ssh_scp_accept_request
*/
int ssh_scp_pull_request(ssh_scp scp){
char buffer[4096];
char *mode=NULL;
char *p,*tmp;
size_t size;
char *name=NULL;
int err;
if(scp->state != SSH_SCP_READ_INITED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_pull_request called under invalid state");
return SSH_ERROR;
}
err=ssh_scp_read_string(scp,buffer,sizeof(buffer));
if(err==SSH_ERROR){
if(channel_is_eof(scp->channel)){
scp->state=SSH_SCP_TERMINATED;
return SSH_SCP_REQUEST_EOF;
}
return err;
}
p=strchr(buffer,'\n');
if(p!=NULL)
*p='\0';
ssh_log(scp->session,SSH_LOG_PROTOCOL,"Received SCP request: '%s'",buffer);
switch(buffer[0]){
case 'C':
/* File */
case 'D':
/* Directory */
p=strchr(buffer,' ');
if(p==NULL)
goto error;
*p='\0';
p++;
//mode=strdup(&buffer[1]);
scp->request_mode=ssh_scp_integer_mode(&buffer[1]);
tmp=p;
p=strchr(p,' ');
if(p==NULL)
goto error;
*p=0;
size=strtoull(tmp,NULL,10);
p++;
name=strdup(p);
SAFE_FREE(scp->request_name);
scp->request_name=name;
if(buffer[0]=='C'){
scp->filelen=size;
scp->request_type=SSH_SCP_REQUEST_NEWFILE;
} else {
scp->filelen='0';
scp->request_type=SSH_SCP_REQUEST_NEWDIR;
}
scp->state=SSH_SCP_READ_REQUESTED;
scp->processed = 0;
return scp->request_type;
break;
case 'E':
scp->request_type=SSH_SCP_REQUEST_ENDDIR;
channel_write(scp->channel,"",1);
return scp->request_type;
case 0x1:
ssh_set_error(scp->session,SSH_REQUEST_DENIED,"SCP: Warning: %s",&buffer[1]);
scp->request_type=SSH_SCP_REQUEST_WARNING;
SAFE_FREE(scp->warning);
scp->warning=strdup(&buffer[1]);
return scp->request_type;
case 0x2:
ssh_set_error(scp->session,SSH_FATAL,"SCP: Error: %s",&buffer[1]);
return SSH_ERROR;
case 'T':
/* Timestamp */
default:
ssh_set_error(scp->session,SSH_FATAL,"Unhandled message: (%d)%s",buffer[0],buffer);
return SSH_ERROR;
}
/* a parsing error occured */
error:
SAFE_FREE(name);
SAFE_FREE(mode);
ssh_set_error(scp->session,SSH_FATAL,"Parsing error while parsing message: %s",buffer);
return SSH_ERROR;
}
/**
* @brief denies the transfer of a file or creation of a directory
* coming from the remote party
* @param scp the scp handle.
* @param reason nul-terminated string with a human-readable explanation
* of the deny
* @returns SSH_OK the message was sent
* @returns SSH_ERROR Error sending the message, or sending it in a bad state
*/
int ssh_scp_deny_request(ssh_scp scp, const char *reason){
char buffer[4096];
int err;
if(scp->state != SSH_SCP_READ_REQUESTED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_deny_request called under invalid state");
return SSH_ERROR;
}
snprintf(buffer,sizeof(buffer),"%c%s\n",2,reason);
err=channel_write(scp->channel,buffer,strlen(buffer));
if(err==SSH_ERROR) {
return SSH_ERROR;
}
else {
scp->state=SSH_SCP_READ_INITED;
return SSH_OK;
}
}
/**
* @brief accepts transfer of a file or creation of a directory
* coming from the remote party
* @param scp the scp handle.
* @returns SSH_OK the message was sent
* @returns SSH_ERROR Error sending the message, or sending it in a bad state
*/
int ssh_scp_accept_request(ssh_scp scp){
char buffer[]={0x00};
int err;
if(scp->state != SSH_SCP_READ_REQUESTED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_deny_request called under invalid state");
return SSH_ERROR;
}
err=channel_write(scp->channel,buffer,1);
if(err==SSH_ERROR) {
return SSH_ERROR;
}
if(scp->request_type==SSH_SCP_REQUEST_NEWFILE)
scp->state=SSH_SCP_READ_READING;
else
scp->state=SSH_SCP_READ_INITED;
return SSH_OK;
}
/** @brief Read from a remote scp file
* @param scp the scp handle.
* @param buffer Destination buffer
* @param size Size of the buffer
* @returns Number of bytes read
* @returns SSH_ERROR An error happened while reading
*/
int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){
int r;
int code;
if(scp->state == SSH_SCP_READ_REQUESTED && scp->request_type == SSH_SCP_REQUEST_NEWFILE){
r=ssh_scp_accept_request(scp);
if(r==SSH_ERROR)
return r;
}
if(scp->state != SSH_SCP_READ_READING){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_read called under invalid state");
return SSH_ERROR;
}
if(scp->processed + size > scp->filelen)
size = scp->filelen - scp->processed;
if(size > 65536)
size=65536; /* avoid too large reads */
r=channel_read(scp->channel,buffer,size,0);
if(r != SSH_ERROR)
scp->processed += r;
else {
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
/* Check if we arrived at end of file */
if(scp->processed == scp->filelen) {
scp->processed=scp->filelen=0;
channel_write(scp->channel,"",1);
code=ssh_scp_response(scp,NULL);
if(code == 0){
scp->state=SSH_SCP_READ_INITED;
return r;
}
if(code==1){
scp->state=SSH_SCP_READ_INITED;
return SSH_ERROR;
}
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
return r;
}
/** @brief Gets the name of the directory or file being
* pushed from the other party
* @returns file name. Should not be freed.
*/
const char *ssh_scp_request_get_filename(ssh_scp scp){
return scp->request_name;
}
/**@brief Gets the permissions of the directory or file being
* pushed from the other party
* @returns Unix permission, e.g 0644.
*/
int ssh_scp_request_get_permissions(ssh_scp scp){
return scp->request_mode;
}
/** @brief Gets the size of the file being pushed
* from the other party
* @returns Numeric size of the file being read.
*/
size_t ssh_scp_request_get_size(ssh_scp scp){
return scp->filelen;
}
/** @brief Converts a scp text mode to an integer one
* @param mode mode to convert, e.g. "0644"
* @returns integer value, e.g. 420 for "0644"
*/
int ssh_scp_integer_mode(const char *mode){
int value=strtoul(mode,NULL,8) & 0xffff;
return value;
}
/** @brief Converts a unix mode into a scp string one.
* @param mode mode to convert, e.g. 420 or 0644
* @returns pointer to a malloc'ed string containing the scp mode,
* e.g. "0644".
*/
char *ssh_scp_string_mode(int mode){
char buffer[16];
snprintf(buffer,sizeof(buffer),"%.4o",mode);
return strdup(buffer);
}
/** @brief Gets the warning string
* @returns Warning string. Should not be freed.
*/
const char *ssh_scp_request_get_warning(ssh_scp scp){
return scp->warning;
}
/** @} */

View File

@@ -27,28 +27,17 @@
* @{
*/
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "libssh/priv.h"
#include "libssh/libssh.h"
#include "libssh/server.h"
#include "libssh/ssh2.h"
#include "libssh/keyfiles.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/socket.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
#ifdef _WIN32
@@ -56,7 +45,7 @@
#define SOCKOPT_TYPE_ARG4 char
/* We need to provide hstrerror. Not we can't call the parameter h_errno because it's #defined */
static char *hstrerror(int h_errno_val) {
inline char *hstrerror(int h_errno_val) {
static char text[50] = {0};
snprintf(text, sizeof(text), "gethostbyname error %d\n", h_errno_val);
@@ -73,7 +62,7 @@ static char *hstrerror(int h_errno_val) {
#endif /* _WIN32 */
/* TODO FIXME: must use getaddrinfo */
static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
static socket_t bind_socket(SSH_BIND *ssh_bind, const char *hostname,
int port) {
struct sockaddr_in myaddr;
struct hostent *hp=NULL;
@@ -82,7 +71,7 @@ static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno));
ssh_set_error(ssh_bind, SSH_FATAL, "%s", strerror(errno));
return -1;
}
@@ -91,7 +80,7 @@ static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
#endif
if (hp == NULL) {
ssh_set_error(sshbind, SSH_FATAL,
ssh_set_error(ssh_bind, SSH_FATAL,
"Resolving %s: %s", hostname, hstrerror(h_errno));
close(s);
return -1;
@@ -103,14 +92,14 @@ static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
myaddr.sin_port = htons(port);
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) {
ssh_set_error(sshbind, SSH_FATAL,
ssh_set_error(ssh_bind, SSH_FATAL,
"Setting socket options failed: %s", hstrerror(h_errno));
close(s);
return -1;
}
if (bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) {
ssh_set_error(sshbind, SSH_FATAL, "Binding to %s:%d: %s",
ssh_set_error(ssh_bind, SSH_FATAL, "Binding to %s:%d: %s",
hostname,
port,
strerror(errno));
@@ -121,42 +110,48 @@ static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
return s;
}
ssh_bind ssh_bind_new(void) {
ssh_bind ptr;
SSH_BIND *ssh_bind_new(void) {
SSH_BIND *ptr;
ptr = malloc(sizeof(struct ssh_bind_struct));
ptr = malloc(sizeof(SSH_BIND));
if (ptr == NULL) {
return NULL;
}
ZERO_STRUCTP(ptr);
ptr->bindfd = SSH_INVALID_SOCKET;
ptr->bindport= 22;
ptr->log_verbosity = 0;
ptr->bindfd = -1;
return ptr;
}
int ssh_bind_listen(ssh_bind sshbind) {
const char *host;
socket_t fd;
void ssh_bind_set_options(SSH_BIND *ssh_bind, SSH_OPTIONS *options) {
ssh_bind->options = options;
}
if (ssh_init() < 0) {
int ssh_bind_listen(SSH_BIND *ssh_bind) {
const char *host;
int fd;
if (ssh_bind->options == NULL) {
return -1;
}
host = sshbind->bindaddr;
if (ssh_socket_init() < 0) {
return -1;
}
host = ssh_bind->options->bindaddr;
if (host == NULL) {
host = "0.0.0.0";
}
fd = bind_socket(sshbind, host, sshbind->bindport);
fd = bind_socket(ssh_bind, host, ssh_bind->options->bindport);
if (fd < 0) {
return -1;
}
sshbind->bindfd = fd;
ssh_bind->bindfd = fd;
if (listen(fd, 10) < 0) {
ssh_set_error(sshbind, SSH_FATAL,
ssh_set_error(ssh_bind, SSH_FATAL,
"Listening to socket %d: %s",
fd, strerror(errno));
close(fd);
@@ -166,169 +161,143 @@ int ssh_bind_listen(ssh_bind sshbind) {
return 0;
}
void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) {
sshbind->blocking = blocking ? 1 : 0;
void ssh_bind_set_blocking(SSH_BIND *ssh_bind, int blocking) {
ssh_bind->blocking = blocking ? 1 : 0;
}
socket_t ssh_bind_get_fd(ssh_bind sshbind) {
return sshbind->bindfd;
socket_t ssh_bind_get_fd(SSH_BIND *ssh_bind) {
return ssh_bind->bindfd;
}
void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) {
sshbind->bindfd = fd;
void ssh_bind_set_fd(SSH_BIND *ssh_bind, socket_t fd) {
ssh_bind->bindfd = fd;
}
void ssh_bind_fd_toaccept(ssh_bind sshbind) {
sshbind->toaccept = 1;
void ssh_bind_fd_toaccept(SSH_BIND *ssh_bind) {
ssh_bind->toaccept = 1;
}
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
ssh_private_key dsa = NULL;
ssh_private_key rsa = NULL;
socket_t fd = SSH_INVALID_SOCKET;
int i;
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind) {
SSH_SESSION *session;
PRIVATE_KEY *dsa = NULL;
PRIVATE_KEY *rsa = NULL;
int fd = -1;
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL,
if (ssh_bind->bindfd < 0) {
ssh_set_error(ssh_bind, SSH_FATAL,
"Can't accept new clients on a not bound socket.");
return SSH_ERROR;
}
if(session == NULL){
ssh_set_error(sshbind, SSH_FATAL,"session is null");
return SSH_ERROR;
}
if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) {
ssh_set_error(sshbind, SSH_FATAL,
"DSA or RSA host key file must be set before accept()");
return SSH_ERROR;
return NULL;
}
if (sshbind->dsakey) {
dsa = _privatekey_from_file(sshbind, sshbind->dsakey, TYPE_DSS);
if (ssh_bind->options->dsakey == NULL || ssh_bind->options->rsakey == NULL) {
ssh_set_error(ssh_bind, SSH_FATAL,
"DSA or RSA host key file must be set before accept()");
return NULL;
}
if (ssh_bind->options->dsakey) {
dsa = _privatekey_from_file(ssh_bind, ssh_bind->options->dsakey, TYPE_DSS);
if (dsa == NULL) {
return SSH_ERROR;
return NULL;
}
}
if (sshbind->rsakey) {
rsa = _privatekey_from_file(sshbind, sshbind->rsakey, TYPE_RSA);
if (ssh_bind->options->rsakey) {
rsa = _privatekey_from_file(ssh_bind, ssh_bind->options->rsakey, TYPE_RSA);
if (rsa == NULL) {
privatekey_free(dsa);
return SSH_ERROR;
return NULL;
}
}
fd = accept(sshbind->bindfd, NULL, NULL);
if (fd == SSH_INVALID_SOCKET) {
ssh_set_error(sshbind, SSH_FATAL,
fd = accept(ssh_bind->bindfd, NULL, NULL);
if (fd < 0) {
ssh_set_error(ssh_bind, SSH_FATAL,
"Accepting a new connection: %s",
strerror(errno));
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
return NULL;
}
session = ssh_new();
if (session == NULL) {
ssh_set_error(ssh_bind, SSH_FATAL, "Not enough space");
privatekey_free(dsa);
privatekey_free(rsa);
return NULL;
}
session->server = 1;
session->version = 2;
/* copy options */
for (i = 0; i < 10; ++i) {
if (sshbind->wanted_methods[i]) {
session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
if (session->wanted_methods[i] == NULL) {
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
}
}
session->options = ssh_options_copy(ssh_bind->options);
if (session->options == NULL) {
ssh_set_error(ssh_bind, SSH_FATAL, "No space left");
privatekey_free(dsa);
privatekey_free(rsa);
ssh_cleanup(session);
return NULL;
}
if (sshbind->bindaddr == NULL)
session->bindaddr = NULL;
else {
session->bindaddr = strdup(sshbind->bindaddr);
if (session->bindaddr == NULL) {
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
}
}
session->log_verbosity = sshbind->log_verbosity;
ssh_socket_free(session->socket);
session->socket = ssh_socket_new(session);
if (session->socket == NULL) {
privatekey_free(dsa);
privatekey_free(rsa);
return SSH_ERROR;
ssh_cleanup(session);
return NULL;
}
ssh_socket_set_fd(session->socket, fd);
ssh_socket_set_fd(session->socket,fd);
session->dsa_key = dsa;
session->rsa_key = rsa;
return SSH_OK;
return session;
}
void ssh_bind_free(ssh_bind sshbind){
int i;
if (sshbind == NULL) {
void ssh_bind_free(SSH_BIND *ssh_bind){
if (ssh_bind == NULL) {
return;
}
if (sshbind->bindfd >= 0) {
#ifdef _WIN32
closesocket(sshbind->bindfd);
#else
close(sshbind->bindfd);
#endif
if (ssh_bind->bindfd >= 0) {
close(ssh_bind->bindfd);
}
sshbind->bindfd = SSH_INVALID_SOCKET;
/* options */
SAFE_FREE(sshbind->banner);
SAFE_FREE(sshbind->dsakey);
SAFE_FREE(sshbind->rsakey);
SAFE_FREE(sshbind->bindaddr);
for (i = 0; i < 10; i++) {
if (sshbind->wanted_methods[i]) {
SAFE_FREE(sshbind->wanted_methods[i]);
}
ssh_bind->bindfd = -1;
if (ssh_bind->options) {
ssh_options_free(ssh_bind->options);
}
SAFE_FREE(sshbind);
SAFE_FREE(ssh_bind);
}
extern char *supported_methods[];
/** @internal
* This functions sets the Key Exchange protocols to be accepted
* by the server. They depend on
* -What the user asked (via options)
* -What is available (keys)
* It should then accept the intersection of what the user asked
* and what is available, and return an error if nothing matches
*/
static int server_set_kex(ssh_session session) {
static int server_set_kex(SSH_SESSION * session) {
KEX *server = &session->server_kex;
SSH_OPTIONS *options = session->options;
int i, j;
char *wanted;
ZERO_STRUCTP(server);
ssh_get_random(server->cookie, 16, 0);
/*
* The program might ask for a specific cookie to be sent. Useful for server
* debugging
*/
if (options->wanted_cookie) {
memcpy(server->cookie, options->wanted_cookie, 16);
} else {
ssh_get_random(server->cookie, 16, 0);
}
if (session->dsa_key != NULL && session->rsa_key != NULL) {
if (ssh_options_set_algo(session, SSH_HOSTKEYS,
if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS,
"ssh-dss,ssh-rsa") < 0) {
return -1;
}
} else if (session->dsa_key != NULL) {
if (ssh_options_set_algo(session, SSH_HOSTKEYS, "ssh-dss") < 0) {
if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, "ssh-dss") < 0) {
return -1;
}
} else {
if (ssh_options_set_algo(session, SSH_HOSTKEYS, "ssh-rsa") < 0) {
if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, "ssh-rsa") < 0) {
return -1;
}
}
@@ -339,7 +308,7 @@ static int server_set_kex(ssh_session session) {
}
for (i = 0; i < 10; i++) {
if ((wanted = session->wanted_methods[i]) == NULL) {
if ((wanted = options->wanted_methods[i]) == NULL) {
wanted = supported_methods[i];
}
server->methods[i] = strdup(wanted);
@@ -355,13 +324,13 @@ static int server_set_kex(ssh_session session) {
return 0;
}
static int dh_handshake_server(ssh_session session) {
ssh_string e;
ssh_string f;
ssh_string pubkey;
ssh_string sign;
ssh_public_key pub;
ssh_private_key prv;
static int dh_handshake_server(SSH_SESSION *session) {
STRING *e;
STRING *f;
STRING *pubkey;
STRING *sign;
PUBLIC_KEY *pub;
PRIVATE_KEY *prv;
if (packet_wait(session, SSH2_MSG_KEXDH_INIT, 1) != SSH_OK) {
return -1;
@@ -455,7 +424,7 @@ static int dh_handshake_server(ssh_session session) {
buffer_add_ssh_string(session->out_buffer, f) < 0 ||
buffer_add_ssh_string(session->out_buffer, sign) < 0) {
ssh_set_error(session, SSH_FATAL, "Not enough space");
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
string_free(f);
string_free(sign);
return -1;
@@ -468,7 +437,7 @@ static int dh_handshake_server(ssh_session session) {
}
if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
buffer_reinit(session->out_buffer);
buffer_free(session->out_buffer);
return -1;
}
@@ -505,11 +474,15 @@ static int dh_handshake_server(ssh_session session) {
}
/* Do the banner and key exchange */
int ssh_accept(ssh_session session) {
int ssh_accept(SSH_SESSION *session) {
if (ssh_send_banner(session, 1) < 0) {
return -1;
}
if (ssh_crypto_init() < 0) {
return -1;
}
session->alive = 1;
session->clientbanner = ssh_get_banner(session);
@@ -541,353 +514,6 @@ int ssh_accept(ssh_session session) {
return 0;
}
/**
* @brief Blocking write on channel for stderr.
*
* @param channel The channel to write to.
*
* @param data A pointer to the data to write.
*
* @param len The length of the buffer to write to.
*
* @return The number of bytes written, SSH_ERROR on error.
*
* @see channel_read()
*/
int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) {
return channel_write_common(channel, data, len, 1);
}
/* messages */
static int ssh_message_auth_reply_default(ssh_message msg,int partial) {
ssh_session session = msg->session;
char methods_c[128] = {0};
ssh_string methods = NULL;
int rc = SSH_ERROR;
enter_function();
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_FAILURE) < 0) {
return rc;
}
if (session->auth_methods == 0) {
session->auth_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD;
}
if (session->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
strcat(methods_c, "publickey,");
}
if (session->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
strcat(methods_c, "keyboard-interactive,");
}
if (session->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
strcat(methods_c, "password,");
}
if (session->auth_methods & SSH_AUTH_METHOD_HOSTBASED) {
strcat(methods_c, "hostbased,");
}
/* Strip the comma. */
methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at
ssh_log(session, SSH_LOG_PACKET,
"Sending a auth failure. methods that can continue: %s", methods_c);
methods = string_from_char(methods_c);
if (methods == NULL) {
goto error;
}
if (buffer_add_ssh_string(msg->session->out_buffer, methods) < 0) {
goto error;
}
if (partial) {
if (buffer_add_u8(session->out_buffer, 1) < 0) {
goto error;
}
} else {
if (buffer_add_u8(session->out_buffer, 0) < 0) {
goto error;
}
}
rc = packet_send(msg->session);
error:
string_free(methods);
leave_function();
return rc;
}
static int ssh_message_channel_request_open_reply_default(ssh_message msg) {
ssh_log(msg->session, SSH_LOG_FUNCTIONS, "Refusing a channel");
if (buffer_add_u8(msg->session->out_buffer
, SSH2_MSG_CHANNEL_OPEN_FAILURE) < 0) {
goto error;
}
if (buffer_add_u32(msg->session->out_buffer,
htonl(msg->channel_request_open.sender)) < 0) {
goto error;
}
if (buffer_add_u32(msg->session->out_buffer,
htonl(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) < 0) {
goto error;
}
/* reason is an empty string */
if (buffer_add_u32(msg->session->out_buffer, 0) < 0) {
goto error;
}
/* language too */
if (buffer_add_u32(msg->session->out_buffer, 0) < 0) {
goto error;
}
return packet_send(msg->session);
error:
return SSH_ERROR;
}
static int ssh_message_channel_request_reply_default(ssh_message msg) {
uint32_t channel;
if (msg->channel_request.want_reply) {
channel = msg->channel_request.channel->remote_channel;
ssh_log(msg->session, SSH_LOG_PACKET,
"Sending a default channel_request denied to channel %d", channel);
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_CHANNEL_FAILURE) < 0) {
return SSH_ERROR;
}
if (buffer_add_u32(msg->session->out_buffer, htonl(channel)) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
ssh_log(msg->session, SSH_LOG_PACKET,
"The client doesn't want to know the request failed!");
return SSH_OK;
}
static int ssh_message_service_request_reply_default(ssh_message msg) {
/* The only return code accepted by specifications are success or disconnect */
return ssh_message_service_reply_success(msg);
}
int ssh_message_service_reply_success(ssh_message msg) {
struct ssh_string_struct *service;
ssh_session session=msg->session;
if (msg == NULL) {
return SSH_ERROR;
}
ssh_log(session, SSH_LOG_PACKET,
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {
return -1;
}
service=string_from_char(msg->service_request.service);
if (buffer_add_ssh_string(session->out_buffer, service) < 0) {
string_free(service);
return -1;
}
string_free(service);
return packet_send(msg->session);
}
int ssh_message_reply_default(ssh_message msg) {
if (msg == NULL) {
return -1;
}
switch(msg->type) {
case SSH_REQUEST_AUTH:
return ssh_message_auth_reply_default(msg, 0);
case SSH_REQUEST_CHANNEL_OPEN:
return ssh_message_channel_request_open_reply_default(msg);
case SSH_REQUEST_CHANNEL:
return ssh_message_channel_request_reply_default(msg);
case SSH_REQUEST_SERVICE:
return ssh_message_service_request_reply_default(msg);
default:
ssh_log(msg->session, SSH_LOG_PACKET,
"Don't know what to default reply to %d type",
msg->type);
break;
}
return -1;
}
char *ssh_message_service_service(ssh_message msg){
if (msg == NULL) {
return NULL;
}
return msg->service_request.service;
}
char *ssh_message_auth_user(ssh_message msg) {
if (msg == NULL) {
return NULL;
}
return msg->auth_request.username;
}
char *ssh_message_auth_password(ssh_message msg){
if (msg == NULL) {
return NULL;
}
return msg->auth_request.password;
}
/* Get the publickey of an auth request */
ssh_public_key ssh_message_auth_publickey(ssh_message msg){
if (msg == NULL) {
return NULL;
}
return msg->auth_request.public_key;
}
int ssh_message_auth_set_methods(ssh_message msg, int methods) {
if (msg == NULL || msg->session == NULL) {
return -1;
}
msg->session->auth_methods = methods;
return 0;
}
int ssh_message_auth_reply_success(ssh_message msg, int partial) {
if (msg == NULL) {
return SSH_ERROR;
}
if (partial) {
return ssh_message_auth_reply_default(msg, partial);
}
if (buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
/* Answer OK to a pubkey auth request */
int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey) {
if (msg == NULL) {
return SSH_ERROR;
}
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_USERAUTH_PK_OK) < 0 ||
buffer_add_ssh_string(msg->session->out_buffer, algo) < 0 ||
buffer_add_ssh_string(msg->session->out_buffer, pubkey) < 0) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
char *ssh_message_channel_request_open_originator(ssh_message msg){
return msg->channel_request_open.originator;
}
int ssh_message_channel_request_open_originator_port(ssh_message msg){
return msg->channel_request_open.originator_port;
}
char *ssh_message_channel_request_open_destination(ssh_message msg){
return msg->channel_request_open.destination;
}
int ssh_message_channel_request_open_destination_port(ssh_message msg){
return msg->channel_request_open.destination_port;
}
ssh_channel ssh_message_channel_request_channel(ssh_message msg){
return msg->channel_request.channel;
}
char *ssh_message_channel_request_pty_term(ssh_message msg){
return msg->channel_request.TERM;
}
int ssh_message_channel_request_pty_width(ssh_message msg){
return msg->channel_request.width;
}
int ssh_message_channel_request_pty_height(ssh_message msg){
return msg->channel_request.height;
}
int ssh_message_channel_request_pty_pxwidth(ssh_message msg){
return msg->channel_request.pxwidth;
}
int ssh_message_channel_request_pty_pxheight(ssh_message msg){
return msg->channel_request.pxheight;
}
char *ssh_message_channel_request_env_name(ssh_message msg){
return msg->channel_request.var_name;
}
char *ssh_message_channel_request_env_value(ssh_message msg){
return msg->channel_request.var_value;
}
char *ssh_message_channel_request_command(ssh_message msg){
return msg->channel_request.command;
}
char *ssh_message_channel_request_subsystem(ssh_message msg){
return msg->channel_request.subsystem;
}
/** @brief defines the SSH_MESSAGE callback
* @param session the current ssh session
* @param ssh_message_callback a function pointer to a callback taking the
* current ssh session and received message as parameters. the function returns
* 0 if the message has been parsed and treated sucessfuly, 1 otherwise (libssh
* must take care of the response).
*/
void ssh_set_message_callback(ssh_session session,
int(*ssh_message_callback)(ssh_session session, ssh_message msg)){
session->ssh_message_callback=ssh_message_callback;
}
int ssh_execute_message_callbacks(ssh_session session){
ssh_message msg=NULL;
int ret;
if(!session->ssh_message_list)
return SSH_OK;
if(session->ssh_message_callback){
while((msg=ssh_list_pop_head(ssh_message , session->ssh_message_list)) != NULL){
ret=session->ssh_message_callback(session,msg);
if(ret==1){
ret = ssh_message_reply_default(msg);
if(ret != SSH_OK)
return ret;
}
}
} else {
while((msg=ssh_list_pop_head(ssh_message , session->ssh_message_list)) != NULL){
ret = ssh_message_reply_default(msg);
if(ret != SSH_OK)
return ret;
}
}
return SSH_OK;
}
/** @}
*/
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -21,19 +21,11 @@
* MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include "libssh/libssh.h"
#include "libssh/priv.h"
#include "libssh/server.h"
#include "libssh/socket.h"
#include "libssh/agent.h"
#include "libssh/packet.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#include "libssh/ssh2.h"
#include "libssh/buffer.h"
#define FIRST_CHANNEL 42 // why not ? it helps to find bugs.
/** \defgroup ssh_session SSH Session
@@ -45,27 +37,32 @@
/** \brief creates a new ssh session
* \returns new ssh_session pointer
*/
ssh_session ssh_new(void) {
ssh_session session;
char *id;
int rc;
SSH_SESSION *ssh_new(void) {
SSH_SESSION *session;
session = malloc(sizeof (struct ssh_session_struct));
session = malloc(sizeof (SSH_SESSION));
if (session == NULL) {
return NULL;
}
ZERO_STRUCTP(session);
memset(session, 0, sizeof(SSH_SESSION));
session->next_crypto = crypto_new();
if (session->next_crypto == NULL) {
goto err;
}
session->maxchannel = FIRST_CHANNEL;
session->socket = ssh_socket_new(session);
if (session->socket == NULL) {
goto err;
}
session->alive = 0;
session->auth_methods = 0;
session->blocking = 1;
session->log_indent = 0;
session->out_buffer = buffer_new();
if (session->out_buffer == NULL) {
goto err;
@@ -76,74 +73,20 @@ ssh_session ssh_new(void) {
goto err;
}
session->alive = 0;
session->auth_methods = 0;
session->blocking = 1;
session->log_indent = 0;
session->maxchannel = FIRST_CHANNEL;
/* options */
session->port = 22;
session->fd = -1;
session->ssh2 = 1;
#ifdef WITH_SSH1
session->ssh1 = 1;
#else
session->ssh1 = 0;
#endif
#ifndef _WIN32
session->agent = agent_new(session);
if (session->agent == NULL) {
goto err;
}
#endif /* _WIN32 */
session->identity = ssh_list_new();
if (session->identity == NULL) {
goto err;
}
id = strdup("%d/id_rsa");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
id = strdup("%d/id_dsa");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
id = strdup("%d/identity");
if (id == NULL) {
goto err;
}
rc = ssh_list_append(session->identity, id);
if (rc == SSH_ERROR) {
goto err;
}
return session;
err:
ssh_free(session);
ssh_cleanup(session);
return NULL;
}
/**
* @brief deallocate a session handle
* @see ssh_disconnect()
* @see ssh_new()
*/
void ssh_free(ssh_session session) {
void ssh_cleanup(SSH_SESSION *session) {
int i;
enter_function();
@@ -154,15 +97,8 @@ void ssh_free(ssh_session session) {
SAFE_FREE(session->serverbanner);
SAFE_FREE(session->clientbanner);
SAFE_FREE(session->banner);
#ifdef WITH_PCAP
if(session->pcap_ctx){
ssh_pcap_context_free(session->pcap_ctx);
session->pcap_ctx=NULL;
}
#endif
buffer_free(session->in_buffer);
buffer_free(session->out_buffer);
session->in_buffer=session->out_buffer=NULL;
crypto_free(session->current_crypto);
crypto_free(session->next_crypto);
ssh_socket_free(session->socket);
@@ -189,49 +125,20 @@ void ssh_free(ssh_session session) {
privatekey_free(session->dsa_key);
privatekey_free(session->rsa_key);
if(session->ssh_message_list){
ssh_message msg;
while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
!= NULL){
ssh_message_free(msg);
}
ssh_list_free(session->ssh_message_list);
}
if (session->identity) {
char *id;
for (id = ssh_list_pop_head(char *, session->identity);
id != NULL;
id = ssh_list_pop_head(char *, session->identity)) {
SAFE_FREE(id);
}
ssh_list_free(session->identity);
}
/* options */
SAFE_FREE(session->username);
SAFE_FREE(session->host);
SAFE_FREE(session->sshdir);
SAFE_FREE(session->knownhosts);
SAFE_FREE(session->ProxyCommand);
for (i = 0; i < 10; i++) {
if (session->wanted_methods[i]) {
SAFE_FREE(session->wanted_methods[i]);
}
}
ssh_message_free(session->ssh_message);
ssh_options_free(session->options);
/* burn connection, it could hang sensitive datas */
ZERO_STRUCTP(session);
memset(session,'X',sizeof(SSH_SESSION));
SAFE_FREE(session);
/* FIXME: leave_function(); ??? */
}
/** \brief disconnect impolitely from remote host by closing the socket.
* Suitable if you forked and want to destroy this session.
/** \brief disconnect impolitely from remote host
* \param session current ssh session
*/
void ssh_silent_disconnect(ssh_session session) {
void ssh_silent_disconnect(SSH_SESSION *session) {
enter_function();
if (session == NULL) {
@@ -241,7 +148,22 @@ void ssh_silent_disconnect(ssh_session session) {
ssh_socket_close(session->socket);
session->alive = 0;
ssh_disconnect(session);
leave_function();
/* FIXME: leave_function(); ??? */
}
/** \brief set the options for the current session
* \param session ssh session
* \param options options structure
* \see ssh_new()
* \see ssh_options_new()
*/
void ssh_set_options(SSH_SESSION *session, SSH_OPTIONS *options) {
if (session == NULL || options == NULL) {
return;
}
session->options = options;
session->log_verbosity = options->log_verbosity;
}
/** \brief set the session in blocking/nonblocking mode
@@ -249,7 +171,7 @@ void ssh_silent_disconnect(ssh_session session) {
* \param blocking zero for nonblocking mode
* \bug nonblocking code is in development and won't work as expected
*/
void ssh_set_blocking(ssh_session session, int blocking) {
void ssh_set_blocking(SSH_SESSION *session, int blocking) {
if (session == NULL) {
return;
}
@@ -264,7 +186,7 @@ void ssh_set_blocking(ssh_session session, int blocking) {
* \return file descriptor of the connection, or -1 if it is
* not connected
*/
socket_t ssh_get_fd(ssh_session session) {
socket_t ssh_get_fd(SSH_SESSION *session) {
if (session == NULL) {
return -1;
}
@@ -275,7 +197,7 @@ socket_t ssh_get_fd(ssh_session session) {
/** \brief say to the session it has data to read on the file descriptor without blocking
* \param session ssh session
*/
void ssh_set_fd_toread(ssh_session session) {
void ssh_set_fd_toread(SSH_SESSION *session) {
if (session == NULL) {
return;
}
@@ -286,7 +208,7 @@ void ssh_set_fd_toread(ssh_session session) {
/** \brief say the session it may write to the file descriptor without blocking
* \param session ssh session
*/
void ssh_set_fd_towrite(ssh_session session) {
void ssh_set_fd_towrite(SSH_SESSION *session) {
if (session == NULL) {
return;
}
@@ -297,7 +219,7 @@ void ssh_set_fd_towrite(ssh_session session) {
/** \brief say the session it has an exception to catch on the file descriptor
* \param session ssh session
*/
void ssh_set_fd_except(ssh_session session) {
void ssh_set_fd_except(SSH_SESSION *session) {
if (session == NULL) {
return;
}
@@ -308,7 +230,7 @@ void ssh_set_fd_except(ssh_session session) {
/** \warning I don't remember if this should be internal or not
*/
/* looks if there is data to read on the socket and parse it. */
int ssh_handle_packets(ssh_session session) {
int ssh_handle_packets(SSH_SESSION *session) {
int w = 0;
int e = 0;
int rc = -1;
@@ -346,7 +268,7 @@ int ssh_handle_packets(ssh_session session) {
* which respectively means the session is closed, has data to read on
* the connection socket and session was closed due to an error.
*/
int ssh_get_status(ssh_session session) {
int ssh_get_status(SSH_SESSION *session) {
int socketstate;
int r = 0;
@@ -374,7 +296,7 @@ int ssh_get_status(ssh_session session) {
* \return message sent by the server along with the disconnect, or NULL in which case the reason of the disconnect may be found with ssh_get_error.
* \see ssh_get_error()
*/
const char *ssh_get_disconnect_message(ssh_session session) {
const char *ssh_get_disconnect_message(SSH_SESSION *session) {
if (session == NULL) {
return NULL;
}
@@ -402,7 +324,7 @@ const char *ssh_get_disconnect_message(ssh_session session) {
*
* @return 1 or 2, for ssh1 or ssh2, < 0 on error.
*/
int ssh_get_version(ssh_session session) {
int ssh_get_version(SSH_SESSION *session) {
if (session == NULL) {
return -1;
}
@@ -410,32 +332,5 @@ int ssh_get_version(ssh_session session) {
return session->version;
}
/**
* @internal
* @handle a SSH_MSG_GLOBAL_REQUEST packet
* @param session the SSH session
*/
void ssh_global_request_handle(ssh_session session){
ssh_string type;
char *type_c;
uint32_t needreply;
type=buffer_get_ssh_string(session->in_buffer);
buffer_get_u32(session->in_buffer,&needreply);
if(type==NULL)
return;
type_c=string_to_char(type);
if(!type_c)
return;
ssh_log(session, SSH_LOG_PROTOCOL,
"Received SSH_GLOBAL_REQUEST %s (wantreply=%d)",type_c,needreply);
SAFE_FREE(type_c);
string_free(type);
if(needreply != 0){
buffer_add_u8(session->out_buffer,SSH2_MSG_REQUEST_FAILURE);
packet_send(session);
}
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

File diff suppressed because it is too large Load Diff

View File

@@ -21,6 +21,7 @@
* MA 02111-1307, USA.
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -33,16 +34,14 @@
#include "libssh/sftp.h"
#include "libssh/ssh2.h"
#include "libssh/priv.h"
#include "libssh/buffer.h"
#include "libssh/misc.h"
sftp_client_message sftp_get_client_message(sftp_session sftp) {
sftp_packet packet;
sftp_client_message msg;
ssh_buffer payload;
ssh_string tmp;
SFTP_CLIENT_MESSAGE *sftp_get_client_message(SFTP_SESSION *sftp) {
SFTP_PACKET *packet;
SFTP_CLIENT_MESSAGE *msg;
BUFFER *payload;
STRING *tmp;
msg = malloc(sizeof (struct sftp_client_message_struct));
msg = malloc(sizeof (SFTP_CLIENT_MESSAGE));
if (msg == NULL) {
return NULL;
}
@@ -213,7 +212,7 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
return msg;
}
void sftp_client_message_free(sftp_client_message msg) {
void sftp_client_message_free(SFTP_CLIENT_MESSAGE *msg) {
if (msg == NULL) {
return;
}
@@ -227,10 +226,10 @@ void sftp_client_message_free(sftp_client_message msg) {
SAFE_FREE(msg);
}
int sftp_reply_name(sftp_client_message msg, const char *name,
sftp_attributes attr) {
ssh_buffer out;
ssh_string file;
int sftp_reply_name(SFTP_CLIENT_MESSAGE *msg, const char *name,
SFTP_ATTRIBUTES *attr) {
BUFFER *out;
STRING *file;
out = buffer_new();
if (out == NULL) {
@@ -259,8 +258,8 @@ int sftp_reply_name(sftp_client_message msg, const char *name,
return 0;
}
int sftp_reply_handle(sftp_client_message msg, ssh_string handle){
ssh_buffer out;
int sftp_reply_handle(SFTP_CLIENT_MESSAGE *msg, STRING *handle){
BUFFER *out;
out = buffer_new();
if (out == NULL) {
@@ -278,8 +277,8 @@ int sftp_reply_handle(sftp_client_message msg, ssh_string handle){
return 0;
}
int sftp_reply_attr(sftp_client_message msg, sftp_attributes attr) {
ssh_buffer out;
int sftp_reply_attr(SFTP_CLIENT_MESSAGE *msg, SFTP_ATTRIBUTES *attr) {
BUFFER *out;
out = buffer_new();
if (out == NULL) {
@@ -297,9 +296,9 @@ int sftp_reply_attr(sftp_client_message msg, sftp_attributes attr) {
return 0;
}
int sftp_reply_names_add(sftp_client_message msg, const char *file,
const char *longname, sftp_attributes attr) {
ssh_string name;
int sftp_reply_names_add(SFTP_CLIENT_MESSAGE *msg, const char *file,
const char *longname, SFTP_ATTRIBUTES *attr) {
STRING *name;
name = string_from_char(file);
if (name == NULL) {
@@ -335,8 +334,8 @@ int sftp_reply_names_add(sftp_client_message msg, const char *file,
return 0;
}
int sftp_reply_names(sftp_client_message msg) {
ssh_buffer out;
int sftp_reply_names(SFTP_CLIENT_MESSAGE *msg) {
BUFFER *out;
out = buffer_new();
if (out == NULL) {
@@ -363,10 +362,10 @@ int sftp_reply_names(sftp_client_message msg) {
return 0;
}
int sftp_reply_status(sftp_client_message msg, uint32_t status,
int sftp_reply_status(SFTP_CLIENT_MESSAGE *msg, u32 status,
const char *message) {
ssh_buffer out;
ssh_string s;
BUFFER *out;
STRING *s;
out = buffer_new();
if (out == NULL) {
@@ -395,8 +394,8 @@ int sftp_reply_status(sftp_client_message msg, uint32_t status,
return 0;
}
int sftp_reply_data(sftp_client_message msg, const void *data, int len) {
ssh_buffer out;
int sftp_reply_data(SFTP_CLIENT_MESSAGE *msg, const void *data, int len) {
BUFFER *out;
out = buffer_new();
if (out == NULL) {
@@ -421,9 +420,9 @@ int sftp_reply_data(sftp_client_message msg, const void *data, int len) {
* the handle. Care is given that a corrupted handle won't give a
* valid info (or worse).
*/
ssh_string sftp_handle_alloc(sftp_session sftp, void *info) {
ssh_string ret;
uint32_t val;
STRING *sftp_handle_alloc(SFTP_SESSION *sftp, void *info) {
STRING *ret;
u32 val;
int i;
if (sftp->handles == NULL) {
@@ -450,24 +449,24 @@ ssh_string sftp_handle_alloc(sftp_session sftp, void *info) {
return NULL;
}
memcpy(string_data(ret), &val, sizeof(uint32_t));
memcpy(ret->string, &val, sizeof(u32));
sftp->handles[i] = info;
return ret;
}
void *sftp_handle(sftp_session sftp, ssh_string handle){
uint32_t val;
void *sftp_handle(SFTP_SESSION *sftp, STRING *handle){
u32 val;
if (sftp->handles == NULL) {
return NULL;
}
if (string_len(handle) != sizeof(uint32_t)) {
if (string_len(handle) != sizeof(u32)) {
return NULL;
}
memcpy(&val, string_data(handle), sizeof(uint32_t));
memcpy(&val, handle->string, sizeof(u32));
if (val > SFTP_HANDLES) {
return NULL;
@@ -476,7 +475,7 @@ void *sftp_handle(sftp_session sftp, ssh_string handle){
return sftp->handles[val];
}
void sftp_handle_remove(sftp_session sftp, void *handle) {
void sftp_handle_remove(SFTP_SESSION *sftp, void *handle) {
int i;
for (i = 0; i < SFTP_HANDLES; i++) {

View File

@@ -21,26 +21,20 @@
* MA 02111-1307, USA.
*/
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
extern char **environ;
#endif
#include "libssh/priv.h"
#include "libssh/socket.h"
#include "libssh/buffer.h"
#include "libssh/poll.h"
#include "libssh/session.h"
/** \defgroup ssh_socket SSH Sockets
* \addtogroup ssh_socket
@@ -54,9 +48,9 @@ struct socket {
not block */
int data_to_write;
int data_except;
ssh_buffer out_buffer;
ssh_buffer in_buffer;
ssh_session session;
BUFFER *out_buffer;
BUFFER *in_buffer;
SSH_SESSION *session;
};
/*
@@ -71,32 +65,21 @@ int ssh_socket_init(void) {
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return -1;
}
#endif
ssh_poll_init();
return 0;
}
/**
* @brief Cleanup the socket system.
*/
void ssh_socket_cleanup(void) {
ssh_poll_cleanup();
}
/**
/*
* \internal
* \brief creates a new Socket object
*/
struct socket *ssh_socket_new(ssh_session session) {
struct socket *ssh_socket_new(SSH_SESSION *session) {
struct socket *s;
s = malloc(sizeof(struct socket));
if (s == NULL) {
return NULL;
}
s->fd = SSH_INVALID_SOCKET;
s->fd = -1;
s->last_errno = -1;
s->session = session;
s->in_buffer = buffer_new();
@@ -138,20 +121,20 @@ int ssh_socket_unix(struct socket *s, const char *path) {
snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path);
s->fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (s->fd == SSH_INVALID_SOCKET) {
if (s->fd < 0) {
return -1;
}
if (fcntl(s->fd, F_SETFD, 1) == -1) {
close(s->fd);
s->fd = SSH_INVALID_SOCKET;
s->fd = -1;
return -1;
}
if (connect(s->fd, (struct sockaddr *) &sunaddr,
sizeof(sunaddr)) < 0) {
close(s->fd);
s->fd = SSH_INVALID_SOCKET;
s->fd = -1;
return -1;
}
@@ -171,7 +154,7 @@ void ssh_socket_close(struct socket *s){
close(s->fd);
s->last_errno = errno;
#endif
s->fd = SSH_INVALID_SOCKET;
s->fd=-1;
}
}
@@ -193,13 +176,13 @@ socket_t ssh_socket_get_fd(struct socket *s) {
* \brief returns nonzero if the socket is open
*/
int ssh_socket_is_open(struct socket *s) {
return s->fd != SSH_INVALID_SOCKET;
return s->fd != -1;
}
/* \internal
* \brief read len bytes from socket into buffer
*/
static int ssh_socket_unbuffered_read(struct socket *s, void *buffer, uint32_t len) {
static int ssh_socket_unbuffered_read(struct socket *s, void *buffer, u32 len) {
int rc = -1;
if (s->data_except) {
@@ -225,7 +208,7 @@ static int ssh_socket_unbuffered_read(struct socket *s, void *buffer, uint32_t l
* \brief writes len bytes from buffer to socket
*/
static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer,
uint32_t len) {
u32 len) {
int w = -1;
if (s->data_except) {
@@ -251,37 +234,37 @@ static int ssh_socket_unbuffered_write(struct socket *s, const void *buffer,
* \brief returns nonzero if the current socket is in the fd_set
*/
int ssh_socket_fd_isset(struct socket *s, fd_set *set) {
if(s->fd == SSH_INVALID_SOCKET) {
if(s->fd == -1) {
return 0;
}
return FD_ISSET(s->fd,set);
}
/* \internal
* \brief sets the current fd in a fd_set and updates the max_fd
* \brief sets the current fd in a fd_set and updates the fd_max
*/
void ssh_socket_fd_set(struct socket *s, fd_set *set, socket_t *max_fd) {
if (s->fd == SSH_INVALID_SOCKET)
void ssh_socket_fd_set(struct socket *s, fd_set *set, int *fd_max) {
if (s->fd == -1)
return;
FD_SET(s->fd,set);
if (s->fd >= 0 && s->fd != SSH_INVALID_SOCKET) {
*max_fd = s->fd + 1;
if (s->fd >= *fd_max) {
*fd_max = s->fd + 1;
}
}
/** \internal
* \brief reads blocking until len bytes have been read
*/
int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len) {
int ssh_socket_completeread(struct socket *s, void *buffer, u32 len) {
int r = -1;
uint32_t total = 0;
uint32_t toread = len;
u32 total = 0;
u32 toread = len;
if(! ssh_socket_is_open(s)) {
return SSH_ERROR;
}
while((r = ssh_socket_unbuffered_read(s, ((uint8_t*)buffer + total), toread))) {
while((r = ssh_socket_unbuffered_read(s, buffer + total, toread))) {
if (r < 0) {
return SSH_ERROR;
}
@@ -302,8 +285,8 @@ int ssh_socket_completeread(struct socket *s, void *buffer, uint32_t len) {
/** \internal
* \brief Blocking write of len bytes
*/
int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len) {
ssh_session session = s->session;
int ssh_socket_completewrite(struct socket *s, const void *buffer, u32 len) {
SSH_SESSION *session = s->session;
int written = -1;
enter_function();
@@ -320,7 +303,7 @@ int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len)
return SSH_ERROR;
}
len -= written;
buffer = ((uint8_t*)buffer + written);
buffer += written;
}
leave_function();
@@ -333,7 +316,7 @@ int ssh_socket_completewrite(struct socket *s, const void *buffer, uint32_t len)
* \returns SSH_AGAIN in nonblocking mode
*/
int ssh_socket_read(struct socket *s, void *buffer, int len){
ssh_session session = s->session;
SSH_SESSION *session = s->session;
int rc = SSH_ERROR;
enter_function();
@@ -358,7 +341,7 @@ int ssh_socket_read(struct socket *s, void *buffer, int len){
* \warning has no effect on socket before a flush
*/
int ssh_socket_write(struct socket *s, const void *buffer, int len) {
ssh_session session = s->session;
SSH_SESSION *session = s->session;
int rc = SSH_ERROR;
enter_function();
@@ -387,7 +370,7 @@ int ssh_socket_write(struct socket *s, const void *buffer, int len) {
* \returns SSH_AGAIN need to call later for data
* \returns SSH_ERROR error happened
*/
int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len) {
int ssh_socket_wait_for_data(struct socket *s, SSH_SESSION *session, u32 len) {
char buffer[4096] = {0};
char *buf = NULL;
int except;
@@ -449,7 +432,7 @@ int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len
if (ssh_socket_is_open(session->socket)) {
r = ssh_socket_unbuffered_read(session->socket, buffer, sizeof(buffer));
} else {
r = -1;
r =- 1;
}
if (r <= 0) {
@@ -463,7 +446,7 @@ int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len
return SSH_ERROR;
}
if (buffer_add_data(s->in_buffer,buffer, (uint32_t) r) < 0) {
if (buffer_add_data(s->in_buffer,buffer, (u32) r) < 0) {
leave_function();
return SSH_ERROR;
}
@@ -475,8 +458,8 @@ int ssh_socket_wait_for_data(struct socket *s, ssh_session session, uint32_t len
/* ssh_socket_poll */
int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
ssh_session session = s->session;
ssh_pollfd_t fd[1];
SSH_SESSION *session = s->session;
pollfd_t fd[1];
int rc = -1;
enter_function();
@@ -496,15 +479,13 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
if (!s->data_to_write) {
fd->events |= POLLOUT;
}
/* do not do poll if fd->events is empty, we already know the response */
if(fd->events != 0){
/* Make the call, and listen for errors */
rc = ssh_poll(fd, 1, 0);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL, "poll(): %s", strerror(errno));
leave_function();
return -1;
}
/* Make the call, and listen for errors */
rc = ssh_poll(fd, 1, 0);
if (rc < 0) {
ssh_set_error(session, SSH_FATAL, "poll(): %s", strerror(errno));
leave_function();
return -1;
}
if (!s->data_to_read) {
@@ -528,7 +509,7 @@ int ssh_socket_poll(struct socket *s, int *writeable, int *except) {
* \brief nonblocking flush of the output buffer
*/
int ssh_socket_nonblocking_flush(struct socket *s) {
ssh_session session = s->session;
SSH_SESSION *session = s->session;
int except;
int can_write;
int w;
@@ -558,7 +539,7 @@ int ssh_socket_nonblocking_flush(struct socket *s) {
buffer_get_rest_len(s->out_buffer));
} else {
/* write failed */
w = -1;
w =- 1;
}
if (w < 0) {
@@ -597,7 +578,7 @@ int ssh_socket_nonblocking_flush(struct socket *s) {
* \brief locking flush of the output packet buffer
*/
int ssh_socket_blocking_flush(struct socket *s) {
ssh_session session = s->session;
SSH_SESSION *session = s->session;
enter_function();
@@ -674,54 +655,6 @@ int ssh_socket_get_status(struct socket *s) {
return r;
}
#ifndef _WIN32
/**
* @internal
* @brief executes a command and redirect input and outputs
* @param command command to execute
* @param in input file descriptor
* @param out output file descriptor
*/
void ssh_execute_command(const char *command, socket_t in, socket_t out){
const char *args[]={"/bin/sh","-c",command,NULL};
/* redirect in and out to stdin, stdout and stderr */
dup2(in, 0);
dup2(out,1);
dup2(out,2);
close(in);
close(out);
execve(args[0],(char * const *)args,(char * const *)environ);
exit(1);
}
/**
* @internal
* @brief Open a socket on a ProxyCommand
* This call will always be nonblocking.
* @param s socket to connect.
* @param command Command to execute.
* @returns SSH_OK socket is being connected.
* @returns SSH_ERROR error while executing the command.
*/
socket_t ssh_socket_connect_proxycommand(ssh_session session,
const char *command){
socket_t fd[2];
int pid;
enter_function();
socketpair(AF_UNIX,SOCK_STREAM,0,fd);
pid = fork();
if(pid == 0){
ssh_execute_command(command,fd[1],fd[1]);
}
close(fd[1]);
ssh_log(session,SSH_LOG_PROTOCOL,"ProxyCommand connection pipe: [%d,%d]",fd[0],fd[1]);
return fd[0];
}
#endif /* _WIN32 */
/** @}
*/
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -22,6 +22,7 @@
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#ifndef _WIN32
@@ -29,7 +30,7 @@
#endif
#include "libssh/priv.h"
#include "libssh/string.h"
/** \defgroup ssh_string SSH Strings
* \brief string manipulations
*/
@@ -41,8 +42,8 @@
* \param size size of the string
* \return the newly allocated string
*/
struct ssh_string_struct *string_new(size_t size) {
struct ssh_string_struct *str = NULL;
struct string_struct *string_new(size_t size) {
struct string_struct *str = NULL;
str = malloc(size + 4);
if (str == NULL) {
@@ -64,7 +65,7 @@ struct ssh_string_struct *string_new(size_t size) {
*
* @return 0 on success, < 0 on error.
*/
int string_fill(struct ssh_string_struct *s, const void *data, size_t len) {
int string_fill(struct string_struct *s, const void *data, size_t len) {
if ((s == NULL) || (data == NULL) ||
(len == 0) || (len > s->size)) {
return -1;
@@ -80,8 +81,8 @@ int string_fill(struct ssh_string_struct *s, const void *data, size_t len) {
* \return the newly allocated string.
* \warning The nul byte is not copied nor counted in the ouput string.
*/
struct ssh_string_struct *string_from_char(const char *what) {
struct ssh_string_struct *ptr = NULL;
struct string_struct *string_from_char(const char *what) {
struct string_struct *ptr = NULL;
size_t len = strlen(what);
ptr = malloc(4 + len);
@@ -96,10 +97,10 @@ struct ssh_string_struct *string_from_char(const char *what) {
/**
* \brief returns the size of a SSH string
* \param s the input SSH string
* \param str the input SSH string
* \return size of the content of str, 0 on error
*/
size_t string_len(struct ssh_string_struct *s) {
size_t string_len(struct string_struct *s) {
if (s == NULL) {
return ntohl(0);
}
@@ -109,12 +110,12 @@ size_t string_len(struct ssh_string_struct *s) {
/**
* \brief convert a SSH string to a C nul-terminated string
* \param s the input SSH string
* \param str the input SSH string
* \return a malloc'ed string pointer.
* \warning If the input SSH string contains zeroes, some parts of
* the output string may not be readable with regular libc functions.
*/
char *string_to_char(struct ssh_string_struct *s) {
char *string_to_char(struct string_struct *s) {
size_t len = ntohl(s->size) + 1;
char *new = malloc(len);
@@ -134,8 +135,8 @@ char *string_to_char(struct ssh_string_struct *s) {
*
* @return Newly allocated copy of the string, NULL on error.
*/
struct ssh_string_struct *string_copy(struct ssh_string_struct *s) {
struct ssh_string_struct *new = malloc(ntohl(s->size) + 4);
struct string_struct *string_copy(struct string_struct *s) {
struct string_struct *new = malloc(ntohl(s->size) + 4);
if (new == NULL) {
return NULL;
@@ -149,7 +150,7 @@ struct ssh_string_struct *string_copy(struct ssh_string_struct *s) {
/** \brief destroy data in a string so it couldn't appear in a core dump
* \param s string to burn
*/
void string_burn(struct ssh_string_struct *s) {
void string_burn(struct string_struct *s) {
if (s == NULL) {
return;
}
@@ -163,7 +164,7 @@ void string_burn(struct ssh_string_struct *s) {
*
* @return Return the data of the string or NULL on error.
*/
void *string_data(struct ssh_string_struct *s) {
void *string_data(struct string_struct *s) {
if (s == NULL) {
return NULL;
}
@@ -175,7 +176,7 @@ void *string_data(struct ssh_string_struct *s) {
* \brief deallocate a STRING object
* \param s String to delete
*/
void string_free(struct ssh_string_struct *s) {
void string_free(struct string_struct *s) {
SAFE_FREE(s);
}

View File

@@ -31,19 +31,16 @@
* are welcome.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "libssh/priv.h"
#include "libssh/session.h"
#include "libssh/crypto.h"
#include "libssh/wrapper.h"
#ifdef HAVE_LIBGCRYPT
#include <gcrypt.h>
#include "libssh/crypto.h"
static int alloc_key(struct crypto_struct *cipher) {
cipher->key = malloc(cipher->keylen);
@@ -157,31 +154,29 @@ static void blowfish_decrypt(struct crypto_struct *cipher, void *in,
}
static int aes_set_key(struct crypto_struct *cipher, void *key, void *IV) {
int mode=GCRY_CIPHER_MODE_CBC;
if (cipher->key == NULL) {
if (alloc_key(cipher) < 0) {
return -1;
}
if(strstr(cipher->name,"-ctr"))
mode=GCRY_CIPHER_MODE_CTR;
switch (cipher->keysize) {
case 128:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES128,
mode, 0)) {
GCRY_CIPHER_MODE_CBC, 0)) {
SAFE_FREE(cipher->key);
return -1;
}
break;
case 192:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES192,
mode, 0)) {
GCRY_CIPHER_MODE_CBC, 0)) {
SAFE_FREE(cipher->key);
return -1;
}
break;
case 256:
if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES256,
mode, 0)) {
GCRY_CIPHER_MODE_CBC, 0)) {
SAFE_FREE(cipher->key);
return -1;
}
@@ -191,17 +186,9 @@ static int aes_set_key(struct crypto_struct *cipher, void *key, void *IV) {
SAFE_FREE(cipher->key);
return -1;
}
if(mode == GCRY_CIPHER_MODE_CBC){
if (gcry_cipher_setiv(cipher->key[0], IV, 16)) {
SAFE_FREE(cipher->key);
return -1;
}
} else {
if(gcry_cipher_setctr(cipher->key[0],IV,16)){
SAFE_FREE(cipher->key);
return -1;
}
if (gcry_cipher_setiv(cipher->key[0], IV, 16)) {
SAFE_FREE(cipher->key);
return -1;
}
}
@@ -275,11 +262,11 @@ static int des3_1_set_key(struct crypto_struct *cipher, void *key, void *IV) {
SAFE_FREE(cipher->key);
return -1;
}
if (gcry_cipher_setkey(cipher->key[1], (unsigned char *)key + 8, 8)) {
if (gcry_cipher_setkey(cipher->key[1], key + 8, 8)) {
SAFE_FREE(cipher->key);
return -1;
}
if (gcry_cipher_setiv(cipher->key[1], (unsigned char *)IV + 8, 8)) {
if (gcry_cipher_setiv(cipher->key[1], IV + 8, 8)) {
SAFE_FREE(cipher->key);
return -1;
}
@@ -289,11 +276,11 @@ static int des3_1_set_key(struct crypto_struct *cipher, void *key, void *IV) {
SAFE_FREE(cipher->key);
return -1;
}
if (gcry_cipher_setkey(cipher->key[2], (unsigned char *)key + 16, 8)) {
if (gcry_cipher_setkey(cipher->key[2], key + 16, 8)) {
SAFE_FREE(cipher->key);
return -1;
}
if (gcry_cipher_setiv(cipher->key[2], (unsigned char *)IV + 16, 8)) {
if (gcry_cipher_setiv(cipher->key[2], IV + 16, 8)) {
SAFE_FREE(cipher->key);
return -1;
}
@@ -329,39 +316,6 @@ static struct crypto_struct ssh_ciphertab[] = {
.cbc_encrypt = blowfish_encrypt,
.cbc_decrypt = blowfish_decrypt
},
{
.name = "aes128-ctr",
.blocksize = 16,
.keylen = sizeof(gcry_cipher_hd_t),
.key = NULL,
.keysize = 128,
.set_encrypt_key = aes_set_key,
.set_decrypt_key = aes_set_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_encrypt
},
{
.name = "aes192-ctr",
.blocksize = 16,
.keylen = sizeof(gcry_cipher_hd_t),
.key = NULL,
.keysize = 192,
.set_encrypt_key = aes_set_key,
.set_decrypt_key = aes_set_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_encrypt
},
{
.name = "aes256-ctr",
.blocksize = 16,
.keylen = sizeof(gcry_cipher_hd_t),
.key = NULL,
.keysize = 256,
.set_encrypt_key = aes_set_key,
.set_decrypt_key = aes_set_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_encrypt
},
{
.name = "aes128-cbc",
.blocksize = 16,
@@ -451,7 +405,7 @@ static struct crypto_struct ssh_ciphertab[] = {
#include <openssl/des.h>
#endif
#if (OPENSSL_VERSION_NUMBER<0x00907000L)
#if (OPENSSL_VERSION_NUMBER<0x009070000)
#define OLD_CRYPTO
#endif
@@ -613,30 +567,6 @@ static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out,
unsigned long len, void *IV) {
AES_cbc_encrypt(in, out, len, cipher->key, IV, AES_DECRYPT);
}
#ifndef BROKEN_AES_CTR
/* OpenSSL until 0.9.7c has a broken AES_ctr128_encrypt implementation which
* increments the counter from 2^64 instead of 1. It's better not to use it
*/
/** @internal
* @brief encrypts/decrypts data with stream cipher AES_ctr128. 128 bits is actually
* the size of the CTR counter and incidentally the blocksize, but not the keysize.
* @param len[in] must be a multiple of AES128 block size.
*/
static void aes_ctr128_encrypt(struct crypto_struct *cipher, void *in, void *out,
unsigned long len, void *IV) {
unsigned char tmp_buffer[128/8];
unsigned int num=0;
/* Some things are special with ctr128 :
* In this case, tmp_buffer is not being used, because it is used to store temporary data
* when an encryption is made on lengths that are not multiple of blocksize.
* Same for num, which is being used to store the current offset in blocksize in CTR
* function.
*/
AES_ctr128_encrypt(in, out, len, cipher->key, IV, tmp_buffer, &num);
}
#endif /* BROKEN_AES_CTR */
#endif /* HAS_AES */
#ifdef HAS_DES
@@ -647,11 +577,11 @@ static int des3_set_key(struct crypto_struct *cipher, void *key) {
}
DES_set_odd_parity(key);
DES_set_odd_parity((void*)((uint8_t*)key + 8));
DES_set_odd_parity((void*)((uint8_t*)key + 16));
DES_set_odd_parity(key + 8);
DES_set_odd_parity(key + 16);
DES_set_key_unchecked(key, cipher->key);
DES_set_key_unchecked((void*)((uint8_t*)key + 8), (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)));
DES_set_key_unchecked((void*)((uint8_t*)key + 16), (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)));
DES_set_key_unchecked(key + 8, cipher->key + sizeof(DES_key_schedule));
DES_set_key_unchecked(key + 16, cipher->key + 2 * sizeof(DES_key_schedule));
}
return 0;
@@ -660,16 +590,16 @@ static int des3_set_key(struct crypto_struct *cipher, void *key) {
static void des3_encrypt(struct crypto_struct *cipher, void *in,
void *out, unsigned long len, void *IV) {
DES_ede3_cbc_encrypt(in, out, len, cipher->key,
(void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)),
(void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)),
cipher->key + sizeof(DES_key_schedule),
cipher->key + 2 * sizeof(DES_key_schedule),
IV, 1);
}
static void des3_decrypt(struct crypto_struct *cipher, void *in,
void *out, unsigned long len, void *IV) {
DES_ede3_cbc_encrypt(in, out, len, cipher->key,
(void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)),
(void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)),
cipher->key + sizeof(DES_key_schedule),
cipher->key + 2 * sizeof(DES_key_schedule),
IV, 0);
}
@@ -679,10 +609,10 @@ static void des3_1_encrypt(struct crypto_struct *cipher, void *in,
ssh_print_hexa("Encrypt IV before", IV, 24);
#endif
DES_ncbc_encrypt(in, out, len, cipher->key, IV, 1);
DES_ncbc_encrypt(out, in, len, (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)),
(void*)((uint8_t*)IV + 8), 0);
DES_ncbc_encrypt(in, out, len, (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)),
(void*)((uint8_t*)IV + 16), 1);
DES_ncbc_encrypt(out, in, len, cipher->key + sizeof(DES_key_schedule),
IV + 8, 0);
DES_ncbc_encrypt(in, out, len, cipher->key + 2 * sizeof(DES_key_schedule),
IV + 16, 1);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Encrypt IV after", IV, 24);
#endif
@@ -694,11 +624,11 @@ static void des3_1_decrypt(struct crypto_struct *cipher, void *in,
ssh_print_hexa("Decrypt IV before", IV, 24);
#endif
DES_ncbc_encrypt(in, out, len, (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)),
DES_ncbc_encrypt(in, out, len, cipher->key + 2 * sizeof(DES_key_schedule),
IV, 0);
DES_ncbc_encrypt(out, in, len, (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)),
(void*)((uint8_t*)IV + 8), 1);
DES_ncbc_encrypt(in, out, len, cipher->key, (void*)((uint8_t*)IV + 16), 0);
DES_ncbc_encrypt(out, in, len, cipher->key + sizeof(DES_key_schedule),
IV + 8, 1);
DES_ncbc_encrypt(in, out, len, cipher->key, IV + 16, 0);
#ifdef DEBUG_CRYPTO
ssh_print_hexa("Decrypt IV after", IV, 24);
@@ -707,130 +637,90 @@ static void des3_1_decrypt(struct crypto_struct *cipher, void *in,
#endif /* HAS_DES */
/*
* The table of supported ciphers
*
* WARNING: If you modify crypto_struct, you must make sure the order is
* correct!
*/
/* the table of supported ciphers */
static struct crypto_struct ssh_ciphertab[] = {
#ifdef HAS_BLOWFISH
{
"blowfish-cbc",
8,
sizeof (BF_KEY),
NULL,
128,
blowfish_set_key,
blowfish_set_key,
blowfish_encrypt,
blowfish_decrypt
.name = "blowfish-cbc",
.blocksize = 8,
.keylen = sizeof (BF_KEY),
.key = NULL,
.keysize = 128,
.set_encrypt_key = blowfish_set_key,
.set_decrypt_key = blowfish_set_key,
.cbc_encrypt = blowfish_encrypt,
.cbc_decrypt = blowfish_decrypt
},
#endif /* HAS_BLOWFISH */
#ifdef HAS_AES
#ifndef BROKEN_AES_CTR
{
"aes128-ctr",
16,
sizeof(AES_KEY),
NULL,
128,
aes_set_encrypt_key,
aes_set_encrypt_key,
aes_ctr128_encrypt,
aes_ctr128_encrypt
.name = "aes128-cbc",
.blocksize = 16,
.keylen = sizeof(AES_KEY),
.key = NULL,
.keysize = 128,
.set_encrypt_key = aes_set_encrypt_key,
.set_decrypt_key = aes_set_decrypt_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_decrypt
},
{
"aes192-ctr",
16,
sizeof(AES_KEY),
NULL,
192,
aes_set_encrypt_key,
aes_set_encrypt_key,
aes_ctr128_encrypt,
aes_ctr128_encrypt
.name = "aes192-cbc",
.blocksize = 16,
.keylen = sizeof(AES_KEY),
.key = NULL,
.keysize = 192,
.set_encrypt_key = aes_set_encrypt_key,
.set_decrypt_key = aes_set_decrypt_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_decrypt
},
{
"aes256-ctr",
16,
sizeof(AES_KEY),
NULL,
256,
aes_set_encrypt_key,
aes_set_encrypt_key,
aes_ctr128_encrypt,
aes_ctr128_encrypt
},
#endif /* BROKEN_AES_CTR */
{
"aes128-cbc",
16,
sizeof(AES_KEY),
NULL,
128,
aes_set_encrypt_key,
aes_set_decrypt_key,
aes_encrypt,
aes_decrypt
},
{
"aes192-cbc",
16,
sizeof(AES_KEY),
NULL,
192,
aes_set_encrypt_key,
aes_set_decrypt_key,
aes_encrypt,
aes_decrypt
},
{
"aes256-cbc",
16,
sizeof(AES_KEY),
NULL,
256,
aes_set_encrypt_key,
aes_set_decrypt_key,
aes_encrypt,
aes_decrypt
.name = "aes256-cbc",
.blocksize = 16,
.keylen = sizeof(AES_KEY),
.key = NULL,
.keysize = 256,
.set_encrypt_key = aes_set_encrypt_key,
.set_decrypt_key = aes_set_decrypt_key,
.cbc_encrypt = aes_encrypt,
.cbc_decrypt = aes_decrypt
},
#endif /* HAS_AES */
#ifdef HAS_DES
{
"3des-cbc",
8,
sizeof(DES_key_schedule) * 3,
NULL,
192,
des3_set_key,
des3_set_key,
des3_encrypt,
des3_decrypt
.name = "3des-cbc",
.blocksize = 8,
.keylen = sizeof(DES_key_schedule) * 3,
.key = NULL,
.keysize = 192,
.set_encrypt_key = des3_set_key,
.set_decrypt_key = des3_set_key,
.cbc_encrypt = des3_encrypt,
.cbc_decrypt = des3_decrypt
},
{
"3des-cbc-ssh1",
8,
sizeof(DES_key_schedule) * 3,
NULL,
192,
des3_set_key,
des3_set_key,
des3_1_encrypt,
des3_1_decrypt
.name = "3des-cbc-ssh1",
.blocksize = 8,
.keylen = sizeof(DES_key_schedule) * 3,
.key = NULL,
.keysize = 192,
.set_encrypt_key = des3_set_key,
.set_decrypt_key = des3_set_key,
.cbc_encrypt = des3_1_encrypt,
.cbc_decrypt = des3_1_decrypt
},
#endif /* HAS_DES */
{
NULL,
0,
0,
NULL,
0,
NULL,
NULL,
NULL,
NULL
.name = NULL,
.blocksize = 0,
.keylen = 0,
.key = NULL,
.keysize = 0,
.set_encrypt_key = NULL,
.set_decrypt_key = NULL,
.cbc_encrypt = NULL,
.cbc_decrypt = NULL
}
};
#endif /* OPENSSL_CRYPTO */
@@ -873,18 +763,20 @@ static void cipher_free(struct crypto_struct *cipher) {
SAFE_FREE(cipher);
}
struct ssh_crypto_struct *crypto_new(void) {
struct ssh_crypto_struct *crypto;
CRYPTO *crypto_new(void) {
CRYPTO *crypto;
crypto = malloc(sizeof(struct ssh_crypto_struct));
crypto = malloc(sizeof(CRYPTO));
if (crypto == NULL) {
return NULL;
}
ZERO_STRUCTP(crypto);
memset(crypto, 0, sizeof(CRYPTO));
return crypto;
}
void crypto_free(struct ssh_crypto_struct *crypto){
void crypto_free(CRYPTO *crypto){
if (crypto == NULL) {
return;
}
@@ -906,7 +798,7 @@ void crypto_free(struct ssh_crypto_struct *crypto){
SAFE_FREE(crypto);
}
static int crypt_set_algorithms2(ssh_session session){
static int crypt_set_algorithms2(SSH_SESSION *session){
const char *wanted;
int i = 0;
@@ -963,7 +855,7 @@ static int crypt_set_algorithms2(ssh_session session){
return SSH_OK;
}
static int crypt_set_algorithms1(ssh_session session) {
static int crypt_set_algorithms1(SSH_SESSION *session) {
int i = 0;
/* right now, we force 3des-cbc to be taken */
@@ -992,13 +884,13 @@ static int crypt_set_algorithms1(ssh_session session) {
return SSH_OK;
}
int crypt_set_algorithms(ssh_session session) {
int crypt_set_algorithms(SSH_SESSION *session) {
return (session->version == 1) ? crypt_set_algorithms1(session) :
crypt_set_algorithms2(session);
}
// TODO Obviously too much cut and paste here
int crypt_set_algorithms_server(ssh_session session){
int crypt_set_algorithms_server(SSH_SESSION *session){
char *server = NULL;
char *client = NULL;
char *match = NULL;
@@ -1009,8 +901,7 @@ int crypt_set_algorithms_server(ssh_session session){
/* out */
server = session->server_kex.methods[SSH_CRYPT_S_C];
client = session->client_kex.methods[SSH_CRYPT_S_C];
/* That's the client algorithms that are more important */
match = ssh_find_matching(server,client);
match = ssh_find_matching(client,server);
if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server);
@@ -1039,7 +930,7 @@ int crypt_set_algorithms_server(ssh_session session){
/* in */
client=session->client_kex.methods[SSH_CRYPT_C_S];
server=session->server_kex.methods[SSH_CRYPT_S_C];
match=ssh_find_matching(server,client);
match=ssh_find_matching(client,server);
if(!match){
ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server : no matching algorithm function found for %s",server);
free(match);
@@ -1067,37 +958,36 @@ int crypt_set_algorithms_server(ssh_session session){
/* compression */
client=session->client_kex.methods[SSH_CRYPT_C_S];
server=session->server_kex.methods[SSH_CRYPT_C_S];
match=ssh_find_matching(server,client);
match=ssh_find_matching(client,server);
if(match && !strcmp(match,"zlib")){
ssh_log(session,SSH_LOG_PACKET,"enabling C->S compression");
session->next_crypto->do_compress_in=1;
}
SAFE_FREE(match);
free(match);
client=session->client_kex.methods[SSH_CRYPT_S_C];
server=session->server_kex.methods[SSH_CRYPT_S_C];
match=ssh_find_matching(server,client);
match=ssh_find_matching(client,server);
if(match && !strcmp(match,"zlib")){
ssh_log(session,SSH_LOG_PACKET,"enabling S->C compression\n");
session->next_crypto->do_compress_out=1;
}
SAFE_FREE(match);
free(match);
server=session->server_kex.methods[SSH_HOSTKEYS];
client=session->client_kex.methods[SSH_HOSTKEYS];
match=ssh_find_matching(server,client);
if(match && !strcmp(match,"ssh-dss"))
match=ssh_find_matching(client,server);
if(!strcmp(match,"ssh-dss"))
session->hostkeys=TYPE_DSS;
else if(match && !strcmp(match,"ssh-rsa"))
else if(!strcmp(match,"ssh-rsa"))
session->hostkeys=TYPE_RSA;
else {
ssh_set_error(session, SSH_FATAL, "Cannot know what %s is into %s",
match ? match : NULL, server);
SAFE_FREE(match);
ssh_set_error(session,SSH_FATAL,"cannot know what %s is into %s",match,server);
free(match);
leave_function();
return SSH_ERROR;
}
SAFE_FREE(match);
free(match);
leave_function();
return SSH_OK;
}

567
sample.c Normal file
View File

@@ -0,0 +1,567 @@
/* client.c */
/*
Copyright 2003 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/libssh.h>
#include <libssh/sftp.h>
#include <fcntl.h>
#define MAXCMD 10
char *host;
char *user;
int sftp;
char *cmds[MAXCMD];
struct termios terminal;
void do_sftp(SSH_SESSION *session);
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",
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv){
int i;
if(strstr(argv[0],"sftp"))
sftp=1;
// for(i=0;i<argc;i++)
// printf("%d : %s\n",i,argv[i]);
/* insert your own arguments here */
while((i=getopt(argc,argv,""))!=-1){
switch(i){
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);
}
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);
channel_change_pty_size(chan,win.ws_col, win.ws_row);
// printf("Changed pty size\n");
setsignal();
}
static void select_loop(SSH_SESSION *session,CHANNEL *channel){
fd_set fds;
struct timeval timeout;
char buffer[10];
BUFFER *readbuf=buffer_new();
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,10);
if(lus)
channel_write(channel,buffer,lus);
else {
eof=1;
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=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 && channel_is_closed(channel)){
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(channels[0]){
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
lus=channel_read_buffer(channel,readbuf,0,0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
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
write(1,buffer_get(readbuf),lus);
}
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
lus=channel_read_buffer(channel,readbuf,0,1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
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
write(2,buffer_get(readbuf),lus);
}
}
if(channel && channel_is_closed(channel)){
channel_free(channel);
channel=NULL;
}
}
buffer_free(readbuf);
}
static void shell(SSH_SESSION *session){
CHANNEL *channel;
struct termios terminal_local;
int interactive=isatty(0);
channel = channel_new(session);
if(interactive){
tcgetattr(0,&terminal_local);
memcpy(&terminal,&terminal_local,sizeof(struct termios));
}
if(channel_open_session(channel)){
printf("error opening channel : %s\n",ssh_get_error(session));
return;
}
chan=channel;
if(interactive){
channel_request_pty(channel);
sizechanged();
}
if(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);
}
static void batch_shell(SSH_SESSION *session){
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]);
channel=channel_new(session);
channel_open_session(channel);
if(channel_request_exec(channel,buffer)){
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
return;
}
select_loop(session,channel);
}
#ifdef WITH_SFTP
/* it's just a proof of concept code for sftp, till i write a real documentation about it */
void do_sftp(SSH_SESSION *session){
SFTP_SESSION *sftp_session=sftp_new(session);
SFTP_DIR *dir;
SFTP_ATTRIBUTES *file;
SFTP_FILE *fichier;
SFTP_FILE *to;
int len=1;
int i;
char data[8000];
if(!sftp_session){
fprintf(stderr, "sftp error initialising channel: %s\n",
ssh_get_error(session));
return;
}
if(sftp_init(sftp_session)){
fprintf(stderr, "error initialising sftp: %s\n",
ssh_get_error(session));
return;
}
/* the connection is made */
/* opening a directory */
dir=sftp_opendir(sftp_session,"./");
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_session,dir))){
fprintf(stderr, "%30s(%.8o) : %.5d.%.5d : %.10llu bytes\n",
file->name,
file->permissions,
file->uid,
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_session,"/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_session,"ssh-copy",O_WRONLY | O_CREAT, 0);
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_session,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
for(i=0;i<1000;++i){
len=sftp_write(to,data,8000);
printf("wrote %d bytes\n",len);
if(len != 8000){
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
}
}
sftp_close(to);
/* close the sftp session */
sftp_free(sftp_session);
printf("session sftp termin<69>\n");
}
#endif
static int auth_kbdint(SSH_SESSION *session){
int err=ssh_userauth_kbdint(session,NULL,NULL);
char *name,*instruction,*prompt,*ptr;
char buffer[128];
int i,n;
char echo;
while (err==SSH_AUTH_INFO){
name=ssh_userauth_kbdint_getname(session);
instruction=ssh_userauth_kbdint_getinstruction(session);
n=ssh_userauth_kbdint_getnprompts(session);
if(strlen(name)>0)
printf("%s\n",name);
if(strlen(instruction)>0)
printf("%s\n",instruction);
for(i=0;i<n;++i){
prompt=ssh_userauth_kbdint_getprompt(session,i,&echo);
if(echo){
printf("%s",prompt);
fgets(buffer,sizeof(buffer),stdin);
buffer[sizeof(buffer)-1]=0;
if((ptr=strchr(buffer,'\n')))
*ptr=0;
if (ssh_userauth_kbdint_setanswer(session,i,buffer) < 0) {
return SSH_AUTH_ERROR;
}
memset(buffer,0,strlen(buffer));
} else {
ptr=getpass(prompt);
if (ssh_userauth_kbdint_setanswer(session,i,ptr) < 0) {
return SSH_AUTH_ERROR;
}
}
}
err=ssh_userauth_kbdint(session,NULL,NULL);
}
return err;
}
int main(int argc, char **argv){
SSH_SESSION *session;
SSH_OPTIONS *options;
int auth=0;
char *password;
char *banner;
char *hexa;
int state;
char buf[10];
unsigned char *hash = NULL;
int hlen;
options=ssh_options_new();
if(ssh_options_getopt(options,&argc, argv)){
fprintf(stderr,"error parsing command line :%s\n",ssh_get_error(options));
usage();
}
opts(argc,argv);
signal(SIGTERM, do_exit);
if (user) {
if (ssh_options_set_username(options,user) < 0) {
ssh_options_free(options);
return 1;
}
}
if (ssh_options_set_host(options,host) < 0) {
ssh_options_free(options);
return 1;
}
session=ssh_new();
ssh_set_options(session,options);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
ssh_disconnect(session);
ssh_finalize();
return 1;
}
state=ssh_is_server_known(session);
hlen = ssh_get_pubkey_hash(session, &hash);
if (hlen < 0) {
ssh_disconnect(session);
ssh_finalize();
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);
free(hash);
fprintf(stderr,"For security reason, connection will be stopped\n");
ssh_disconnect(session);
ssh_finalize();
exit(-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");
ssh_disconnect(session);
ssh_finalize();
exit(-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 behaviour */
case SSH_SERVER_NOT_KNOWN:
hexa = ssh_get_hexa(hash, hlen);
free(hash);
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
free(hexa);
fgets(buf,sizeof(buf),stdin);
if(strncasecmp(buf,"yes",3)!=0){
ssh_disconnect(session);
exit(-1);
}
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
fgets(buf,sizeof(buf),stdin);
if(strncasecmp(buf,"yes",3)==0){
if(ssh_write_knownhost(session))
fprintf(stderr,"error %s\n",ssh_get_error(session));
}
break;
case SSH_SERVER_ERROR:
free(hash);
fprintf(stderr,"%s",ssh_get_error(session));
ssh_disconnect(session);
ssh_finalize();
exit(-1);
}
free(hash);
ssh_userauth_none(session, NULL);
auth = ssh_auth_list(session);
printf("auth: 0x%04x\n", auth);
printf("supported auth methods: ");
if (auth & SSH_AUTH_METHOD_PUBLICKEY) {
printf("publickey");
}
if (auth & SSH_AUTH_METHOD_INTERACTIVE) {
printf(", keyboard-interactive");
}
printf("\n");
/* no ? you should :) */
auth=ssh_userauth_autopubkey(session, NULL);
if(auth==SSH_AUTH_ERROR){
fprintf(stderr,"Authenticating with pubkey: %s\n",ssh_get_error(session));
ssh_finalize();
return -1;
}
banner=ssh_get_issue_banner(session);
if(banner){
printf("%s\n",banner);
free(banner);
}
if(auth!=SSH_AUTH_SUCCESS){
auth=auth_kbdint(session);
if(auth==SSH_AUTH_ERROR){
fprintf(stderr,"authenticating with keyb-interactive: %s\n",
ssh_get_error(session));
ssh_finalize();
return -1;
}
}
if(auth!=SSH_AUTH_SUCCESS){
password=getpass("Password: ");
if(ssh_userauth_password(session,NULL,password) != SSH_AUTH_SUCCESS){
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
ssh_disconnect(session);
ssh_finalize();
return -1;
}
memset(password,0,strlen(password));
}
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
if(strstr(argv[0],"sftp")){
sftp=1;
ssh_log(session, SSH_LOG_FUNCTIONS, "Doing sftp instead");
}
if(!sftp){
if(!cmds[0])
shell(session);
else
batch_shell(session);
}
else
do_sftp(session);
if(!sftp && !cmds[0])
do_cleanup(0);
ssh_disconnect(session);
ssh_finalize();
return 0;
}

158
samplesshd.c Normal file
View File

@@ -0,0 +1,158 @@
/* sshd.c */
/* yet another ssh daemon (Yawn!) */
/*
Copyright 2004 Aris Adamantiadis
This file is part of the SSH Library
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 <libssh/libssh.h>
#include <libssh/server.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#ifdef _WIN32
#define KEYS_FOLDER
#else
#define KEYS_FOLDER "/etc/ssh/"
#endif
static int auth_password(char *user, char *password){
if(strcmp(user,"aris"))
return 0;
if(strcmp(password,"lala"))
return 0;
return 1; // authenticated
}
int main(int argc, char **argv){
SSH_OPTIONS *options=ssh_options_new();
SSH_SESSION *session;
SSH_BIND *ssh_bind;
SSH_MESSAGE *message;
CHANNEL *chan=0;
BUFFER *buf;
int auth=0;
int sftp=0;
int i;
ssh_options_getopt(options,&argc,argv);
ssh_options_set_dsa_server_key(options, KEYS_FOLDER "ssh_host_dsa_key");
ssh_options_set_rsa_server_key(options, KEYS_FOLDER "ssh_host_rsa_key");
ssh_bind=ssh_bind_new();
ssh_bind_set_options(ssh_bind,options);
if(ssh_bind_listen(ssh_bind)<0){
printf("Error listening to socket: %s\n",ssh_get_error(ssh_bind));
return 1;
}
session=ssh_bind_accept(ssh_bind);
if(!session){
printf("error accepting a connection : %s\n",ssh_get_error(ssh_bind));
return 1;
}
printf("Socket connected: fd = %d\n", ssh_get_fd(session));
if(ssh_accept(session)){
printf("ssh_accept: %s\n",ssh_get_error(session));
return 1;
}
do {
message=ssh_message_get(session);
if(!message)
break;
switch(ssh_message_type(message)){
case SSH_AUTH_REQUEST:
switch(ssh_message_subtype(message)){
case SSH_AUTH_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_NONE:
default:
ssh_message_auth_set_methods(message,SSH_AUTH_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_finalize();
return 1;
}
do {
message=ssh_message_get(session);
if(message){
switch(ssh_message_type(message)){
case SSH_CHANNEL_REQUEST_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_CHANNEL_REQUEST &&
ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){
// if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){
sftp=1;
ssh_message_channel_request_reply_success(message);
break;
// }
}
if(!sftp){
ssh_message_reply_default(message);
}
ssh_message_free(message);
} while (message && !sftp);
if(!sftp){
printf("error : %s\n",ssh_get_error(session));
return 1;
}
printf("it works !\n");
buf=buffer_new();
do{
i=channel_read_buffer(chan,buf,0,0);
if(i>0)
write(1,buffer_get(buf),buffer_get_len(buf));
} while (i>0);
buffer_free(buf);
ssh_disconnect(session);
ssh_bind_free(ssh_bind);
ssh_finalize();
return 0;
}

View File

@@ -1,4 +1,4 @@
all: test_tunnel test_exec test_pcap
all: test_tunnel test_exec
CFLAGS=-I../include/ -g -Wall
LDFLAGS=-lssh -L../build/libssh/
@@ -8,8 +8,5 @@ test_tunnel: test_tunnel.o authentication.o connection.o
test_exec: test_exec.o authentication.o connection.o
gcc -o $@ $^ $(LDFLAGS)
test_pcap: test_pcap.o
gcc -o $@ $^ $(LDFLAGS)
clean:
rm -f *.o test_tunnel

View File

@@ -1,13 +0,0 @@
export CIPHER=aes128-cbc
export DEST=localhost
echo "Upload raw SSH statistics"
echo "local machine: `uname -a`"
echo "Cipher : $CIPHER ; Destination : $DEST (`ssh $DEST uname -a`)"
echo "Local ssh version: `ssh -V 2>&1`"
echo "Ping latency to $DEST":
ping -q -c 1 -n $DEST
echo "Destination $DEST SSHD vesion : `echo | nc $DEST 22 | head -n1`"
echo "ssh login latency :`(time -f user:%U ssh $DEST 'id > /dev/null') 2>&1`"
./generate.py | dd bs=4096 count=100000 | time ssh -c $CIPHER $DEST "dd bs=4096 of=/dev/null" 2>&1

View File

@@ -1,13 +0,0 @@
export CIPHER=aes128-cbc
export DEST=localhost
echo "Upload raw SSH statistics"
echo "local machine: `uname -a`"
echo "Cipher : $CIPHER ; Destination : $DEST (`ssh $DEST uname -a`)"
echo "Local ssh version: `samplessh -V 2>&1`"
echo "Ping latency to $DEST":
ping -q -c 1 -n $DEST
echo "Destination $DEST SSHD vesion : `echo | nc $DEST 22 | head -n1`"
echo "ssh login latency :`(time -f user:%U samplessh $DEST 'id > /dev/null') 2>&1`"
./generate.py | dd bs=4096 count=100000 | strace samplessh -c $CIPHER $DEST "dd bs=4096 of=/dev/null" 2>&1

View File

@@ -1,10 +0,0 @@
#!/usr/bin/python
import os
a=""
for i in xrange(4096):
a+=chr(i % 256);
while True:
try:
os.write(1,a)
except:
exit(0)

View File

@@ -1,174 +0,0 @@
/*
* main.c
*
* Created on: 22 juin 2009
* Author: aris
*/
#include <stdio.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include <time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <pthread.h>
#define TEST_READ 1
#define TEST_WRITE 2
#define NTHREADS 3
#define FILESIZE 100000
unsigned char samplefile[FILESIZE];
volatile int stop=0;
const char* hosts[]={"localhost","barebone"};
void signal_stop(){
stop=1;
printf("Stopping...\n");
}
SSH_SESSION *connect_host(const char *hostname);
int sftp_test(SSH_SESSION *session, int test);
int docycle(const char *host, int test){
SSH_SESSION *session=connect_host(host);
int ret=SSH_ERROR;
if(!session){
printf("connect failed\n");
} else {
printf("Connected\n");
ret=sftp_test(session,test);
if(ret != SSH_OK){
printf("Error in sftp\n");
}
ssh_disconnect(session);
}
return ret;
}
int thread(){
while(docycle(hosts[rand()%2],TEST_WRITE) == SSH_OK)
if(stop)
break;
return 0;
}
int main(int argc, char **argv){
int i;
pthread_t threads[NTHREADS];
ssh_init();
srand(time(NULL));
for(i=0;i<FILESIZE;++i)
samplefile[i]=rand() & 0xff;
signal(SIGTERM,signal_stop);
signal(SIGINT,signal_stop);
for(i=0;i<NTHREADS;++i){
srand(i);
pthread_create(&threads[i],NULL,(void *) thread, NULL);
}
for(i=0;i<NTHREADS;++i){
pthread_join(threads[i],NULL);
}
ssh_finalize();
printf("Ended\n");
return 0;
}
SSH_SESSION *connect_host(const char *hostname){
SSH_SESSION *session;
SSH_OPTIONS *options;
int auth=0;
int state;
options=ssh_options_new();
ssh_options_set_host(options,hostname);
session=ssh_new();
ssh_set_options(session,options);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
ssh_disconnect(session);
return NULL;
}
state=ssh_is_server_known(session);
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");
fprintf(stderr,"For security reason, connection will be stopped\n");
ssh_disconnect(session);
ssh_finalize();
return NULL;
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");
ssh_disconnect(session);
ssh_finalize();
return NULL;
case SSH_SERVER_NOT_KNOWN:
fprintf(stderr,"The server is unknown. Leaving now");
ssh_disconnect(session);
return NULL;
case SSH_SERVER_ERROR:
fprintf(stderr,"%s",ssh_get_error(session));
ssh_disconnect(session);
return NULL;
}
ssh_userauth_none(session, NULL);
auth=ssh_userauth_autopubkey(session, NULL);
if(auth==SSH_AUTH_ERROR){
fprintf(stderr,"Authenticating with pubkey: %s\n",ssh_get_error(session));
ssh_disconnect(session);
return NULL;
}
if(auth!=SSH_AUTH_SUCCESS){
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
ssh_disconnect(session);
return NULL;
}
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
return session;
}
int sftp_test(SSH_SESSION *session, int test){
SFTP_SESSION *sftp=sftp_new(session);
SFTP_FILE *file;
int wrote=0;
char name[128];
if(sftp == NULL)
return SSH_ERROR;
if(sftp_init(sftp)<0){
printf("problem initializing sftp : %s\n",ssh_get_error(session));
return SSH_ERROR;
}
if(test==TEST_WRITE){
snprintf(name,sizeof(name),"/tmp/libsshstress%d",rand());
file=sftp_open(sftp,name,O_RDWR|O_CREAT,0777);
if(!file){
printf("Failed to open file : %s\n",ssh_get_error(session));
sftp_free(sftp);
return SSH_ERROR;
}
while(wrote<FILESIZE){
int max=FILESIZE-wrote;
int towrite=rand()%max + 1;
int ret=sftp_write(file,&samplefile[wrote],towrite);
if(ret<=0){
printf("Problem while writing : %s\n",ssh_get_error(session));
sftp_free(sftp);
return SSH_ERROR;
}
if(ret != towrite){
printf("Asked to write %d, wrote %d\n",towrite,ret);
}
wrote += ret;
}
sftp_close(file);
}
sftp_free(sftp);
return SSH_OK;
}

Some files were not shown because too many files have changed in this diff Show More