mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 21:00:33 +09:00
Compare commits
107 Commits
libssh-0.6
...
libssh-0.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
319129399d | ||
|
|
87ae95eb3c | ||
|
|
055f102601 | ||
|
|
2d6862ddb9 | ||
|
|
22aa60d506 | ||
|
|
4b02bbbd32 | ||
|
|
31ded2070e | ||
|
|
df3d53e561 | ||
|
|
f28c3099da | ||
|
|
32a106c70d | ||
|
|
5d75090d9f | ||
|
|
32a3cfe661 | ||
|
|
1c59844dfe | ||
|
|
f071954a76 | ||
|
|
a033b93c61 | ||
|
|
b7856780a9 | ||
|
|
8b3425865a | ||
|
|
a30e234c03 | ||
|
|
bbf172a79c | ||
|
|
f28748578d | ||
|
|
36f7d1a614 | ||
|
|
71241ca68c | ||
|
|
bfbf9283d0 | ||
|
|
d75573e665 | ||
|
|
8fe36e3d07 | ||
|
|
f2e9ce68e7 | ||
|
|
cfb4d27c47 | ||
|
|
d366e289f3 | ||
|
|
2fc8347504 | ||
|
|
2691ed595e | ||
|
|
7b133cf9f5 | ||
|
|
9b59f1a222 | ||
|
|
8f21f879d3 | ||
|
|
67752dabfc | ||
|
|
34ac4e4248 | ||
|
|
1928fb6a85 | ||
|
|
5b1678f197 | ||
|
|
8aff91dfcb | ||
|
|
c0cc12d582 | ||
|
|
a162071f9a | ||
|
|
2091dab273 | ||
|
|
7f18ec4620 | ||
|
|
8e698382db | ||
|
|
ce10d40325 | ||
|
|
3fed9a5aff | ||
|
|
da0c77fdb1 | ||
|
|
818c80baed | ||
|
|
bb55bb2daf | ||
|
|
fdced9d544 | ||
|
|
96db44ff17 | ||
|
|
70dbbfa320 | ||
|
|
1118fc2adf | ||
|
|
257449a0b6 | ||
|
|
8752460df4 | ||
|
|
6f089a098b | ||
|
|
8b3be050c9 | ||
|
|
ade33474be | ||
|
|
dbf7749696 | ||
|
|
2db45dd547 | ||
|
|
87145387aa | ||
|
|
d027460792 | ||
|
|
3fdd82f2a8 | ||
|
|
6cd94a63ff | ||
|
|
e85b20ba82 | ||
|
|
78d5d64b38 | ||
|
|
f73a44c223 | ||
|
|
1cccfdf8a0 | ||
|
|
abe4ed0e75 | ||
|
|
e7f831f0a3 | ||
|
|
4ea4e12df2 | ||
|
|
fb49e194df | ||
|
|
13f4e31ad1 | ||
|
|
da5fa4ef66 | ||
|
|
dca415a38e | ||
|
|
56f86cd4a1 | ||
|
|
f265afacfb | ||
|
|
99f8b2b803 | ||
|
|
22edaf43ee | ||
|
|
497bd31364 | ||
|
|
8ed0c0b3c8 | ||
|
|
ce39d2fa73 | ||
|
|
90d3768f0f | ||
|
|
6f66032209 | ||
|
|
c571cd8402 | ||
|
|
b049e12652 | ||
|
|
785682ac28 | ||
|
|
f29f10876a | ||
|
|
45d28c7682 | ||
|
|
2786565e77 | ||
|
|
96ad690c80 | ||
|
|
0d82186503 | ||
|
|
5157d96958 | ||
|
|
6a0787a366 | ||
|
|
709e921942 | ||
|
|
43a69b0a65 | ||
|
|
18506f697c | ||
|
|
15bede0c0e | ||
|
|
92dde09a37 | ||
|
|
809d76cbf2 | ||
|
|
f78a74c160 | ||
|
|
b3b3045a81 | ||
|
|
72fd3a73df | ||
|
|
cf19770ede | ||
|
|
7f42f5a3c9 | ||
|
|
6223e05b23 | ||
|
|
634671db11 | ||
|
|
1f689261ec |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@
|
||||
build
|
||||
cscope.*
|
||||
tags
|
||||
build
|
||||
|
||||
@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
|
||||
set(APPLICATION_VERSION_MAJOR "0")
|
||||
set(APPLICATION_VERSION_MINOR "6")
|
||||
set(APPLICATION_VERSION_PATCH "0")
|
||||
set(APPLICATION_VERSION_PATCH "4")
|
||||
|
||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||
|
||||
@@ -19,7 +19,7 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.3.0")
|
||||
set(LIBRARY_VERSION "4.5.0")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
@@ -97,18 +97,22 @@ install(
|
||||
)
|
||||
|
||||
# cmake config files
|
||||
configure_file(libssh-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-config.cmake @ONLY)
|
||||
configure_file(libssh-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-config-version.cmake @ONLY)
|
||||
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
set(LIBSSH_THREADS_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
configure_file(${PROJECT_NAME}-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake @ONLY)
|
||||
configure_file(${PROJECT_NAME}-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake @ONLY)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh-config-version.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_DIR}
|
||||
${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
|
||||
COMPONENT
|
||||
devel
|
||||
)
|
||||
|
||||
|
||||
# in tree build settings
|
||||
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSIO
|
||||
|
||||
### source generator
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;/obj/;tags;cscope.*")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
if (WIN32)
|
||||
|
||||
33
ChangeLog
33
ChangeLog
@@ -1,6 +1,39 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.6.4 (released 2014-12-19)
|
||||
* Fixed CVE-2014-8132.
|
||||
* Added SHA-2 for session ID signing with ECDSA keys.
|
||||
* Added support for ECDSA host keys.
|
||||
* Added support for more ECDSA hostkey algorithms.
|
||||
* Added ssh_pki_key_ecdsa_name() API.
|
||||
* Fixed setting the bindfd only after successful listen.
|
||||
* Fixed issues with user created sockets.
|
||||
* Fixed several issues in libssh C++ wrapper.
|
||||
* Fixed several documentation issues.
|
||||
* Fixed channel exit-signal request.
|
||||
* Fixed X11 request screen number in messages.
|
||||
* Fixed several memory leaks.
|
||||
|
||||
version 0.6.3 (released 2014-03-04)
|
||||
* Fixed CVE-2014-0017.
|
||||
* Fixed memory leak with ecdsa signatures.
|
||||
|
||||
version 0.6.2 (released 2014-03-04)
|
||||
* security: fix for vulnerability CVE-2014-0017
|
||||
|
||||
version 0.6.1 (released 2014-02-08)
|
||||
* Added support for libgcrypt 1.6.
|
||||
* Added ssh_channel_accept_forward().
|
||||
* Added known_hosts heuristic during connection (#138).
|
||||
* Added getters for session cipher names.
|
||||
* Fixed decrypt of zero length buffer.
|
||||
* Fixed padding in RSA signature blobs.
|
||||
* Fixed DSA signature extraction.
|
||||
* Fixed some memory leaks.
|
||||
* Fixed read of non-connected socket.
|
||||
* Fixed thread dectection.
|
||||
|
||||
version 0.6.0 (released 2014-01-08)
|
||||
* Added new publicy key API.
|
||||
* Added new userauth API.
|
||||
|
||||
@@ -51,6 +51,7 @@ check_include_file(pty.h HAVE_PTY_H)
|
||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||
check_include_file(unistd.h HAVE_UNISTD_H)
|
||||
check_include_file(util.h HAVE_UTIL_H)
|
||||
check_include_file(sys/time.h HAVE_SYS_TIME_H)
|
||||
|
||||
if (WIN32)
|
||||
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
|
||||
@@ -169,11 +170,9 @@ if (GCRYPT_FOUND)
|
||||
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
if (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(HAVE_PTHREAD 1)
|
||||
endif (CMAKE_USE_PTHREADS_INIT)
|
||||
endif (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(HAVE_PTHREAD 1)
|
||||
endif (CMAKE_USE_PTHREADS_INIT)
|
||||
|
||||
# OPTIONS
|
||||
check_c_source_compiles("
|
||||
|
||||
@@ -25,3 +25,6 @@ if (NOT CMAKE_BUILD_TYPE)
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
||||
)
|
||||
endif (NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
# Create the compile command database for clang by default
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
@@ -75,3 +75,10 @@ if (MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
|
||||
endif (MSVC)
|
||||
|
||||
# This removes this annoying warning
|
||||
# "warning: 'BN_CTX_free' is deprecated: first deprecated in OS X 10.7 [-Wdeprecated-declarations]"
|
||||
if (OSX)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
|
||||
endif (OSX)
|
||||
|
||||
|
||||
@@ -2,10 +2,18 @@
|
||||
#
|
||||
# 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.
|
||||
# The doxygen target is added to the doc target as a dependency.
|
||||
# i.e.: the API documentation is built with:
|
||||
# make doc
|
||||
#
|
||||
# USAGE: GLOBAL INSTALL
|
||||
#
|
||||
# Install it with:
|
||||
# cmake ./ && sudo make install
|
||||
# Add the following to the CMakeLists.txt of your project:
|
||||
# include(UseDoxygen OPTIONAL)
|
||||
# Optionally copy Doxyfile.in in the directory of CMakeLists.txt and edit it.
|
||||
#
|
||||
# USAGE: INCLUDE IN PROJECT
|
||||
#
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -13,88 +21,120 @@
|
||||
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
|
||||
#
|
||||
#
|
||||
# CONFIGURATION
|
||||
#
|
||||
# To configure Doxygen you can edit Doxyfile.in and set some variables in cmake.
|
||||
# Variables you may define are:
|
||||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
|
||||
#
|
||||
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
|
||||
#
|
||||
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
|
||||
# DOXYFILE_SOURCE_DIR - Path where the Doxygen input files are.
|
||||
# Defaults to the current source directory.
|
||||
# DOXYFILE_EXTRA_SOURCES - Additional source diretories/files for Doxygen to scan.
|
||||
# The Paths should be in double quotes and separated by space. e.g.:
|
||||
# "${CMAKE_CURRENT_BINARY_DIR}/foo.c" "${CMAKE_CURRENT_BINARY_DIR}/bar/"
|
||||
#
|
||||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored.
|
||||
# Defaults to "${CMAKE_CURRENT_BINARY_DIR}/doc".
|
||||
#
|
||||
# DOXYFILE_LATEX - ON/OFF; Set to "ON" if you want the LaTeX documentation
|
||||
# to be built.
|
||||
# DOXYFILE_LATEX_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
|
||||
# the Doxygen LaTeX output is stored. Defaults to "latex".
|
||||
#
|
||||
# DOXYFILE_HTML_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
|
||||
# the Doxygen html output is stored. Defaults to "html".
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2009, 2010, 2011 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
macro(usedoxygen_set_default name value)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}")
|
||||
endif()
|
||||
macro(usedoxygen_set_default name value type docstring)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}" CACHE "${type}" "${docstring}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
find_file(DOXYFILE_IN
|
||||
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")
|
||||
find_file(DOXYFILE_IN "Doxyfile.in"
|
||||
PATHS "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_ROOT}/Modules/"
|
||||
NO_DEFAULT_PATH
|
||||
DOC "Path to the doxygen configuration template file")
|
||||
set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
||||
endif()
|
||||
|
||||
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
|
||||
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
|
||||
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc"
|
||||
PATH "Doxygen output directory")
|
||||
usedoxygen_set_default(DOXYFILE_HTML_DIR "html"
|
||||
STRING "Doxygen HTML output directory")
|
||||
usedoxygen_set_default(DOXYFILE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
PATH "Input files source directory")
|
||||
usedoxygen_set_default(DOXYFILE_EXTRA_SOURCE_DIRS ""
|
||||
STRING "Additional source files/directories separated by space")
|
||||
set(DOXYFILE_SOURCE_DIRS "\"${DOXYFILE_SOURCE_DIR}\" ${DOXYFILE_EXTRA_SOURCES}")
|
||||
|
||||
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
|
||||
usedoxygen_set_default(DOXYFILE_LATEX YES BOOL "Generate LaTeX API documentation" OFF)
|
||||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex" STRING "LaTex output directory")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||
mark_as_advanced(DOXYFILE_OUTPUT_DIR DOXYFILE_HTML_DIR DOXYFILE_LATEX_DIR
|
||||
DOXYFILE_SOURCE_DIR DOXYFILE_EXTRA_SOURCE_DIRS DOXYFILE_IN)
|
||||
|
||||
set(DOXYFILE_LATEX FALSE)
|
||||
set(DOXYFILE_PDFLATEX FALSE)
|
||||
set(DOXYFILE_DOT FALSE)
|
||||
|
||||
#find_package(LATEX)
|
||||
#if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
|
||||
# set(DOXYFILE_LATEX TRUE)
|
||||
# usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
|
||||
#
|
||||
# set_property(DIRECTORY APPEND PROPERTY
|
||||
# ADDITIONAL_MAKE_CLEAN_FILES
|
||||
# "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
#
|
||||
# if(PDFLATEX_COMPILER)
|
||||
# set(DOXYFILE_PDFLATEX TRUE)
|
||||
# endif()
|
||||
# if(DOXYGEN_DOT_EXECUTABLE)
|
||||
# set(DOXYFILE_DOT TRUE)
|
||||
# endif()
|
||||
#
|
||||
# add_custom_command(TARGET doxygen
|
||||
# POST_BUILD
|
||||
# COMMAND ${CMAKE_MAKE_PROGRAM}
|
||||
# WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
#endif()
|
||||
set_property(DIRECTORY
|
||||
APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||
|
||||
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
|
||||
endif()
|
||||
add_custom_target(doxygen
|
||||
COMMAND "${DOXYGEN_EXECUTABLE}"
|
||||
"${DOXYFILE}"
|
||||
COMMENT "Writing documentation to ${DOXYFILE_OUTPUT_DIR}..."
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
get_target_property(DOC_TARGET doc TYPE)
|
||||
if(NOT DOC_TARGET)
|
||||
add_custom_target(doc)
|
||||
endif()
|
||||
set(DOXYFILE_DOT "NO")
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
set(DOXYFILE_DOT "YES")
|
||||
endif()
|
||||
|
||||
add_dependencies(doc doxygen)
|
||||
## LaTeX
|
||||
set(DOXYFILE_PDFLATEX "NO")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
|
||||
if(DOXYFILE_LATEX STREQUAL "ON")
|
||||
set(DOXYFILE_GENERATE_LATEX "YES")
|
||||
find_package(LATEX)
|
||||
find_program(DOXYFILE_MAKE make)
|
||||
mark_as_advanced(DOXYFILE_MAKE)
|
||||
if(LATEX_COMPILER AND MAKEINDEX_COMPILER AND DOXYFILE_MAKE)
|
||||
if(PDFLATEX_COMPILER)
|
||||
set(DOXYFILE_PDFLATEX "YES")
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET doxygen
|
||||
POST_BUILD
|
||||
COMMAND "${DOXYFILE_MAKE}"
|
||||
COMMENT "Running LaTeX for Doxygen documentation in ${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}..."
|
||||
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
else()
|
||||
set(DOXYGEN_LATEX "NO")
|
||||
endif()
|
||||
else()
|
||||
set(DOXYFILE_GENERATE_LATEX "NO")
|
||||
endif()
|
||||
|
||||
|
||||
configure_file("${DOXYFILE_IN}" "${DOXYFILE}" @ONLY)
|
||||
|
||||
add_custom_target(doc)
|
||||
add_dependencies(doc doxygen)
|
||||
endif()
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
/* Define to 1 if you have the <util.h> header file. */
|
||||
#cmakedefine HAVE_UTIL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#cmakedefine HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#cmakedefine HAVE_TERMIOS_H 1
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ int authenticate_kbdint(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_none(session, NULL, NULL);
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
@@ -304,7 +304,7 @@ int test_several_auth_methods(ssh_session session)
|
||||
{
|
||||
int method, rc;
|
||||
|
||||
rc = ssh_userauth_none(session, NULL, NULL);
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc != SSH_AUTH_SUCCESS) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
1546
doc/doxy.trac.in
1546
doc/doxy.trac.in
File diff suppressed because it is too large
Load Diff
@@ -145,7 +145,7 @@ or whatever use you have for it.
|
||||
@subsection libssh_reverse Doing reverse port forwarding with libssh
|
||||
|
||||
To do reverse port forwarding, call ssh_forward_listen(),
|
||||
then ssh_forward_accept().
|
||||
then ssh_channel_accept_forward().
|
||||
|
||||
When you call ssh_forward_listen(), you can let the remote server
|
||||
chose the non-priviledged port it should listen to. Otherwise, you can chose
|
||||
@@ -164,6 +164,7 @@ int web_server(ssh_session session)
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
int port;
|
||||
char *helloworld = ""
|
||||
"HTTP/1.1 200 OK\n"
|
||||
"Content-Type: text/html\n"
|
||||
@@ -186,7 +187,7 @@ int web_server(ssh_session session)
|
||||
return rc;
|
||||
}
|
||||
|
||||
channel = ssh_forward_accept(session, 60000);
|
||||
channel = ssh_channel_accept_forward(session, 60000, &port);
|
||||
if (channel == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error waiting for incoming connection: %s\n",
|
||||
|
||||
@@ -443,11 +443,10 @@ Most of time, the error returned are SSH_FATAL, but some functions
|
||||
(generaly the ssh_request_xxx ones) may fail because of server denying request.
|
||||
In these cases, SSH_REQUEST_DENIED is returned.
|
||||
|
||||
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
|
||||
That's for thread safety, error messages that can be attached to a session
|
||||
aren't static anymore. Any error that happens during ssh_options_xxx()
|
||||
or ssh_connect() (i.e., outside of any session) can be retrieved by
|
||||
giving NULL as argument.
|
||||
For thread safety, errors are bound to ssh_session objects.
|
||||
As long as your ssh_session object is not NULL, you can retrieve the last error
|
||||
message and error code from the ssh_session using ssh_get_error() and
|
||||
ssh_get_error_code() respectively.
|
||||
|
||||
The SFTP subsystem has its own error codes, in addition to libssh ones.
|
||||
|
||||
|
||||
@@ -61,5 +61,6 @@ implement the following methods :
|
||||
- mutex_destroy
|
||||
- thread_id
|
||||
|
||||
libgcrypt 1.6 and bigger backend does not support custom callback. Using anything else than pthreads (ssh_threads_get_pthread()) here will fail.
|
||||
Good luck !
|
||||
*/
|
||||
|
||||
@@ -495,6 +495,8 @@ LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
|
||||
* @param len the length of the data
|
||||
* @param is_stderr is 0 for stdout or 1 for stderr
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns number of bytes processed by the callee. The remaining bytes will
|
||||
* be sent in the next callback message, when more data is available.
|
||||
*/
|
||||
typedef int (*ssh_channel_data_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
@@ -801,6 +803,8 @@ struct ssh_threads_callbacks_struct {
|
||||
*
|
||||
* @see ssh_threads_callbacks_struct
|
||||
* @see SSH_THREADS_PTHREAD
|
||||
* @bug libgcrypt 1.6 and bigger backend does not support custom callback.
|
||||
* Using anything else than pthreads here will fail.
|
||||
*/
|
||||
LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
|
||||
*cb);
|
||||
|
||||
@@ -49,7 +49,7 @@ int hashbufin_add_cookie(ssh_session session, unsigned char *cookie);
|
||||
int hashbufout_add_cookie(ssh_session session);
|
||||
int generate_session_keys(ssh_session session);
|
||||
bignum make_string_bn(ssh_string string);
|
||||
void make_string_bn_inplace(ssh_string string, bignum bnout);
|
||||
ssh_string make_bignum_string(bignum num);
|
||||
|
||||
|
||||
#endif /* DH_H_ */
|
||||
|
||||
27
include/libssh/knownhosts.h
Normal file
27
include/libssh/knownhosts.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 20014 by Aris Adamantiadis <aris@badcode.be>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef KNOWNHOSTS_H_
|
||||
#define KNOWNHOSTS_H_
|
||||
|
||||
char **ssh_knownhosts_algorithms(ssh_session session);
|
||||
|
||||
#endif /* KNOWNHOSTS_H_ */
|
||||
@@ -78,7 +78,7 @@
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 6
|
||||
#define LIBSSH_VERSION_MICRO 0
|
||||
#define LIBSSH_VERSION_MICRO 4
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
@@ -377,7 +377,7 @@ LIBSSH_API int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr,
|
||||
LIBSSH_API int ssh_channel_poll(ssh_channel channel, int is_stderr);
|
||||
LIBSSH_API int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr);
|
||||
LIBSSH_API int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
||||
LIBSSH_API int ssh_channel_read_timeout(ssh_channel channel, void *dest, uint32_t count, int is_stderr, int timeout);
|
||||
LIBSSH_API int ssh_channel_read_timeout(ssh_channel channel, void *dest, uint32_t count, int is_stderr, int timeout_ms);
|
||||
LIBSSH_API int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr);
|
||||
LIBSSH_API int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value);
|
||||
@@ -406,6 +406,7 @@ LIBSSH_API void ssh_disconnect(ssh_session session);
|
||||
LIBSSH_API char *ssh_dirname (const char *path);
|
||||
LIBSSH_API int ssh_finalize(void);
|
||||
LIBSSH_API ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms);
|
||||
LIBSSH_API ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int *destination_port);
|
||||
LIBSSH_API int ssh_forward_cancel(ssh_session session, const char *address, int port);
|
||||
LIBSSH_API int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
||||
LIBSSH_API void ssh_free(ssh_session session);
|
||||
@@ -533,6 +534,8 @@ LIBSSH_API int ssh_pki_export_pubkey_base64(const ssh_key key,
|
||||
LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key,
|
||||
const char *filename);
|
||||
|
||||
LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key);
|
||||
|
||||
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
|
||||
LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data);
|
||||
LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display);
|
||||
@@ -627,6 +630,8 @@ LIBSSH_API int ssh_event_remove_session(ssh_event event, ssh_session session);
|
||||
LIBSSH_API void ssh_event_free(ssh_event event);
|
||||
LIBSSH_API const char* ssh_get_clientbanner(ssh_session session);
|
||||
LIBSSH_API const char* ssh_get_serverbanner(ssh_session session);
|
||||
LIBSSH_API const char* ssh_get_cipher_in(ssh_session session);
|
||||
LIBSSH_API const char* ssh_get_cipher_out(ssh_session session);
|
||||
|
||||
#ifndef LIBSSH_LEGACY_0_4
|
||||
#include "libssh/legacy.h"
|
||||
|
||||
@@ -361,8 +361,8 @@ public:
|
||||
* @see ssh_channel_forward_accept
|
||||
* @see Session::listenForward
|
||||
*/
|
||||
Channel *acceptForward(int timeout_ms);
|
||||
/* acceptForward is implemented later in this file */
|
||||
inline Channel *acceptForward(int timeout_ms);
|
||||
/* implemented outside the class due Channel references */
|
||||
|
||||
void_throwable cancelForward(const char *address, int port){
|
||||
int err=ssh_forward_cancel(c_session, address, port);
|
||||
@@ -480,12 +480,30 @@ public:
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
int read(void *dest, size_t count, bool is_stderr=false){
|
||||
int read(void *dest, size_t count, bool is_stderr){
|
||||
int err;
|
||||
/* handle int overflow */
|
||||
if(count > 0x7fffffff)
|
||||
count = 0x7fffffff;
|
||||
err=ssh_channel_read(channel,dest,count,is_stderr);
|
||||
err=ssh_channel_read_timeout(channel,dest,count,is_stderr,-1);
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
int read(void *dest, size_t count, int timeout){
|
||||
int err;
|
||||
/* handle int overflow */
|
||||
if(count > 0x7fffffff)
|
||||
count = 0x7fffffff;
|
||||
err=ssh_channel_read_timeout(channel,dest,count,false,timeout);
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
int read(void *dest, size_t count, bool is_stderr=false, int timeout=-1){
|
||||
int err;
|
||||
/* handle int overflow */
|
||||
if(count > 0x7fffffff)
|
||||
count = 0x7fffffff;
|
||||
err=ssh_channel_read_timeout(channel,dest,count,is_stderr,timeout);
|
||||
ssh_throw(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ void _ssh_pki_log(const char *function,
|
||||
const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
|
||||
int pki_key_ecdsa_nid_from_name(const char *name);
|
||||
const char *pki_key_ecdsa_nid_to_name(int nid);
|
||||
|
||||
/* SSH Key Functions */
|
||||
ssh_key pki_key_dup(const ssh_key key, int demote);
|
||||
|
||||
@@ -120,11 +120,24 @@ int gettimeofday(struct timeval *__p, void *__t);
|
||||
#include "libssh/callbacks.h"
|
||||
|
||||
/* some constants */
|
||||
#ifndef MAX_PACKAT_LEN
|
||||
#define MAX_PACKET_LEN 262144
|
||||
#endif
|
||||
#ifndef ERROR_BUFFERLEN
|
||||
#define ERROR_BUFFERLEN 1024
|
||||
#endif
|
||||
#ifndef CLIENTBANNER1
|
||||
#define CLIENTBANNER1 "SSH-1.5-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
|
||||
#endif
|
||||
#ifndef CLIENTBANNER2
|
||||
#define CLIENTBANNER2 "SSH-2.0-libssh-" SSH_STRINGIFY(LIBSSH_VERSION)
|
||||
#endif
|
||||
#ifndef KBDINT_MAX_PROMPT
|
||||
#define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
|
||||
#endif
|
||||
#ifndef MAX_BUF_SIZE
|
||||
#define MAX_BUF_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef __FUNCTION__
|
||||
#if defined(__SUNPRO_C)
|
||||
@@ -155,16 +168,6 @@ int gettimeofday(struct timeval *__p, void *__t);
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* get rid of deprecacy warnings on OSX when using OpenSSL
|
||||
*/
|
||||
#if defined(__APPLE__)
|
||||
#ifdef MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
#undef MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
#endif
|
||||
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6
|
||||
#endif
|
||||
|
||||
/* forward declarations */
|
||||
struct ssh_common_struct;
|
||||
struct ssh_kex_struct;
|
||||
|
||||
@@ -44,7 +44,8 @@ enum ssh_bind_options_e {
|
||||
SSH_BIND_OPTIONS_RSAKEY,
|
||||
SSH_BIND_OPTIONS_BANNER,
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY,
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
|
||||
SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
|
||||
SSH_BIND_OPTIONS_ECDSAKEY
|
||||
};
|
||||
|
||||
typedef struct ssh_bind_struct* ssh_bind;
|
||||
@@ -80,69 +81,6 @@ typedef struct ssh_bind_callbacks_struct *ssh_bind_callbacks;
|
||||
*/
|
||||
LIBSSH_API ssh_bind ssh_bind_new(void);
|
||||
|
||||
/**
|
||||
* @brief Set the options for the current SSH server bind.
|
||||
*
|
||||
* @param sshbind The ssh server bind to configure.
|
||||
*
|
||||
* @param type The option type to set. This could be one of the
|
||||
* following:
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDADDR
|
||||
* The ip address to bind (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDPORT
|
||||
* The port to bind (unsigned int).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BINDPORT_STR
|
||||
* The port to bind (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_HOSTKEY
|
||||
* This specifies the file containing the private host key used
|
||||
* by SSHv1. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_DSAKEY
|
||||
* This specifies the file containing the private host dsa key
|
||||
* used by SSHv2. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_RSAKEY
|
||||
* This specifies the file containing the private host dsa key
|
||||
* used by SSHv2. (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BANNER
|
||||
* That the server banner (version string) for SSH.
|
||||
* (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY
|
||||
* Set the session logging verbosity (int).\n
|
||||
* \n
|
||||
* The verbosity of the messages. Every log smaller or
|
||||
* equal to verbosity will be shown.
|
||||
* - SSH_LOG_NOLOG: No logging
|
||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* - SSH_LOG_PACKET: Packet id and size
|
||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR
|
||||
* Set the session logging verbosity (const char *).\n
|
||||
* \n
|
||||
* The verbosity of the messages. Every log smaller or
|
||||
* equal to verbosity will be shown.
|
||||
* - SSH_LOG_NOLOG: No logging
|
||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* - SSH_LOG_PACKET: Packet id and size
|
||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
* \n
|
||||
* See the corresponding numbers in libssh.h.
|
||||
*
|
||||
* @param value The value to set. This is a generic pointer and the
|
||||
* datatype which is used should be set according to the
|
||||
* type set.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR on invalid option or parameter.
|
||||
*/
|
||||
LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind,
|
||||
enum ssh_bind_options_e type, const void *value);
|
||||
|
||||
|
||||
@@ -175,6 +175,7 @@ struct ssh_session_struct {
|
||||
char *knownhosts;
|
||||
char *wanted_methods[10];
|
||||
char *ProxyCommand;
|
||||
char *custombanner;
|
||||
unsigned long timeout; /* seconds */
|
||||
unsigned long timeout_usec;
|
||||
unsigned int port;
|
||||
|
||||
@@ -70,5 +70,6 @@ int crypt_set_algorithms_server(ssh_session session);
|
||||
struct ssh_crypto_struct *crypto_new(void);
|
||||
void crypto_free(struct ssh_crypto_struct *crypto);
|
||||
|
||||
void ssh_reseed(void);
|
||||
|
||||
#endif /* WRAPPER_H_ */
|
||||
|
||||
@@ -7,5 +7,7 @@ else()
|
||||
set(LIBSSH_INCLUDE_DIR @INCLUDE_INSTALL_DIR@)
|
||||
endif()
|
||||
|
||||
set(LIBSSH_LIRBARY @LIB_INSTALL_DIR@/libssh.so)
|
||||
set(LIBSSH_LIRBARIES @LIB_INSTALL_DIR@/libssh.so)
|
||||
set(LIBSSH_LIBRARY @LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@)
|
||||
set(LIBSSH_LIBRARIES @LIB_INSTALL_DIR@/@LIBSSH_LIBRARY_NAME@)
|
||||
|
||||
set(LIBSSH_THREADS_LIBRARY @LIB_INSTALL_DIR@/@LIBSSH_THREADS_LIBRARY_NAME@)
|
||||
|
||||
@@ -288,6 +288,6 @@ if (WITH_STATIC_LIB)
|
||||
)
|
||||
endif (WITH_STATIC_LIB)
|
||||
|
||||
if (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
if (Threads_FOUND)
|
||||
add_subdirectory(threads)
|
||||
endif (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
endif (Threads_FOUND)
|
||||
|
||||
65
src/bind.c
65
src/bind.c
@@ -144,26 +144,19 @@ ssh_bind ssh_bind_new(void) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int ssh_bind_listen(ssh_bind sshbind) {
|
||||
const char *host;
|
||||
socket_t fd;
|
||||
static int ssh_bind_import_keys(ssh_bind sshbind) {
|
||||
int rc;
|
||||
|
||||
if (ssh_init() < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sshbind->ecdsakey == NULL &&
|
||||
sshbind->dsakey == NULL &&
|
||||
sshbind->rsakey == NULL) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"DSA or RSA host key file must be set before listen()");
|
||||
"ECDSA, DSA, or RSA host key file must be set");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
if (sshbind->ecdsakey) {
|
||||
if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) {
|
||||
rc = ssh_pki_import_privkey_file(sshbind->ecdsakey,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -179,12 +172,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"The ECDSA host key has the wrong type");
|
||||
ssh_key_free(sshbind->ecdsa);
|
||||
sshbind->ecdsa = NULL;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sshbind->dsakey) {
|
||||
if (sshbind->dsa == NULL && sshbind->dsakey != NULL) {
|
||||
rc = ssh_pki_import_privkey_file(sshbind->dsakey,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -201,11 +195,12 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
||||
"The DSA host key has the wrong type: %d",
|
||||
ssh_key_type(sshbind->dsa));
|
||||
ssh_key_free(sshbind->dsa);
|
||||
sshbind->dsa = NULL;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (sshbind->rsakey) {
|
||||
if (sshbind->rsa == NULL && sshbind->rsakey != NULL) {
|
||||
rc = ssh_pki_import_privkey_file(sshbind->rsakey,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -222,10 +217,29 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
"The RSA host key has the wrong type");
|
||||
ssh_key_free(sshbind->rsa);
|
||||
sshbind->rsa = NULL;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int ssh_bind_listen(ssh_bind sshbind) {
|
||||
const char *host;
|
||||
socket_t fd;
|
||||
int rc;
|
||||
|
||||
if (ssh_init() < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ssh_bind_import_keys(sshbind);
|
||||
if (rc != SSH_OK) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (sshbind->bindfd == SSH_INVALID_SOCKET) {
|
||||
host = sshbind->bindaddr;
|
||||
if (host == NULL) {
|
||||
@@ -235,10 +249,11 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
||||
fd = bind_socket(sshbind, host, sshbind->bindport);
|
||||
if (fd == SSH_INVALID_SOCKET) {
|
||||
ssh_key_free(sshbind->dsa);
|
||||
sshbind->dsa = NULL;
|
||||
ssh_key_free(sshbind->rsa);
|
||||
sshbind->rsa = NULL;
|
||||
return -1;
|
||||
}
|
||||
sshbind->bindfd = fd;
|
||||
|
||||
if (listen(fd, 10) < 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,
|
||||
@@ -246,9 +261,13 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
||||
fd, strerror(errno));
|
||||
close(fd);
|
||||
ssh_key_free(sshbind->dsa);
|
||||
sshbind->dsa = NULL;
|
||||
ssh_key_free(sshbind->rsa);
|
||||
sshbind->rsa = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sshbind->bindfd = fd;
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket");
|
||||
}
|
||||
@@ -348,8 +367,11 @@ void ssh_bind_free(ssh_bind sshbind){
|
||||
SAFE_FREE(sshbind->ecdsakey);
|
||||
|
||||
ssh_key_free(sshbind->dsa);
|
||||
sshbind->dsa = NULL;
|
||||
ssh_key_free(sshbind->rsa);
|
||||
sshbind->rsa = NULL;
|
||||
ssh_key_free(sshbind->ecdsa);
|
||||
sshbind->ecdsa = NULL;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (sshbind->wanted_methods[i]) {
|
||||
@@ -361,7 +383,7 @@ void ssh_bind_free(ssh_bind sshbind){
|
||||
}
|
||||
|
||||
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
||||
int i;
|
||||
int i, rc;
|
||||
|
||||
if (session == NULL){
|
||||
ssh_set_error(sshbind, SSH_FATAL,"session is null");
|
||||
@@ -392,7 +414,8 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
||||
}
|
||||
|
||||
session->common.log_verbosity = sshbind->common.log_verbosity;
|
||||
|
||||
if(sshbind->banner != NULL)
|
||||
session->opts.custombanner = strdup(sshbind->banner);
|
||||
ssh_socket_free(session->socket);
|
||||
session->socket = ssh_socket_new(session);
|
||||
if (session->socket == NULL) {
|
||||
@@ -403,6 +426,16 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
||||
ssh_socket_set_fd(session->socket, fd);
|
||||
ssh_socket_get_poll_handle_out(session->socket);
|
||||
|
||||
/* We must try to import any keys that could be imported in case
|
||||
* we are not using ssh_bind_listen (which is the other place
|
||||
* where keys can be imported) on this ssh_bind and are instead
|
||||
* only using ssh_bind_accept_fd to manage sockets ourselves.
|
||||
*/
|
||||
rc = ssh_bind_import_keys(sshbind);
|
||||
if (rc != SSH_OK) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
if (sshbind->ecdsa) {
|
||||
session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa);
|
||||
@@ -426,6 +459,8 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
/* force PRNG to change state in case we fork after ssh_bind_accept */
|
||||
ssh_reseed();
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
|
||||
137
src/channels.c
137
src/channels.c
@@ -916,10 +916,10 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
* SSH_AGAIN if in nonblocking mode and call has
|
||||
* to be done again.
|
||||
*
|
||||
* @see channel_open_forward()
|
||||
* @see channel_request_env()
|
||||
* @see channel_request_shell()
|
||||
* @see channel_request_exec()
|
||||
* @see ssh_channel_open_forward()
|
||||
* @see ssh_channel_request_env()
|
||||
* @see ssh_channel_request_shell()
|
||||
* @see ssh_channel_request_exec()
|
||||
*/
|
||||
int ssh_channel_open_session(ssh_channel channel) {
|
||||
if(channel == NULL) {
|
||||
@@ -952,7 +952,7 @@ int ssh_channel_open_session(ssh_channel channel) {
|
||||
* SSH_AGAIN if in nonblocking mode and call has
|
||||
* to be done again.
|
||||
*
|
||||
* @see channel_open_forward()
|
||||
* @see ssh_channel_open_forward()
|
||||
*/
|
||||
int ssh_channel_open_auth_agent(ssh_channel channel){
|
||||
if(channel == NULL) {
|
||||
@@ -1120,8 +1120,24 @@ void ssh_channel_do_free(ssh_channel channel){
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*
|
||||
* @see channel_close()
|
||||
* @see channel_free()
|
||||
* Example:
|
||||
@code
|
||||
rc = ssh_channel_send_eof(channel);
|
||||
if (rc == SSH_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
while(!ssh_channel_is_eof(channel)) {
|
||||
rc = ssh_channel_read(channel, buf, sizeof(buf), 0);
|
||||
if (rc == SSH_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ssh_channel_close(channel);
|
||||
@endcode
|
||||
*
|
||||
* @see ssh_channel_close()
|
||||
* @see ssh_channel_free()
|
||||
* @see ssh_channel_is_eof()
|
||||
*/
|
||||
int ssh_channel_send_eof(ssh_channel channel){
|
||||
ssh_session session;
|
||||
@@ -1170,8 +1186,8 @@ error:
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*
|
||||
* @see channel_free()
|
||||
* @see channel_eof()
|
||||
* @see ssh_channel_free()
|
||||
* @see ssh_channel_is_eof()
|
||||
*/
|
||||
int ssh_channel_close(ssh_channel channel){
|
||||
ssh_session session;
|
||||
@@ -1222,7 +1238,8 @@ error:
|
||||
static int ssh_channel_waitwindow_termination(void *c){
|
||||
ssh_channel channel = (ssh_channel) c;
|
||||
if (channel->remote_window > 0 ||
|
||||
channel->session->session_state == SSH_SESSION_STATE_ERROR)
|
||||
channel->session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||
channel->state == SSH_CHANNEL_STATE_CLOSED)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
@@ -1329,7 +1346,8 @@ int channel_write_common(ssh_channel channel, const void *data,
|
||||
ssh_channel_waitwindow_termination,channel);
|
||||
if (rc == SSH_ERROR ||
|
||||
!ssh_channel_waitwindow_termination(channel) ||
|
||||
channel->session->session_state == SSH_SESSION_STATE_ERROR)
|
||||
channel->session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||
channel->state == SSH_CHANNEL_STATE_CLOSED)
|
||||
goto out;
|
||||
continue;
|
||||
}
|
||||
@@ -1397,7 +1415,7 @@ uint32_t ssh_channel_window_size(ssh_channel channel) {
|
||||
*
|
||||
* @return The number of bytes written, SSH_ERROR on error.
|
||||
*
|
||||
* @see channel_read()
|
||||
* @see ssh_channel_read()
|
||||
*/
|
||||
int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len) {
|
||||
return channel_write_common(channel, data, len, 0);
|
||||
@@ -1410,7 +1428,7 @@ int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len) {
|
||||
*
|
||||
* @return 0 if channel is closed, nonzero otherwise.
|
||||
*
|
||||
* @see channel_is_closed()
|
||||
* @see ssh_channel_is_closed()
|
||||
*/
|
||||
int ssh_channel_is_open(ssh_channel channel) {
|
||||
if(channel == NULL) {
|
||||
@@ -1426,7 +1444,7 @@ int ssh_channel_is_open(ssh_channel channel) {
|
||||
*
|
||||
* @return 0 if channel is opened, nonzero otherwise.
|
||||
*
|
||||
* @see channel_is_open()
|
||||
* @see ssh_channel_is_open()
|
||||
*/
|
||||
int ssh_channel_is_closed(ssh_channel channel) {
|
||||
if(channel == NULL) {
|
||||
@@ -1725,7 +1743,7 @@ error:
|
||||
* SSH_AGAIN if in nonblocking mode and call has
|
||||
* to be done again.
|
||||
*
|
||||
* @see channel_request_pty_size()
|
||||
* @see ssh_channel_request_pty_size()
|
||||
*/
|
||||
int ssh_channel_request_pty(ssh_channel channel) {
|
||||
return ssh_channel_request_pty_size(channel, "xterm", 80, 24);
|
||||
@@ -1964,7 +1982,7 @@ error:
|
||||
}
|
||||
|
||||
static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
|
||||
int timeout_ms) {
|
||||
int timeout_ms, int *destination_port) {
|
||||
#ifndef _WIN32
|
||||
static const struct timespec ts = {
|
||||
.tv_sec = 0,
|
||||
@@ -1981,7 +1999,11 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
|
||||
* 50 ms. So we need to decrement by 100 ms.
|
||||
*/
|
||||
for (t = timeout_ms; t >= 0; t -= 100) {
|
||||
ssh_handle_packets(session, 50);
|
||||
if (timeout_ms == 0) {
|
||||
ssh_handle_packets(session, 0);
|
||||
} else {
|
||||
ssh_handle_packets(session, 50);
|
||||
}
|
||||
|
||||
if (session->ssh_message_list) {
|
||||
iterator = ssh_list_get_iterator(session->ssh_message_list);
|
||||
@@ -1991,6 +2013,10 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
|
||||
ssh_message_subtype(msg) == channeltype) {
|
||||
ssh_list_remove(session->ssh_message_list, iterator);
|
||||
channel = ssh_message_channel_request_open_reply_accept(msg);
|
||||
if(destination_port) {
|
||||
*destination_port=msg->channel_request_open.destination_port;
|
||||
}
|
||||
|
||||
ssh_message_free(msg);
|
||||
return channel;
|
||||
}
|
||||
@@ -2021,7 +2047,7 @@ static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
|
||||
* the server.
|
||||
*/
|
||||
ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms) {
|
||||
return ssh_channel_accept(channel->session, SSH_CHANNEL_X11, timeout_ms);
|
||||
return ssh_channel_accept(channel->session, SSH_CHANNEL_X11, timeout_ms, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2275,7 +2301,23 @@ error:
|
||||
* the server
|
||||
*/
|
||||
ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms) {
|
||||
return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms);
|
||||
return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accept an incoming TCP/IP forwarding channel and get information
|
||||
* about incomming connection
|
||||
* @param[in] session The ssh session to use.
|
||||
*
|
||||
* @param[in] timeout_ms A timeout in milliseconds.
|
||||
*
|
||||
* @param[in] destination_port A pointer to destination port or NULL.
|
||||
*
|
||||
* @return Newly created channel, or NULL if no incoming channel request from
|
||||
* the server
|
||||
*/
|
||||
ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int* destination_port) {
|
||||
return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, destination_port);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2411,20 +2453,22 @@ error:
|
||||
* SSH_ERROR if an error occurred,
|
||||
* SSH_AGAIN if in nonblocking mode and call has
|
||||
* to be done again.
|
||||
* @code
|
||||
* rc = channel_request_exec(channel, "ps aux");
|
||||
* if (rc > 0) {
|
||||
* return -1;
|
||||
* }
|
||||
*
|
||||
* while ((rc = channel_read(channel, buffer, sizeof(buffer), 0)) > 0) {
|
||||
* if (fwrite(buffer, 1, rc, stdout) != (unsigned int) rc) {
|
||||
* return -1;
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* Example:
|
||||
@code
|
||||
rc = channel_request_exec(channel, "ps aux");
|
||||
if (rc > 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((rc = channel_read(channel, buffer, sizeof(buffer), 0)) > 0) {
|
||||
if (fwrite(buffer, 1, rc, stdout) != (unsigned int) rc) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
*
|
||||
* @see channel_request_shell()
|
||||
* @see ssh_channel_request_shell()
|
||||
*/
|
||||
int ssh_channel_request_exec(ssh_channel channel, const char *cmd) {
|
||||
ssh_buffer buffer = NULL;
|
||||
@@ -2678,16 +2722,16 @@ int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_std
|
||||
/**
|
||||
* @brief Reads data from a channel.
|
||||
*
|
||||
* @param[in] channel The channel to read from.
|
||||
* @param[in] channel The channel to read from.
|
||||
*
|
||||
* @param[in] dest The destination buffer which will get the data.
|
||||
* @param[in] dest The destination buffer which will get the data.
|
||||
*
|
||||
* @param[in] count The count of bytes to be read.
|
||||
* @param[in] count The count of bytes to be read.
|
||||
*
|
||||
* @param[in] is_stderr A boolean value to mark reading from the stderr flow.
|
||||
* @param[in] is_stderr A boolean value to mark reading from the stderr flow.
|
||||
*
|
||||
* @param[in] timeout A timeout in seconds. A value of -1 means infinite
|
||||
* timeout.
|
||||
* @param[in] timeout_ms A timeout in milliseconds. A value of -1 means
|
||||
* infinite timeout.
|
||||
*
|
||||
* @return The number of bytes read, 0 on end of file or SSH_ERROR
|
||||
* on error. In nonblocking mode it Can return 0 if no data
|
||||
@@ -2803,7 +2847,7 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
*
|
||||
* @warning Don't forget to check for EOF as it would return 0 here.
|
||||
*
|
||||
* @see channel_is_eof()
|
||||
* @see ssh_channel_is_eof()
|
||||
*/
|
||||
int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr) {
|
||||
@@ -2855,7 +2899,7 @@ int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count
|
||||
*
|
||||
* @warning When the channel is in EOF state, the function returns SSH_EOF.
|
||||
*
|
||||
* @see channel_is_eof()
|
||||
* @see ssh_channel_is_eof()
|
||||
*/
|
||||
int ssh_channel_poll(ssh_channel channel, int is_stderr){
|
||||
ssh_buffer stdbuf;
|
||||
@@ -2907,7 +2951,7 @@ int ssh_channel_poll(ssh_channel channel, int is_stderr){
|
||||
*
|
||||
* @warning When the channel is in EOF state, the function returns SSH_EOF.
|
||||
*
|
||||
* @see channel_is_eof()
|
||||
* @see ssh_channel_is_eof()
|
||||
*/
|
||||
int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr){
|
||||
ssh_session session;
|
||||
@@ -2980,6 +3024,11 @@ static int ssh_channel_exit_status_termination(void *c){
|
||||
* (yet).
|
||||
* @warning This function may block until a timeout (or never)
|
||||
* if the other side is not willing to close the channel.
|
||||
*
|
||||
* If you're looking for an async handling of this register a callback for the
|
||||
* exit status.
|
||||
*
|
||||
* @see ssh_channel_exit_status_callback
|
||||
*/
|
||||
int ssh_channel_get_exit_status(ssh_channel channel) {
|
||||
int rc;
|
||||
@@ -3212,7 +3261,7 @@ int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans,
|
||||
*
|
||||
* @return The number of bytes written, SSH_ERROR on error.
|
||||
*
|
||||
* @see channel_read()
|
||||
* @see ssh_channel_read()
|
||||
*/
|
||||
int ssh_channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) {
|
||||
return channel_write_common(channel, data, len, 1);
|
||||
@@ -3418,9 +3467,9 @@ error:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an exit signal to remote process (as described in RFC 4254, section 6.10).
|
||||
* @brief Send an exit signal to remote process (RFC 4254, section 6.10).
|
||||
*
|
||||
* Sends a signal 'sig' to the remote process.
|
||||
* This sends the exit status of the remote process.
|
||||
* Note, that remote system may not support signals concept.
|
||||
* In such a case this request will be silently ignored.
|
||||
* Only SSH-v2 is supported (I'm not sure about SSH-v1).
|
||||
@@ -3498,7 +3547,7 @@ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig,
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = channel_request(channel, "signal", buffer, 0);
|
||||
rc = channel_request(channel, "exit-signal", buffer, 0);
|
||||
error:
|
||||
ssh_buffer_free(buffer);
|
||||
if(tmp)
|
||||
|
||||
22
src/client.c
22
src/client.c
@@ -60,12 +60,15 @@
|
||||
static void socket_callback_connected(int code, int errno_code, void *user){
|
||||
ssh_session session=(ssh_session)user;
|
||||
|
||||
if(session->session_state != SSH_SESSION_STATE_CONNECTING){
|
||||
if (session->session_state != SSH_SESSION_STATE_CONNECTING &&
|
||||
session->session_state != SSH_SESSION_STATE_SOCKET_CONNECTED)
|
||||
{
|
||||
ssh_set_error(session,SSH_FATAL, "Wrong state in socket_callback_connected : %d",
|
||||
session->session_state);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_RARE,"Socket connection callback: %d (%d)",code, errno_code);
|
||||
if(code == SSH_SOCKET_CONNECTED_OK)
|
||||
session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED;
|
||||
@@ -152,19 +155,27 @@ int ssh_send_banner(ssh_session session, int server) {
|
||||
banner = session->version == 1 ? CLIENTBANNER1 : CLIENTBANNER2;
|
||||
|
||||
if (server) {
|
||||
session->serverbanner = strdup(banner);
|
||||
if(session->opts.custombanner == NULL){
|
||||
session->serverbanner = strdup(banner);
|
||||
} else {
|
||||
session->serverbanner = malloc(strlen(session->opts.custombanner) + 9);
|
||||
if(!session->serverbanner)
|
||||
goto end;
|
||||
strcpy(session->serverbanner, "SSH-2.0-");
|
||||
strcat(session->serverbanner, session->opts.custombanner);
|
||||
}
|
||||
if (session->serverbanner == NULL) {
|
||||
goto end;
|
||||
}
|
||||
snprintf(buffer, 128, "%s\n", session->serverbanner);
|
||||
} else {
|
||||
session->clientbanner = strdup(banner);
|
||||
if (session->clientbanner == NULL) {
|
||||
goto end;
|
||||
}
|
||||
snprintf(buffer, 128, "%s\n", session->clientbanner);
|
||||
}
|
||||
|
||||
snprintf(buffer, 128, "%s\n", banner);
|
||||
|
||||
if (ssh_socket_write(session->socket, buffer, strlen(buffer)) == SSH_ERROR) {
|
||||
goto end;
|
||||
}
|
||||
@@ -536,7 +547,8 @@ pending:
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET,"ssh_connect: Actual timeout : %d", timeout);
|
||||
ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session);
|
||||
if (ret == SSH_ERROR || !ssh_connect_termination(session)) {
|
||||
if (session->session_state != SSH_SESSION_STATE_ERROR &&
|
||||
(ret == SSH_ERROR || !ssh_connect_termination(session))) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Timeout connecting to %s", session->opts.host);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
|
||||
@@ -128,7 +128,7 @@ static char *ssh_config_get_token(char **str) {
|
||||
c = ssh_config_get_cmd(str);
|
||||
|
||||
for (r = c; *c; c++) {
|
||||
if (isblank(*c)) {
|
||||
if (isblank(*c) || *c == '=') {
|
||||
*c = '\0';
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -382,7 +382,15 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(s, itr->ai_addr, itr->ai_addrlen);
|
||||
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
|
||||
if (rc == -1 && (errno != EINPROGRESS)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to connect: %s", strerror(errno));
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -421,7 +429,7 @@ static int ssh_select_cb (socket_t fd, int revents, void *userdata){
|
||||
* @param[in] readfds A fd_set of file descriptors to be select'ed for
|
||||
* reading.
|
||||
*
|
||||
* @param[in] timeout A timeout for the select.
|
||||
* @param[in] timeout The timeout in milliseconds.
|
||||
*
|
||||
* @return SSH_OK on success,
|
||||
* SSH_ERROR on error,
|
||||
|
||||
11
src/dh.c
11
src/dh.c
@@ -170,7 +170,7 @@ int ssh_crypto_init(void) {
|
||||
return -1;
|
||||
}
|
||||
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, &p_group14);
|
||||
if (p_group1 == NULL) {
|
||||
if (p_group14 == NULL) {
|
||||
bignum_free(g);
|
||||
bignum_free(p_group1);
|
||||
g = NULL;
|
||||
@@ -407,6 +407,15 @@ bignum make_string_bn(ssh_string string){
|
||||
return bn;
|
||||
}
|
||||
|
||||
void make_string_bn_inplace(ssh_string string, bignum bnout) {
|
||||
unsigned int len = ssh_string_len(string);
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#error "unsupported"
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
bignum_bin2bn(string->data, len, bnout);
|
||||
#endif
|
||||
}
|
||||
|
||||
ssh_string dh_get_e(ssh_session session) {
|
||||
return make_bignum_string(session->next_crypto->e);
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ void _ssh_set_error_invalid(void *error, const char *function)
|
||||
/**
|
||||
* @brief Retrieve the error text message from the last error.
|
||||
*
|
||||
* @param error The SSH session pointer.
|
||||
* @param error An ssh_session or ssh_bind.
|
||||
*
|
||||
* @return A static string describing the error.
|
||||
*/
|
||||
@@ -117,7 +117,7 @@ const char *ssh_get_error(void *error) {
|
||||
/**
|
||||
* @brief Retrieve the error code from the last error.
|
||||
*
|
||||
* @param error The SSH session pointer.
|
||||
* @param error An ssh_session or ssh_bind.
|
||||
*
|
||||
* \return SSH_NO_ERROR No error occurred\n
|
||||
* SSH_REQUEST_DENIED The last request was denied but situation is
|
||||
|
||||
@@ -539,8 +539,12 @@ ssh_gssapi_creds ssh_gssapi_get_creds(ssh_session session){
|
||||
return (ssh_gssapi_creds)session->gssapi->client_creds;
|
||||
}
|
||||
|
||||
#endif /* SERVER */
|
||||
|
||||
/**
|
||||
* @brief Set the forwadable ticket to be given to the server for authentication.
|
||||
* Unlike ssh_gssapi_get_creds() this is called on the client side of an ssh
|
||||
* connection.
|
||||
*
|
||||
* @param[in] creds gssapi credentials handle.
|
||||
*/
|
||||
@@ -559,8 +563,6 @@ void ssh_gssapi_set_creds(ssh_session session, const ssh_gssapi_creds creds)
|
||||
session->gssapi->client.client_deleg_creds = (gss_cred_id_t)creds;
|
||||
}
|
||||
|
||||
#endif /* SERVER */
|
||||
|
||||
static int ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, int n_oid){
|
||||
ssh_string str;
|
||||
int rc;
|
||||
|
||||
64
src/kex.c
64
src/kex.c
@@ -35,6 +35,7 @@
|
||||
#include "libssh/ssh2.h"
|
||||
#include "libssh/string.h"
|
||||
#include "libssh/curve25519.h"
|
||||
#include "libssh/knownhosts.h"
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
# define BLOWFISH "blowfish-cbc,"
|
||||
@@ -72,7 +73,7 @@
|
||||
|
||||
#ifdef HAVE_ECDH
|
||||
#define ECDH "ecdh-sha2-nistp256,"
|
||||
#define HOSTKEYS "ecdsa-sha2-nistp256,ssh-rsa,ssh-dss"
|
||||
#define HOSTKEYS "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-dss"
|
||||
#else
|
||||
#define HOSTKEYS "ssh-rsa,ssh-dss"
|
||||
#define ECDH ""
|
||||
@@ -314,7 +315,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
str = buffer_get_ssh_string(packet);
|
||||
if (str == NULL) {
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(session->in_hashbuf, str) < 0) {
|
||||
@@ -349,6 +350,11 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
error:
|
||||
ssh_string_free(str);
|
||||
for (i = 0; i < SSH_KEX_METHODS; i++) {
|
||||
if (server_kex) {
|
||||
session->next_crypto->client_kex.methods[i] = NULL;
|
||||
} else { /* client */
|
||||
session->next_crypto->server_kex.methods[i] = NULL;
|
||||
}
|
||||
SAFE_FREE(strings[i]);
|
||||
}
|
||||
|
||||
@@ -373,6 +379,53 @@ void ssh_list_kex(struct ssh_kex_struct *kex) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief selects the hostkey mechanisms to be chosen for the key exchange,
|
||||
* as some hostkey mechanisms may be present in known_hosts file and preferred
|
||||
* @returns a cstring containing a comma-separated list of hostkey methods.
|
||||
* NULL if no method matches
|
||||
*/
|
||||
static char *ssh_client_select_hostkeys(ssh_session session){
|
||||
char methods_buffer[128]={0};
|
||||
static const char *preferred_hostkeys[]={"ecdsa-sha2-nistp521","ecdsa-sha2-nistp384",
|
||||
"ecdsa-sha2-nistp256", "ssh-rsa", "ssh-dss", "ssh-rsa1", NULL};
|
||||
char **methods;
|
||||
int i,j;
|
||||
int needcoma=0;
|
||||
|
||||
methods = ssh_knownhosts_algorithms(session);
|
||||
if (methods == NULL || methods[0] == NULL){
|
||||
SAFE_FREE(methods);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i=0;preferred_hostkeys[i] != NULL; ++i){
|
||||
for (j=0; methods[j] != NULL; ++j){
|
||||
if(strcmp(preferred_hostkeys[i], methods[j]) == 0){
|
||||
if (verify_existing_algo(SSH_HOSTKEYS, methods[j])){
|
||||
if(needcoma)
|
||||
strncat(methods_buffer,",",sizeof(methods_buffer)-strlen(methods_buffer)-1);
|
||||
strncat(methods_buffer, methods[j], sizeof(methods_buffer)-strlen(methods_buffer)-1);
|
||||
needcoma = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0;methods[i]!= NULL; ++i){
|
||||
SAFE_FREE(methods[i]);
|
||||
}
|
||||
SAFE_FREE(methods);
|
||||
|
||||
if(strlen(methods_buffer) > 0){
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Changing host key method to \"%s\"", methods_buffer);
|
||||
return strdup(methods_buffer);
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "No supported kex method for existing key in known_hosts file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief sets the key exchange parameters to be sent to the server,
|
||||
* in function of the options and available methods.
|
||||
@@ -385,6 +438,13 @@ int set_client_kex(ssh_session session){
|
||||
ssh_get_random(client->cookie, 16, 0);
|
||||
|
||||
memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **));
|
||||
/* first check if we have specific host key methods */
|
||||
if(session->opts.wanted_methods[SSH_HOSTKEYS] == NULL){
|
||||
/* Only if no override */
|
||||
session->opts.wanted_methods[SSH_HOSTKEYS] =
|
||||
ssh_client_select_hostkeys(session);
|
||||
}
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
wanted = session->opts.wanted_methods[i];
|
||||
if (wanted == NULL)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/pki.h"
|
||||
#include "libssh/options.h"
|
||||
|
||||
#include "libssh/knownhosts.h"
|
||||
/*todo: remove this include */
|
||||
#include "libssh/string.h"
|
||||
|
||||
@@ -647,6 +647,102 @@ int ssh_write_knownhost(ssh_session session) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define KNOWNHOSTS_MAXTYPES 10
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief Check which kind of host keys should be preferred for connection
|
||||
* by reading the known_hosts file.
|
||||
*
|
||||
* @param[in] session The SSH session to use.
|
||||
*
|
||||
* @returns array of supported key types
|
||||
* NULL on error
|
||||
*/
|
||||
char **ssh_knownhosts_algorithms(ssh_session session) {
|
||||
FILE *file = NULL;
|
||||
char **tokens;
|
||||
char *host;
|
||||
char *hostport;
|
||||
const char *type;
|
||||
int match;
|
||||
char **array;
|
||||
int i=0, j;
|
||||
|
||||
if (session->opts.knownhosts == NULL) {
|
||||
if (ssh_options_apply(session) < 0) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Can't find a known_hosts file");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (session->opts.host == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
host = ssh_lowercase(session->opts.host);
|
||||
hostport = ssh_hostport(host, session->opts.port);
|
||||
array = malloc(sizeof(char *) * KNOWNHOSTS_MAXTYPES);
|
||||
|
||||
if (host == NULL || hostport == NULL || array == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(host);
|
||||
SAFE_FREE(hostport);
|
||||
SAFE_FREE(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
tokens = ssh_get_knownhost_line(&file,
|
||||
session->opts.knownhosts, &type);
|
||||
|
||||
/* End of file, return the current state */
|
||||
if (tokens == NULL) {
|
||||
break;
|
||||
}
|
||||
match = match_hashed_host(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(hostport, tokens[0]);
|
||||
}
|
||||
if (match) {
|
||||
/* We got a match. Now check the key type */
|
||||
SSH_LOG(SSH_LOG_DEBUG, "server %s:%d has %s in known_hosts",
|
||||
host, session->opts.port, type);
|
||||
/* don't copy more than once */
|
||||
for(j=0;j<i && match;++j){
|
||||
if(strcmp(array[j], type)==0)
|
||||
match=0;
|
||||
}
|
||||
if (match){
|
||||
array[i] = strdup(type);
|
||||
i++;
|
||||
if(i>= KNOWNHOSTS_MAXTYPES-1){
|
||||
tokens_free(tokens);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
tokens_free(tokens);
|
||||
} while (1);
|
||||
|
||||
array[i]=NULL;
|
||||
SAFE_FREE(host);
|
||||
SAFE_FREE(hostport);
|
||||
if (file != NULL) {
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/* Return the current state at end of file */
|
||||
return array;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/* vim: set ts=4 sw=4 et cindent: */
|
||||
|
||||
@@ -19,10 +19,14 @@
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
@@ -38,6 +42,8 @@
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#ifdef HAVE_OPENSSL_AES_H
|
||||
#define HAS_AES
|
||||
#include <openssl/aes.h>
|
||||
@@ -74,6 +80,14 @@ static int alloc_key(struct ssh_cipher_struct *cipher) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ssh_reseed(void){
|
||||
#ifndef _WIN32
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
RAND_add(&tv, sizeof(tv), 0.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SHACTX sha1_init(void) {
|
||||
SHACTX c = malloc(sizeof(*c));
|
||||
if (c == NULL) {
|
||||
@@ -193,7 +207,11 @@ void md5_final(unsigned char *md, MD5CTX c) {
|
||||
}
|
||||
|
||||
ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
|
||||
ssh_mac_ctx ctx=malloc(sizeof(struct ssh_mac_ctx_struct));
|
||||
ssh_mac_ctx ctx = malloc(sizeof(struct ssh_mac_ctx_struct));
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->mac_type=type;
|
||||
switch(type){
|
||||
case SSH_MAC_SHA1:
|
||||
|
||||
@@ -45,6 +45,9 @@ static int alloc_key(struct ssh_cipher_struct *cipher) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ssh_reseed(void){
|
||||
}
|
||||
|
||||
SHACTX sha1_init(void) {
|
||||
SHACTX ctx = NULL;
|
||||
gcry_md_open(&ctx, GCRY_MD_SHA1, 0);
|
||||
@@ -88,7 +91,11 @@ void md5_final(unsigned char *md, MD5CTX c) {
|
||||
}
|
||||
|
||||
ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
|
||||
ssh_mac_ctx ctx=malloc(sizeof(struct ssh_mac_ctx_struct));
|
||||
ssh_mac_ctx ctx = malloc(sizeof(struct ssh_mac_ctx_struct));
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->mac_type=type;
|
||||
switch(type){
|
||||
case SSH_MAC_SHA1:
|
||||
|
||||
@@ -208,8 +208,8 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
|
||||
ssh_callbacks_exists(channel->callbacks, channel_pty_window_change_function)) {
|
||||
rc = channel->callbacks->channel_pty_window_change_function(session,
|
||||
channel,
|
||||
msg->channel_request.height, msg->channel_request.width,
|
||||
msg->channel_request.pxheight, msg->channel_request.pxwidth,
|
||||
msg->channel_request.width, msg->channel_request.height,
|
||||
msg->channel_request.pxwidth, msg->channel_request.pxheight,
|
||||
channel->callbacks->userdata);
|
||||
} else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_EXEC &&
|
||||
ssh_callbacks_exists(channel->callbacks, channel_exec_request_function)) {
|
||||
@@ -508,8 +508,7 @@ void ssh_message_free(ssh_message msg){
|
||||
case SSH_REQUEST_AUTH:
|
||||
SAFE_FREE(msg->auth_request.username);
|
||||
if (msg->auth_request.password) {
|
||||
memset(msg->auth_request.password, 0,
|
||||
strlen(msg->auth_request.password));
|
||||
BURN_STRING(msg->auth_request.password);
|
||||
SAFE_FREE(msg->auth_request.password);
|
||||
}
|
||||
ssh_key_free(msg->auth_request.pubkey);
|
||||
@@ -1372,6 +1371,7 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel,
|
||||
msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight);
|
||||
msg->channel_request.modes = buffer_get_ssh_string(packet);
|
||||
if (msg->channel_request.modes == NULL) {
|
||||
msg->channel_request.TERM = NULL;
|
||||
SAFE_FREE(term_c);
|
||||
goto error;
|
||||
}
|
||||
@@ -1470,6 +1470,7 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel,
|
||||
if (strcmp(request, "x11-req") == 0) {
|
||||
ssh_string auth_protocol = NULL;
|
||||
ssh_string auth_cookie = NULL;
|
||||
uint32_t screen_number;
|
||||
|
||||
buffer_get_u8(packet, &msg->channel_request.x11_single_connection);
|
||||
|
||||
@@ -1497,7 +1498,8 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel,
|
||||
ssh_string_free(auth_protocol);
|
||||
ssh_string_free(auth_cookie);
|
||||
|
||||
buffer_get_u32(packet, &msg->channel_request.x11_screen_number);
|
||||
buffer_get_u32(packet, &screen_number);
|
||||
msg->channel_request.x11_screen_number = ntohl(screen_number);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -697,7 +697,6 @@ char *ssh_path_expand_tilde(const char *d) {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
150
src/options.c
150
src/options.c
@@ -512,7 +512,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
}
|
||||
session->opts.username = q;
|
||||
} else if (v[0] == '\0') {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
} else { /* username provided */
|
||||
session->opts.username = strdup(value);
|
||||
@@ -531,7 +531,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
} else if (v[0] == '\0') {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
} else {
|
||||
session->opts.sshdir = ssh_path_expand_tilde(v);
|
||||
@@ -1303,65 +1303,89 @@ static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssh_bind_set_key(ssh_bind sshbind, char **key_loc,
|
||||
const void *value) {
|
||||
if (value == NULL) {
|
||||
ssh_set_error_invalid(sshbind);
|
||||
return -1;
|
||||
} else {
|
||||
SAFE_FREE(*key_loc);
|
||||
*key_loc = strdup(value);
|
||||
if (*key_loc == NULL) {
|
||||
ssh_set_error_oom(sshbind);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function can set all possible ssh bind options.
|
||||
* @brief Set options for an SSH server bind.
|
||||
*
|
||||
* @param sshbind An allocated ssh bind structure.
|
||||
* @param sshbind The ssh server bind to configure.
|
||||
*
|
||||
* @param type The option type to set. This could be one of the
|
||||
* @param type The option type to set. This should be one of the
|
||||
* following:
|
||||
*
|
||||
* SSH_BIND_OPTIONS_LOG_VERBOSITY:
|
||||
* Set the session logging verbosity (integer).
|
||||
*
|
||||
* The verbosity of the messages. Every log smaller or
|
||||
* equal to verbosity will be shown.
|
||||
* SSH_LOG_NOLOG: No logging
|
||||
* SSH_LOG_RARE: Rare conditions or warnings
|
||||
* SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* SSH_LOG_PACKET: Packet id and size
|
||||
* SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
*
|
||||
* SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
|
||||
* Set the session logging verbosity (integer).
|
||||
*
|
||||
* The verbosity of the messages. Every log smaller or
|
||||
* equal to verbosity will be shown.
|
||||
* SSH_LOG_NOLOG: No logging
|
||||
* SSH_LOG_RARE: Rare conditions or warnings
|
||||
* SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* SSH_LOG_PACKET: Packet id and size
|
||||
* SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
*
|
||||
* SSH_BIND_OPTIONS_BINDADDR:
|
||||
* Set the bind address.
|
||||
*
|
||||
* SSH_BIND_OPTIONS_BINDPORT:
|
||||
* Set the bind port, default is 22.
|
||||
*
|
||||
* SSH_BIND_OPTIONS_HOSTKEY:
|
||||
* - SSH_BIND_OPTIONS_HOSTKEY:
|
||||
* Set the server public key type: ssh-rsa or ssh-dss
|
||||
* (string).
|
||||
* (const char *).
|
||||
*
|
||||
* SSH_BIND_OPTIONS_DSAKEY:
|
||||
* Set the path to the dsa ssh host key (string).
|
||||
* - SSH_BIND_OPTIONS_BINDADDR:
|
||||
* Set the IP address to bind (const char *).
|
||||
*
|
||||
* SSH_BIND_OPTIONS_RSAKEY:
|
||||
* Set the path to the ssh host rsa key (string).
|
||||
* - SSH_BIND_OPTIONS_BINDPORT:
|
||||
* Set the port to bind (unsigned int *).
|
||||
*
|
||||
* SSH_BIND_OPTIONS_BANNER:
|
||||
* Set the server banner sent to clients (string).
|
||||
* - SSH_BIND_OPTIONS_BINDPORT_STR:
|
||||
* Set the port to bind (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY:
|
||||
* Set the session logging verbosity (int *).
|
||||
* The logging verbosity should have one of the
|
||||
* following values, which are listed in order
|
||||
* of increasing verbosity. Every log message
|
||||
* with verbosity less than or equal to the
|
||||
* logging verbosity will be shown.
|
||||
* - SSH_LOG_NOLOG: No logging
|
||||
* - SSH_LOG_RARE: Rare conditions or warnings
|
||||
* - SSH_LOG_ENTRY: API-accessible entrypoints
|
||||
* - SSH_LOG_PACKET: Packet id and size
|
||||
* - SSH_LOG_FUNCTIONS: Function entering and leaving
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
|
||||
* Set the session logging verbosity via a
|
||||
* string that will be converted to a numerical
|
||||
* value (e.g. "3") and interpreted according
|
||||
* to the values of
|
||||
* SSH_BIND_OPTIONS_LOG_VERBOSITY above (const
|
||||
* char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_DSAKEY:
|
||||
* Set the path to the ssh host dsa key, SSHv2
|
||||
* only (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_RSAKEY:
|
||||
* Set the path to the ssh host rsa key, SSHv2
|
||||
* only (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_ECDSAKEY:
|
||||
* Set the path to the ssh host ecdsa key,
|
||||
* SSHv2 only (const char *).
|
||||
*
|
||||
* - SSH_BIND_OPTIONS_BANNER:
|
||||
* Set the server banner sent to clients (const char *).
|
||||
*
|
||||
* @param value The value to set. This is a generic pointer and the
|
||||
* datatype which is used should be set according to the
|
||||
* type set.
|
||||
* datatype which should be used is described at the
|
||||
* corresponding value of type above.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
* @return 0 on success, < 0 on error, invalid option, or parameter.
|
||||
*/
|
||||
int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
||||
const void *value) {
|
||||
char *p, *q;
|
||||
int i;
|
||||
int i, rc;
|
||||
|
||||
if (sshbind == NULL) {
|
||||
return -1;
|
||||
@@ -1445,31 +1469,23 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
||||
}
|
||||
break;
|
||||
case SSH_BIND_OPTIONS_DSAKEY:
|
||||
if (value == NULL) {
|
||||
ssh_set_error_invalid(sshbind);
|
||||
return -1;
|
||||
} else {
|
||||
SAFE_FREE(sshbind->dsakey);
|
||||
sshbind->dsakey = strdup(value);
|
||||
if (sshbind->dsakey == NULL) {
|
||||
ssh_set_error_oom(sshbind);
|
||||
return -1;
|
||||
rc = ssh_bind_set_key(sshbind, &sshbind->dsakey, value);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case SSH_BIND_OPTIONS_RSAKEY:
|
||||
if (value == NULL) {
|
||||
ssh_set_error_invalid(sshbind);
|
||||
return -1;
|
||||
} else {
|
||||
SAFE_FREE(sshbind->rsakey);
|
||||
sshbind->rsakey = strdup(value);
|
||||
if (sshbind->rsakey == NULL) {
|
||||
ssh_set_error_oom(sshbind);
|
||||
return -1;
|
||||
rc = ssh_bind_set_key(sshbind, &sshbind->rsakey, value);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case SSH_BIND_OPTIONS_ECDSAKEY:
|
||||
rc = ssh_bind_set_key(sshbind, &sshbind->ecdsakey, value);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case SSH_BIND_OPTIONS_BANNER:
|
||||
if (value == NULL) {
|
||||
ssh_set_error_invalid(sshbind);
|
||||
|
||||
35
src/packet.c
35
src/packet.c
@@ -251,12 +251,18 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
* Decrypt the rest of the packet (blocksize bytes already
|
||||
* have been decrypted)
|
||||
*/
|
||||
rc = packet_decrypt(session,
|
||||
((uint8_t*)buffer_get_rest(session->in_buffer) + blocksize),
|
||||
buffer_get_rest_len(session->in_buffer) - blocksize);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Decrypt error");
|
||||
goto error;
|
||||
uint32_t buffer_len = buffer_get_rest_len(session->in_buffer);
|
||||
|
||||
/* The following check avoids decrypting zero bytes */
|
||||
if (buffer_len > blocksize) {
|
||||
uint8_t *payload = ((uint8_t*)buffer_get_rest(session->in_buffer) + blocksize);
|
||||
uint32_t plen = buffer_len - blocksize;
|
||||
|
||||
rc = packet_decrypt(session, payload, plen);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Decrypt error");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy the last part from the incoming buffer */
|
||||
@@ -498,11 +504,13 @@ static int packet_send2(ssh_session session) {
|
||||
session->current_crypto->out_cipher->blocksize : 8);
|
||||
uint32_t currentlen = buffer_get_rest_len(session->out_buffer);
|
||||
unsigned char *hmac = NULL;
|
||||
char padstring[32] = {0};
|
||||
char padstring[32] = { 0 };
|
||||
int rc = SSH_ERROR;
|
||||
uint32_t finallen,payloadsize,compsize;
|
||||
uint8_t padding;
|
||||
|
||||
uint8_t header[sizeof(padding) + sizeof(finallen)] = { 0 };
|
||||
|
||||
payloadsize = currentlen;
|
||||
#ifdef WITH_ZLIB
|
||||
if (session->current_crypto
|
||||
@@ -522,19 +530,18 @@ static int packet_send2(ssh_session session) {
|
||||
|
||||
if (session->current_crypto) {
|
||||
ssh_get_random(padstring, padding, 0);
|
||||
} else {
|
||||
memset(padstring,0,padding);
|
||||
}
|
||||
|
||||
finallen = htonl(currentlen + padding + 1);
|
||||
|
||||
if (buffer_prepend_data(session->out_buffer, &padding, sizeof(uint8_t)) < 0) {
|
||||
memcpy(&header[0], &finallen, sizeof(finallen));
|
||||
header[sizeof(finallen)] = padding;
|
||||
rc = buffer_prepend_data(session->out_buffer, &header, sizeof(header));
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
|
||||
rc = buffer_add_data(session->out_buffer, padstring, padding);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
#ifdef WITH_PCAP
|
||||
|
||||
@@ -106,7 +106,7 @@ int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user
|
||||
size_t processed=0;
|
||||
uint32_t padding;
|
||||
uint32_t crc;
|
||||
uint32_t len;
|
||||
uint32_t len, buffer_len;
|
||||
ssh_session session=(ssh_session)user;
|
||||
|
||||
switch (session->packet_state){
|
||||
@@ -168,11 +168,16 @@ int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user
|
||||
* We decrypt everything, missing the lenght part (which was
|
||||
* previously read, unencrypted, and is not part of the buffer
|
||||
*/
|
||||
if (packet_decrypt(session,
|
||||
ssh_buffer_get_begin(session->in_buffer),
|
||||
ssh_buffer_get_len(session->in_buffer)) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Packet decrypt error");
|
||||
goto error;
|
||||
buffer_len = ssh_buffer_get_len(session->in_buffer);
|
||||
if (buffer_len > 0) {
|
||||
int rc;
|
||||
rc = packet_decrypt(session,
|
||||
ssh_buffer_get_begin(session->in_buffer),
|
||||
buffer_len);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Packet decrypt error");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
@@ -300,6 +305,8 @@ int packet_send1(ssh_session session) {
|
||||
ssh_buffer_get_len(session->out_buffer));
|
||||
#endif
|
||||
|
||||
/* session->out_buffer should have more than sizeof(uint32_t) bytes
|
||||
in it as required for packet_encrypt */
|
||||
packet_encrypt(session, (unsigned char *)ssh_buffer_get_begin(session->out_buffer) + sizeof(uint32_t),
|
||||
ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t));
|
||||
|
||||
|
||||
@@ -43,29 +43,35 @@
|
||||
* @brief Handle a SSH_DISCONNECT packet.
|
||||
*/
|
||||
SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){
|
||||
uint32_t code;
|
||||
char *error=NULL;
|
||||
ssh_string error_s;
|
||||
(void)user;
|
||||
(void)type;
|
||||
buffer_get_u32(packet, &code);
|
||||
int rc;
|
||||
uint32_t code = 0;
|
||||
char *error = NULL;
|
||||
ssh_string error_s;
|
||||
(void)user;
|
||||
(void)type;
|
||||
|
||||
rc = buffer_get_u32(packet, &code);
|
||||
if (rc != 0) {
|
||||
code = ntohl(code);
|
||||
}
|
||||
|
||||
error_s = buffer_get_ssh_string(packet);
|
||||
if (error_s != NULL) {
|
||||
error = ssh_string_to_char(error_s);
|
||||
ssh_string_free(error_s);
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT %d:%s",code,
|
||||
error != NULL ? error : "no error");
|
||||
SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT %d:%s",
|
||||
code, error != NULL ? error : "no error");
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Received SSH_MSG_DISCONNECT: %d:%s",code,
|
||||
error != NULL ? error : "no error");
|
||||
"Received SSH_MSG_DISCONNECT: %d:%s",
|
||||
code, error != NULL ? error : "no error");
|
||||
SAFE_FREE(error);
|
||||
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive = 0;
|
||||
session->session_state= SSH_SESSION_STATE_ERROR;
|
||||
/* TODO: handle a graceful disconnect */
|
||||
return SSH_PACKET_USED;
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
/* TODO: handle a graceful disconnect */
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -59,6 +60,9 @@ uint32_t packet_decrypt_len(ssh_session session, char *crypted){
|
||||
int packet_decrypt(ssh_session session, void *data,uint32_t len) {
|
||||
struct ssh_cipher_struct *crypto = session->current_crypto->in_cipher;
|
||||
char *out = NULL;
|
||||
|
||||
assert(len);
|
||||
|
||||
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;
|
||||
@@ -89,6 +93,8 @@ unsigned char *packet_encrypt(ssh_session session, void *data, uint32_t len) {
|
||||
unsigned int finallen;
|
||||
uint32_t seq;
|
||||
|
||||
assert(len);
|
||||
|
||||
if (!session->current_crypto) {
|
||||
return NULL; /* nothing to do here */
|
||||
}
|
||||
|
||||
86
src/pki.c
86
src/pki.c
@@ -98,6 +98,25 @@ enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey) {
|
||||
return SSH_KEYTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the ECDSA key name ("ecdsa-sha2-nistp256" for example)
|
||||
*
|
||||
* @param[in] key the ssh_key whose ECDSA name to get
|
||||
*
|
||||
* @returns the ECDSA key name ("ecdsa-sha2-nistp256" for example)
|
||||
*
|
||||
* @returns "unknown" if the ECDSA key name is not known
|
||||
*/
|
||||
const char *ssh_pki_key_ecdsa_name(const ssh_key key)
|
||||
{
|
||||
#ifdef HAVE_OPENSSL_ECC /* FIXME Better ECC check needed */
|
||||
return pki_key_ecdsa_nid_to_name(key->ecdsa_nid);
|
||||
#else
|
||||
(void) key; /* unused */
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates a new empty SSH key
|
||||
* @returns an empty ssh_key handle, or NULL on error.
|
||||
@@ -331,6 +350,10 @@ void ssh_signature_free(ssh_signature sig)
|
||||
#endif
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
#if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ECC)
|
||||
ECDSA_SIG_free(sig->ecdsa_sig);
|
||||
#endif
|
||||
break;
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
@@ -720,6 +743,9 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Update key type */
|
||||
key->type_c = ssh_pki_key_ecdsa_name(key);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -976,8 +1002,12 @@ int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
#ifdef HAVE_ECC
|
||||
rc = pki_key_generate_ecdsa(key, parameter);
|
||||
if(rc == SSH_ERROR)
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Update key type */
|
||||
key->type_c = ssh_pki_key_ecdsa_name(key);
|
||||
break;
|
||||
#endif
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
@@ -1295,6 +1325,11 @@ int ssh_pki_signature_verify_blob(ssh_session session,
|
||||
|
||||
evp(key->ecdsa_nid, digest, dlen, ehash, &elen);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash to be verified with ecdsa",
|
||||
ehash, elen);
|
||||
#endif
|
||||
|
||||
rc = pki_signature_verify(session,
|
||||
sig,
|
||||
key,
|
||||
@@ -1361,6 +1396,10 @@ ssh_string ssh_pki_do_sign(ssh_session session,
|
||||
evp_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
|
||||
evp_final(ctx, ehash, &elen);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash being signed", ehash, elen);
|
||||
#endif
|
||||
|
||||
sig = pki_do_sign(privkey, ehash, elen);
|
||||
#endif
|
||||
} else {
|
||||
@@ -1454,10 +1493,8 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
const ssh_key privkey)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto;
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
ssh_signature sig;
|
||||
ssh_string sig_blob;
|
||||
SHACTX ctx;
|
||||
int rc;
|
||||
|
||||
if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) {
|
||||
@@ -1466,24 +1503,47 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
crypto = session->next_crypto ? session->next_crypto :
|
||||
session->current_crypto;
|
||||
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (crypto->secret_hash == NULL){
|
||||
ssh_set_error(session,SSH_FATAL,"Missing secret_hash");
|
||||
return NULL;
|
||||
}
|
||||
sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||
sha1_final(hash, ctx);
|
||||
|
||||
if (privkey->type == SSH_KEYTYPE_ECDSA) {
|
||||
#ifdef HAVE_ECC
|
||||
unsigned char ehash[EVP_DIGEST_LEN] = {0};
|
||||
uint32_t elen;
|
||||
|
||||
evp(privkey->ecdsa_nid, crypto->secret_hash, crypto->digest_len,
|
||||
ehash, &elen);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
|
||||
ssh_print_hexa("Hash being signed", ehash, elen);
|
||||
#endif
|
||||
|
||||
sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
sig = pki_do_sign_sessionid(privkey, ehash, elen);
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
SHACTX ctx;
|
||||
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||
sha1_final(hash, ctx);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
|
||||
#endif
|
||||
|
||||
sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_pki_export_signature_blob(sig, &sig_blob);
|
||||
|
||||
198
src/pki_crypto.c
198
src/pki_crypto.c
@@ -89,7 +89,7 @@ static int pki_key_ecdsa_to_nid(EC_KEY *k)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const char *pki_key_ecdsa_nid_to_name(int nid)
|
||||
const char *pki_key_ecdsa_nid_to_name(int nid)
|
||||
{
|
||||
switch (nid) {
|
||||
case NID_X9_62_prime256v1:
|
||||
@@ -200,9 +200,11 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* EC_KEY_set_public_key duplicates p */
|
||||
ok = EC_KEY_set_public_key(key->ecdsa, p);
|
||||
EC_POINT_free(p);
|
||||
if (!ok) {
|
||||
EC_POINT_free(p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -343,13 +345,13 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
new->ecdsa_nid = key->ecdsa_nid;
|
||||
|
||||
/* privkey -> pubkey */
|
||||
if (demote && ssh_key_is_private(key)) {
|
||||
const EC_POINT *p;
|
||||
int ok;
|
||||
|
||||
new->ecdsa_nid = key->ecdsa_nid;
|
||||
|
||||
new->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
|
||||
if (new->ecdsa == NULL) {
|
||||
goto fail;
|
||||
@@ -381,10 +383,20 @@ fail:
|
||||
}
|
||||
|
||||
int pki_key_generate_rsa(ssh_key key, int parameter){
|
||||
key->rsa = RSA_generate_key(parameter, 65537, NULL, NULL);
|
||||
if(key->rsa == NULL)
|
||||
return SSH_ERROR;
|
||||
return SSH_OK;
|
||||
BIGNUM *e;
|
||||
int rc;
|
||||
|
||||
e = BN_new();
|
||||
key->rsa = RSA_new();
|
||||
|
||||
BN_set_word(e, 65537);
|
||||
rc = RSA_generate_key_ex(key->rsa, parameter, e, NULL);
|
||||
|
||||
BN_free(e);
|
||||
|
||||
if (rc == -1 || key->rsa == NULL)
|
||||
return SSH_ERROR;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int pki_key_generate_dss(ssh_key key, int parameter){
|
||||
@@ -1094,41 +1106,65 @@ static ssh_string _RSA_do_sign(const unsigned char *digest,
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
|
||||
{
|
||||
char buffer[40] = { 0 };
|
||||
ssh_string sig_blob = NULL;
|
||||
|
||||
ssh_string r;
|
||||
int r_len, r_offset_in, r_offset_out;
|
||||
|
||||
ssh_string s;
|
||||
int s_len, s_offset_in, s_offset_out;
|
||||
|
||||
r = make_bignum_string(sig->dsa_sig->r);
|
||||
if (r == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = make_bignum_string(sig->dsa_sig->s);
|
||||
if (s == NULL) {
|
||||
ssh_string_free(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r_len = ssh_string_len(r);
|
||||
r_offset_in = (r_len > 20) ? (r_len - 20) : 0;
|
||||
r_offset_out = (r_len < 20) ? (20 - r_len) : 0;
|
||||
|
||||
s_len = ssh_string_len(s);
|
||||
s_offset_in = (s_len > 20) ? (s_len - 20) : 0;
|
||||
s_offset_out = (s_len < 20) ? (20 - s_len) : 0;
|
||||
|
||||
memcpy(buffer + r_offset_out,
|
||||
((char *)ssh_string_data(r)) + r_offset_in,
|
||||
r_len - r_offset_in);
|
||||
memcpy(buffer + 20 + s_offset_out,
|
||||
((char *)ssh_string_data(s)) + s_offset_in,
|
||||
s_len - s_offset_in);
|
||||
|
||||
ssh_string_free(r);
|
||||
ssh_string_free(s);
|
||||
|
||||
sig_blob = ssh_string_new(40);
|
||||
if (sig_blob == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh_string_fill(sig_blob, buffer, 40);
|
||||
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
{
|
||||
char buffer[40] = {0};
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_string r;
|
||||
ssh_string s;
|
||||
ssh_string sig_blob = NULL;
|
||||
|
||||
switch(sig->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
r = make_bignum_string(sig->dsa_sig->r);
|
||||
if (r == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
s = make_bignum_string(sig->dsa_sig->s);
|
||||
if (s == NULL) {
|
||||
ssh_string_free(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(buffer,
|
||||
((char *)ssh_string_data(r)) + ssh_string_len(r) - 20,
|
||||
20);
|
||||
memcpy(buffer + 20,
|
||||
((char *)ssh_string_data(s)) + ssh_string_len(s) - 20,
|
||||
20);
|
||||
|
||||
ssh_string_free(r);
|
||||
ssh_string_free(s);
|
||||
|
||||
sig_blob = ssh_string_new(40);
|
||||
if (sig_blob == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh_string_fill(sig_blob, buffer, 40);
|
||||
sig_blob = pki_dsa_signature_to_blob(sig);
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
@@ -1188,6 +1224,67 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
static ssh_signature pki_signature_from_rsa_blob(const ssh_key pubkey,
|
||||
const ssh_string sig_blob,
|
||||
ssh_signature sig)
|
||||
{
|
||||
uint32_t pad_len = 0;
|
||||
char *blob_orig;
|
||||
char *blob_padded_data;
|
||||
ssh_string sig_blob_padded;
|
||||
|
||||
size_t rsalen = 0;
|
||||
size_t len = ssh_string_len(sig_blob);
|
||||
|
||||
if (pubkey->rsa == NULL) {
|
||||
ssh_pki_log("Pubkey RSA field NULL");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
rsalen = RSA_size(pubkey->rsa);
|
||||
if (len > rsalen) {
|
||||
ssh_pki_log("Signature is too big: %lu > %lu",
|
||||
(unsigned long)len, (unsigned long)rsalen);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_pki_log("RSA signature len: %lu", (unsigned long)len);
|
||||
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
|
||||
#endif
|
||||
|
||||
if (len == rsalen) {
|
||||
sig->rsa_sig = ssh_string_copy(sig_blob);
|
||||
} else {
|
||||
/* pad the blob to the expected rsalen size */
|
||||
ssh_pki_log("RSA signature len %lu < %lu",
|
||||
(unsigned long)len, (unsigned long)rsalen);
|
||||
|
||||
pad_len = rsalen - len;
|
||||
|
||||
sig_blob_padded = ssh_string_new(rsalen);
|
||||
if (sig_blob_padded == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
blob_padded_data = (char *) ssh_string_data(sig_blob_padded);
|
||||
blob_orig = (char *) ssh_string_data(sig_blob);
|
||||
|
||||
/* front-pad the buffer with zeroes */
|
||||
BURN_BUFFER(blob_padded_data, pad_len);
|
||||
/* fill the rest with the actual signature blob */
|
||||
memcpy(blob_padded_data + pad_len, blob_orig, len);
|
||||
|
||||
sig->rsa_sig = sig_blob_padded;
|
||||
}
|
||||
|
||||
return sig;
|
||||
|
||||
errout:
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
const ssh_string sig_blob,
|
||||
enum ssh_keytypes_e type)
|
||||
@@ -1196,7 +1293,6 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
ssh_string r;
|
||||
ssh_string s;
|
||||
size_t len;
|
||||
size_t rsalen;
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
@@ -1260,29 +1356,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
rsalen = RSA_size(pubkey->rsa);
|
||||
|
||||
if (len > rsalen) {
|
||||
ssh_pki_log("Signature is to big size: %lu",
|
||||
(unsigned long)len);
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len < rsalen) {
|
||||
ssh_pki_log("RSA signature len %lu < %lu",
|
||||
(unsigned long)len, (unsigned long)rsalen);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_pki_log("RSA signature len: %lu", (unsigned long)len);
|
||||
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
|
||||
#endif
|
||||
sig->rsa_sig = ssh_string_copy(sig_blob);
|
||||
if (sig->rsa_sig == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
}
|
||||
sig = pki_signature_from_rsa_blob(pubkey, sig_blob, sig);
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
@@ -1323,7 +1397,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
|
||||
#endif
|
||||
|
||||
sig->ecdsa_sig->r = make_string_bn(r);
|
||||
make_string_bn_inplace(r, sig->ecdsa_sig->r);
|
||||
ssh_string_burn(r);
|
||||
ssh_string_free(r);
|
||||
if (sig->ecdsa_sig->r == NULL) {
|
||||
@@ -1344,7 +1418,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
|
||||
#endif
|
||||
|
||||
sig->ecdsa_sig->s = make_string_bn(s);
|
||||
make_string_bn_inplace(s, sig->ecdsa_sig->s);
|
||||
ssh_string_burn(s);
|
||||
ssh_string_free(s);
|
||||
if (sig->ecdsa_sig->s == NULL) {
|
||||
|
||||
@@ -1657,6 +1657,7 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
return NULL;
|
||||
}
|
||||
sig->type = key->type;
|
||||
sig->type_c = key->type_c;
|
||||
|
||||
switch(key->type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
|
||||
@@ -545,7 +545,7 @@ int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){
|
||||
* @see ssh_scp_request_get_warning()
|
||||
*/
|
||||
int ssh_scp_pull_request(ssh_scp scp){
|
||||
char buffer[4096] = {0};
|
||||
char buffer[MAX_BUF_SIZE] = {0};
|
||||
char *mode=NULL;
|
||||
char *p,*tmp;
|
||||
uint64_t size;
|
||||
@@ -642,7 +642,7 @@ int ssh_scp_pull_request(ssh_scp scp){
|
||||
* the message failed, or sending it in a bad state.
|
||||
*/
|
||||
int ssh_scp_deny_request(ssh_scp scp, const char *reason){
|
||||
char buffer[4096];
|
||||
char buffer[MAX_BUF_SIZE];
|
||||
int err;
|
||||
if(scp==NULL)
|
||||
return SSH_ERROR;
|
||||
@@ -814,7 +814,7 @@ int ssh_scp_integer_mode(const char *mode){
|
||||
*/
|
||||
char *ssh_scp_string_mode(int mode){
|
||||
char buffer[16];
|
||||
snprintf(buffer,sizeof(buffer),"%.4d",mode);
|
||||
snprintf(buffer,sizeof(buffer),"%.4o",mode);
|
||||
return strdup(buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,7 @@ int ssh_get_key_params(ssh_session session, ssh_key *privkey){
|
||||
*privkey = session->srv.ecdsa_key;
|
||||
break;
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
default:
|
||||
*privkey = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +226,11 @@ void ssh_free(ssh_session session) {
|
||||
#endif /* _WIN32 */
|
||||
|
||||
ssh_key_free(session->srv.dsa_key);
|
||||
session->srv.dsa_key = NULL;
|
||||
ssh_key_free(session->srv.rsa_key);
|
||||
session->srv.rsa_key = NULL;
|
||||
ssh_key_free(session->srv.ecdsa_key);
|
||||
session->srv.ecdsa_key = NULL;
|
||||
|
||||
if (session->ssh_message_list) {
|
||||
ssh_message msg;
|
||||
@@ -261,6 +265,7 @@ void ssh_free(ssh_session session) {
|
||||
SAFE_FREE(session->banner);
|
||||
|
||||
SAFE_FREE(session->opts.bindaddr);
|
||||
SAFE_FREE(session->opts.custombanner);
|
||||
SAFE_FREE(session->opts.username);
|
||||
SAFE_FREE(session->opts.host);
|
||||
SAFE_FREE(session->opts.sshdir);
|
||||
@@ -275,7 +280,7 @@ void ssh_free(ssh_session session) {
|
||||
}
|
||||
}
|
||||
|
||||
/* burn connection, it could hang sensitive datas */
|
||||
/* burn connection, it could contain sensitive data */
|
||||
BURN_BUFFER(session, sizeof(struct ssh_session_struct));
|
||||
SAFE_FREE(session);
|
||||
}
|
||||
@@ -309,6 +314,38 @@ const char* ssh_get_serverbanner(ssh_session session) {
|
||||
return session->serverbanner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the name of the input for the given session.
|
||||
*
|
||||
* @param[in] session The SSH session.
|
||||
*
|
||||
* @return Returns cipher name or NULL.
|
||||
*/
|
||||
const char* ssh_get_cipher_in(ssh_session session) {
|
||||
if ((session != NULL) &&
|
||||
(session->current_crypto != NULL) &&
|
||||
(session->current_crypto->in_cipher != NULL)) {
|
||||
return session->current_crypto->in_cipher->name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the name of the output cipher for the given session.
|
||||
*
|
||||
* @param[in] session The SSH session.
|
||||
*
|
||||
* @return Returns cipher name or NULL.
|
||||
*/
|
||||
const char* ssh_get_cipher_out(ssh_session session) {
|
||||
if ((session != NULL) &&
|
||||
(session->current_crypto != NULL) &&
|
||||
(session->current_crypto->out_cipher != NULL)) {
|
||||
return session->current_crypto->out_cipher->name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnect impolitely from a remote host by closing the socket.
|
||||
*
|
||||
@@ -567,7 +604,11 @@ int ssh_handle_packets_termination(ssh_session session,
|
||||
}
|
||||
}
|
||||
|
||||
ssh_timestamp_init(&ts);
|
||||
/* avoid unnecessary syscall for the SSH_TIMEOUT_NONBLOCKING case */
|
||||
if (timeout != SSH_TIMEOUT_NONBLOCKING) {
|
||||
ssh_timestamp_init(&ts);
|
||||
}
|
||||
|
||||
tm = timeout;
|
||||
while(!fct(user)) {
|
||||
ret = ssh_handle_packets(session, tm);
|
||||
@@ -695,8 +736,13 @@ void ssh_socket_exception_callback(int code, int errno_code, void *user){
|
||||
ssh_session session=(ssh_session)user;
|
||||
|
||||
SSH_LOG(SSH_LOG_RARE,"Socket exception callback: %d (%d)",code, errno_code);
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
ssh_set_error(session,SSH_FATAL,"Socket error: %s",strerror(errno_code));
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
if (errno_code == 0 && code == SSH_SOCKET_EXCEPTION_EOF) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: disconnected");
|
||||
} else {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: %s", strerror(errno_code));
|
||||
}
|
||||
|
||||
session->ssh_connection_callback(session);
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload){
|
||||
}
|
||||
|
||||
sftp_packet sftp_packet_read(sftp_session sftp) {
|
||||
unsigned char buffer[4096];
|
||||
unsigned char buffer[MAX_BUF_SIZE];
|
||||
sftp_packet packet = NULL;
|
||||
uint32_t size;
|
||||
int r;
|
||||
|
||||
@@ -218,7 +218,7 @@ void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks){
|
||||
*/
|
||||
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s){
|
||||
ssh_socket s=(ssh_socket )v_s;
|
||||
char buffer[4096];
|
||||
char buffer[MAX_BUF_SIZE];
|
||||
int r;
|
||||
int err=0;
|
||||
socklen_t errlen=sizeof(err);
|
||||
@@ -291,7 +291,7 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
||||
buffer_get_rest_len(s->in_buffer),
|
||||
s->callbacks->userdata);
|
||||
buffer_pass_bytes(s->in_buffer,r);
|
||||
} while (r > 0);
|
||||
} while ((r > 0) && (s->state == SSH_SOCKET_CONNECTED));
|
||||
/* p may have been freed, so don't use it
|
||||
* anymore in this function */
|
||||
p = NULL;
|
||||
@@ -440,6 +440,8 @@ void ssh_socket_close(ssh_socket s){
|
||||
ssh_poll_free(s->poll_out);
|
||||
s->poll_out=NULL;
|
||||
}
|
||||
|
||||
s->state = SSH_SOCKET_CLOSED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -235,10 +235,11 @@ struct ssh_string_struct *ssh_string_copy(struct ssh_string_struct *s) {
|
||||
* @param[in] s The string to burn.
|
||||
*/
|
||||
void ssh_string_burn(struct ssh_string_struct *s) {
|
||||
if (s == NULL) {
|
||||
return;
|
||||
}
|
||||
memset(s->data, 'X', ssh_string_len(s));
|
||||
if (s == NULL || s->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
BURN_BUFFER(s->data, ssh_string_len(s));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,8 +59,28 @@ struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void) {
|
||||
static struct ssh_threads_callbacks_struct *user_callbacks =&ssh_threads_noop;
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#if (GCRYPT_VERSION_NUMBER >= 0x010600)
|
||||
/* libgcrypt >= 1.6 does not support custom callbacks */
|
||||
GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
||||
|
||||
/* Libgcrypt specific way of handling thread callbacks */
|
||||
static int libgcrypt_thread_init(void){
|
||||
if(user_callbacks == NULL)
|
||||
return SSH_ERROR;
|
||||
if(user_callbacks == &ssh_threads_noop)
|
||||
return SSH_OK;
|
||||
if (strcmp(user_callbacks->type, "threads_pthread") == 0){
|
||||
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
|
||||
return SSH_OK;
|
||||
} else {
|
||||
/* not supported */
|
||||
SSH_LOG(SSH_LOG_WARN, "Custom thread handlers not supported with libgcrypt >=1.6, using pthreads");
|
||||
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
|
||||
return SSH_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/* Libgcrypt < 1.6 specific way of handling thread callbacks */
|
||||
|
||||
static struct gcry_thread_cbs gcrypt_threads_callbacks;
|
||||
|
||||
@@ -79,7 +99,8 @@ static int libgcrypt_thread_init(void){
|
||||
gcry_control(GCRYCTL_SET_THREAD_CBS, &gcrypt_threads_callbacks);
|
||||
return SSH_OK;
|
||||
}
|
||||
#else
|
||||
#endif /* GCRYPT_VERSION_NUMBER */
|
||||
#else /* HAVE_LIBGCRYPT */
|
||||
|
||||
/* Libcrypto specific stuff */
|
||||
|
||||
|
||||
@@ -53,73 +53,75 @@ include_directories(
|
||||
${LIBSSH_THREADS_PRIVATE_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_library(${LIBSSH_THREADS_SHARED_LIBRARY} SHARED ${libssh_threads_SRCS})
|
||||
if (libssh_threads_SRCS)
|
||||
add_library(${LIBSSH_THREADS_SHARED_LIBRARY} SHARED ${libssh_threads_SRCS})
|
||||
|
||||
target_link_libraries(${LIBSSH_THREADS_SHARED_LIBRARY} ${LIBSSH_THREADS_LINK_LIBRARIES})
|
||||
target_link_libraries(${LIBSSH_THREADS_SHARED_LIBRARY} ${LIBSSH_THREADS_LINK_LIBRARIES})
|
||||
|
||||
set_target_properties(
|
||||
${LIBSSH_THREADS_SHARED_LIBRARY}
|
||||
PROPERTIES
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
SOVERSION
|
||||
${LIBRARY_SOVERSION}
|
||||
OUTPUT_NAME
|
||||
ssh_threads
|
||||
DEFINE_SYMBOL
|
||||
LIBSSH_EXPORTS
|
||||
)
|
||||
|
||||
if (WITH_VISIBILITY_HIDDEN)
|
||||
set_target_properties(${LIBSSH_THREADS_SHARED_LIBRARY} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
endif (WITH_VISIBILITY_HIDDEN)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
${LIBSSH_THREADS_SHARED_LIBRARY}
|
||||
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
COMPONENT libraries
|
||||
)
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
add_library(${LIBSSH_THREADS_STATIC_LIBRARY} STATIC ${libssh_threads_SRCS})
|
||||
|
||||
if (MSVC)
|
||||
set(OUTPUT_SUFFIX static)
|
||||
else (MSVC)
|
||||
set(OUTPUT_SUFFIX )
|
||||
endif (MSVC)
|
||||
|
||||
set_target_properties(
|
||||
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||
PROPERTIES
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
SOVERSION
|
||||
${LIBRARY_SOVERSION}
|
||||
OUTPUT_NAME
|
||||
ssh_threads
|
||||
ARCHIVE_OUTPUT_DIRECTORY
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
set_target_properties(
|
||||
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-DLIBSSH_STATIC"
|
||||
)
|
||||
endif (WIN32)
|
||||
${LIBSSH_THREADS_SHARED_LIBRARY}
|
||||
PROPERTIES
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
SOVERSION
|
||||
${LIBRARY_SOVERSION}
|
||||
OUTPUT_NAME
|
||||
ssh_threads
|
||||
DEFINE_SYMBOL
|
||||
LIBSSH_EXPORTS
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
|
||||
COMPONENT
|
||||
libraries
|
||||
)
|
||||
endif (WITH_STATIC_LIB)
|
||||
if (WITH_VISIBILITY_HIDDEN)
|
||||
set_target_properties(${LIBSSH_THREADS_SHARED_LIBRARY} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
endif (WITH_VISIBILITY_HIDDEN)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
${LIBSSH_THREADS_SHARED_LIBRARY}
|
||||
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
COMPONENT libraries
|
||||
)
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
add_library(${LIBSSH_THREADS_STATIC_LIBRARY} STATIC ${libssh_threads_SRCS})
|
||||
|
||||
if (MSVC)
|
||||
set(OUTPUT_SUFFIX static)
|
||||
else (MSVC)
|
||||
set(OUTPUT_SUFFIX )
|
||||
endif (MSVC)
|
||||
|
||||
set_target_properties(
|
||||
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||
PROPERTIES
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
SOVERSION
|
||||
${LIBRARY_SOVERSION}
|
||||
OUTPUT_NAME
|
||||
ssh_threads
|
||||
ARCHIVE_OUTPUT_DIRECTORY
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
set_target_properties(
|
||||
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-DLIBSSH_STATIC"
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
${LIBSSH_THREADS_STATIC_LIBRARY}
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
|
||||
COMPONENT
|
||||
libraries
|
||||
)
|
||||
endif (WITH_STATIC_LIB)
|
||||
endif (libssh_threads_SRCS)
|
||||
|
||||
@@ -130,10 +130,13 @@ void crypto_free(struct ssh_crypto_struct *crypto){
|
||||
(deflateEnd(crypto->compress_out_ctx) != 0)) {
|
||||
inflateEnd(crypto->compress_out_ctx);
|
||||
}
|
||||
SAFE_FREE(crypto->compress_out_ctx);
|
||||
|
||||
if (crypto->compress_in_ctx &&
|
||||
(deflateEnd(crypto->compress_in_ctx) != 0)) {
|
||||
inflateEnd(crypto->compress_in_ctx);
|
||||
}
|
||||
SAFE_FREE(crypto->compress_in_ctx);
|
||||
#endif /* WITH_ZLIB */
|
||||
if(crypto->encryptIV)
|
||||
SAFE_FREE(crypto->encryptIV);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "torture.h"
|
||||
#include <libssh/libssh.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define HOST "localhost"
|
||||
/* Should work until Apnic decides to assign it :) */
|
||||
@@ -54,12 +55,11 @@ static void torture_connect_nonblocking(void **state) {
|
||||
ssh_set_blocking(session,0);
|
||||
|
||||
do {
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc != SSH_ERROR);
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc != SSH_ERROR);
|
||||
} while(rc == SSH_AGAIN);
|
||||
|
||||
assert_true(rc==SSH_OK);
|
||||
|
||||
assert_true(rc == SSH_OK);
|
||||
}
|
||||
|
||||
static void torture_connect_timeout(void **state) {
|
||||
@@ -84,9 +84,9 @@ static void torture_connect_timeout(void **state) {
|
||||
sec = after.tv_sec - before.tv_sec;
|
||||
usec = after.tv_usec - before.tv_usec;
|
||||
/* Borrow a second for the missing usecs, but don't bother calculating */
|
||||
if(usec < 0)
|
||||
if (usec < 0)
|
||||
sec--;
|
||||
assert_in_range(sec,1,3);
|
||||
assert_in_range(sec, 1, 3);
|
||||
}
|
||||
|
||||
static void torture_connect_double(void **state) {
|
||||
@@ -102,10 +102,9 @@ static void torture_connect_double(void **state) {
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
}
|
||||
|
||||
static void torture_connect_failure(void **state){
|
||||
static void torture_connect_failure(void **state) {
|
||||
/*
|
||||
* The intent of this test is to check that a fresh
|
||||
* ssh_new/ssh_disconnect/ssh_free sequence doesn't crash/leak
|
||||
@@ -114,6 +113,30 @@ static void torture_connect_failure(void **state){
|
||||
ssh_session session = *state;
|
||||
ssh_disconnect(session);
|
||||
}
|
||||
|
||||
static void torture_connect_socket(void **state) {
|
||||
ssh_session session = *state;
|
||||
|
||||
int rc;
|
||||
int sock_fd = 0;
|
||||
struct sockaddr_in server_addr;
|
||||
|
||||
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
assert_true(sock_fd > 0);
|
||||
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(22);
|
||||
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
rc = connect(sock_fd, &server_addr, sizeof(server_addr));
|
||||
assert_true(rc == 0);
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_FD, &sock_fd);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc == SSH_OK);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
const UnitTest tests[] = {
|
||||
@@ -121,6 +144,7 @@ int torture_run_tests(void) {
|
||||
unit_test_setup_teardown(torture_connect_double, setup, teardown),
|
||||
unit_test_setup_teardown(torture_connect_failure, setup, teardown),
|
||||
unit_test_setup_teardown(torture_connect_timeout, setup, teardown),
|
||||
unit_test_setup_teardown(torture_connect_socket, setup, teardown),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
@@ -23,8 +23,26 @@
|
||||
|
||||
#include "torture.h"
|
||||
#include "session.c"
|
||||
#include "known_hosts.c"
|
||||
|
||||
#define KNOWNHOSTFILES "libssh_torture_knownhosts"
|
||||
#define BADRSA "AAAAB3NzaC1yc2EAAAADAQABAAABAQChm5" \
|
||||
"a6Av65O8cKtx5YXOnui3wJnYE6A6J/I4kZSAibbn14Jcl+34VJQwv96f25AxNmo" \
|
||||
"NwoiZV93IzdypQmiuieh6s6wB9WhYjU9K/6CkIpNhpCxswA90b3ePjS7LnR9B9J" \
|
||||
"slPSbG1H0KC1c5lb7G3utXteXtM+4YvCvpN5VdC4CpghT+p0cwN2Na8Md5vRItz" \
|
||||
"YgIytryNn7LLiwYfoSxvWigFrTTZsrVtCOYyNgklmffpGdzuC43wdANvTewfI9G" \
|
||||
"o71r8EXmEc228CrYPmb8Scv3mpXFK/BosohSGkPlEHu9lf3YjnknBicDaVtJOYp" \
|
||||
"wnXJPjZo2EhG79HxDRpjJHH"
|
||||
#define BADDSA "AAAAB3NzaC1kc3MAAACBAITDKqGQ5aC5wHySG6ZdL1+BVBY2nLP5vzw3i3pvZfP" \
|
||||
"yNUS0UCwrt5pajsMvDRGXXebTJhWVonDnv8tpSgiuIBXMZrma8CU1KCFGRzwb/n8" \
|
||||
"cc5tJmIphlOUTrObjBmsRz7u1eZmoaddXC9ask6BNnt0DmhzYi2esL3mbardy8IN" \
|
||||
"zAAAAFQDlPFCm410pgQQPb3X5FWjyVEIl+QAAAIAp0vqfir8K8p+zP4dzFG7ppnt" \
|
||||
"DjaXf3ge6URF7f5xPDo6CClGo2JQ2REF8NxM7K9cLgR9Ifx2ahO48UMgrXEl/BOp" \
|
||||
"IQHpeBqUz26a49O5J0WEW16YSUHxWwMxWVe/SRmyKdTUZJ6fcepH88JNqm3XudNn" \
|
||||
"s78grM+yx9mcXnK2AsAAAAIBxpF8ZQIlGrSgwCmCfwjP156bC3Ya6LYf9ZpLJ0dX" \
|
||||
"EcxqLVllrNEvd2EGD9p16BYO2yaalYon8im59PtOcul2ay5XQ6rVDQ2T0pgNUpsI" \
|
||||
"h0dSi8VJXI1wes5HTyLsv9VBmU1uCXUUvufoQKfF/OcSH0ufcCpnd62g1/adZcy2" \
|
||||
"WJg=="
|
||||
|
||||
static void setup(void **state) {
|
||||
int verbosity=torture_libssh_verbosity();
|
||||
@@ -93,10 +111,184 @@ static void torture_knownhosts_port(void **state) {
|
||||
assert_true(rc == SSH_SERVER_KNOWN_OK);
|
||||
}
|
||||
|
||||
static void torture_knownhosts_fail(void **state) {
|
||||
ssh_session session = *state;
|
||||
FILE *file;
|
||||
int rc;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-rsa");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
file = fopen(KNOWNHOSTFILES, "w");
|
||||
assert_true(file != NULL);
|
||||
fprintf(file, "localhost ssh-rsa %s\n", BADRSA);
|
||||
fclose(file);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc==SSH_OK);
|
||||
|
||||
rc = ssh_is_server_known(session);
|
||||
assert_true(rc == SSH_SERVER_KNOWN_CHANGED);
|
||||
}
|
||||
|
||||
static void torture_knownhosts_other(void **state) {
|
||||
ssh_session session = *state;
|
||||
FILE *file;
|
||||
int rc;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-dss");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
file = fopen(KNOWNHOSTFILES, "w");
|
||||
assert_true(file != NULL);
|
||||
fprintf(file, "localhost ssh-rsa %s\n", BADRSA);
|
||||
fclose(file);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc==SSH_OK);
|
||||
|
||||
rc = ssh_is_server_known(session);
|
||||
assert_true(rc == SSH_SERVER_FOUND_OTHER);
|
||||
}
|
||||
|
||||
static void torture_knownhosts_other_auto(void **state) {
|
||||
ssh_session session = *state;
|
||||
int rc;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-dss");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc==SSH_OK);
|
||||
|
||||
rc = ssh_is_server_known(session);
|
||||
assert_true(rc == SSH_SERVER_NOT_KNOWN);
|
||||
|
||||
rc = ssh_write_knownhost(session);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
|
||||
/* connect again and check host key */
|
||||
*state = session = ssh_new();
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc==SSH_OK);
|
||||
|
||||
/* ssh-rsa is the default but libssh should try ssh-dss instead */
|
||||
rc = ssh_is_server_known(session);
|
||||
assert_true(rc == SSH_SERVER_KNOWN_OK);
|
||||
}
|
||||
|
||||
static void torture_knownhosts_conflict(void **state) {
|
||||
ssh_session session = *state;
|
||||
FILE *file;
|
||||
int rc;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-rsa");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
file = fopen(KNOWNHOSTFILES, "w");
|
||||
assert_true(file != NULL);
|
||||
fprintf(file, "localhost ssh-rsa %s\n", BADRSA);
|
||||
fprintf(file, "localhost ssh-dss %s\n", BADDSA);
|
||||
fclose(file);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc==SSH_OK);
|
||||
|
||||
rc = ssh_is_server_known(session);
|
||||
assert_true(rc == SSH_SERVER_KNOWN_CHANGED);
|
||||
|
||||
rc = ssh_write_knownhost(session);
|
||||
assert_true(rc==SSH_OK);
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
|
||||
/* connect again and check host key */
|
||||
*state = session = ssh_new();
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-rsa");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_connect(session);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_is_server_known(session);
|
||||
assert_true(rc == SSH_SERVER_KNOWN_OK);
|
||||
}
|
||||
|
||||
static void torture_knownhosts_precheck(void **state) {
|
||||
ssh_session session = *state;
|
||||
FILE *file;
|
||||
int rc;
|
||||
char **kex;
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, KNOWNHOSTFILES);
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
file = fopen(KNOWNHOSTFILES, "w");
|
||||
assert_true(file != NULL);
|
||||
fprintf(file, "localhost ssh-rsa %s\n", BADRSA);
|
||||
fprintf(file, "localhost ssh-dss %s\n", BADDSA);
|
||||
fclose(file);
|
||||
|
||||
kex = ssh_knownhosts_algorithms(session);
|
||||
assert_true(kex != NULL);
|
||||
assert_string_equal(kex[0],"ssh-rsa");
|
||||
assert_string_equal(kex[1],"ssh-dss");
|
||||
assert_true(kex[2]==NULL);
|
||||
free(kex[1]);
|
||||
free(kex[0]);
|
||||
free(kex);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(torture_knownhosts_port, setup, teardown),
|
||||
unit_test_setup_teardown(torture_knownhosts_fail, setup, teardown),
|
||||
unit_test_setup_teardown(torture_knownhosts_other, setup, teardown),
|
||||
unit_test_setup_teardown(torture_knownhosts_other_auto, setup, teardown),
|
||||
unit_test_setup_teardown(torture_knownhosts_conflict, setup, teardown),
|
||||
unit_test_setup_teardown(torture_knownhosts_precheck, setup, teardown)
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
139
tests/test_ssh_bind_accept_fd.c
Normal file
139
tests/test_ssh_bind_accept_fd.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/* Test the ability to use ssh_bind_accept_fd.
|
||||
*
|
||||
* Expected behavior: Prints "SUCCESS!"
|
||||
*
|
||||
* Faulty behavior observed before change: Connection timeout
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <err.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct options {
|
||||
const char *server_keyfile;
|
||||
} options;
|
||||
|
||||
const char HOST[] = "127.0.0.1";
|
||||
const int PORT = 3333;
|
||||
|
||||
int get_connection() {
|
||||
int rc, server_socket, client_conn = -1;
|
||||
struct sockaddr_in server_socket_addr;
|
||||
struct sockaddr_storage client_conn_addr;
|
||||
socklen_t client_conn_addr_size = sizeof(client_conn_addr);
|
||||
|
||||
server_socket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (server_socket < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
server_socket_addr.sin_family = AF_INET;
|
||||
server_socket_addr.sin_port = htons(PORT);
|
||||
if (inet_pton(AF_INET, HOST, &server_socket_addr.sin_addr) != 1) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = bind(server_socket, (struct sockaddr *)&server_socket_addr,
|
||||
sizeof(server_socket_addr));
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (listen(server_socket, 0) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
client_conn = accept(server_socket,
|
||||
(struct sockaddr *)&client_conn_addr,
|
||||
&client_conn_addr_size);
|
||||
|
||||
out:
|
||||
return client_conn;
|
||||
}
|
||||
|
||||
void ssh_server() {
|
||||
ssh_bind bind;
|
||||
ssh_session session;
|
||||
|
||||
int client_conn = get_connection();
|
||||
if (client_conn < 0) {
|
||||
err(1, "get_connection");
|
||||
}
|
||||
|
||||
bind = ssh_bind_new();
|
||||
if (!bind) {
|
||||
errx(1, "ssh_bind_new");
|
||||
}
|
||||
|
||||
if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_DSAKEY,
|
||||
options.server_keyfile) != SSH_OK) {
|
||||
errx(1, "ssh_bind_options_set(SSH_BIND_OPTIONS_DSAKEY");
|
||||
}
|
||||
|
||||
session = ssh_new();
|
||||
if (!session) {
|
||||
errx(1, "ssh_new");
|
||||
}
|
||||
|
||||
if (ssh_bind_accept_fd(bind, session, client_conn) != SSH_OK) {
|
||||
errx(1, "ssh_bind_accept: %s", ssh_get_error(bind));
|
||||
}
|
||||
|
||||
if (ssh_handle_key_exchange(session) != SSH_OK) {
|
||||
errx(1, "ssh_handle_key_exchange: %s", ssh_get_error(session));
|
||||
}
|
||||
|
||||
printf("SUCCESS!\n");
|
||||
}
|
||||
|
||||
void ssh_client() {
|
||||
ssh_session session;
|
||||
|
||||
session = ssh_new();
|
||||
if (!session) {
|
||||
errx(1, "ssh_new");
|
||||
}
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, HOST) < 0) {
|
||||
errx(1, "ssh_options_set(SSH_OPTIONS_HOST)");
|
||||
}
|
||||
if (ssh_options_set(session, SSH_OPTIONS_PORT, &PORT) < 0) {
|
||||
errx(1, "ssh_options_set(SSH_OPTIONS_PORT)");
|
||||
}
|
||||
|
||||
if (ssh_connect(session) != SSH_OK) {
|
||||
errx(1, "ssh_connect: %s", ssh_get_error(session));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s <private key file>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
options.server_keyfile = argv[1];
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
errx(1, "fork");
|
||||
}
|
||||
if (pid == 0) {
|
||||
/* Allow the server to get set up */
|
||||
sleep(3);
|
||||
|
||||
ssh_client();
|
||||
} else {
|
||||
ssh_server();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -36,17 +36,36 @@ static void setup_dsa_key(void **state) {
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
static void setup_ecdsa_key(void **state) {
|
||||
int rc;
|
||||
static void setup_ecdsa_key(void **state, int ecdsa_bits) {
|
||||
int rc = -1;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
unlink(LIBSSH_ECDSA_TESTKEY);
|
||||
unlink(LIBSSH_ECDSA_TESTKEY ".pub");
|
||||
|
||||
rc = system("ssh-keygen -t ecdsa -q -N \"\" -f " LIBSSH_ECDSA_TESTKEY);
|
||||
if (ecdsa_bits == 256) {
|
||||
rc = system("ssh-keygen -t ecdsa -b 256 -q -N \"\" -f " LIBSSH_ECDSA_TESTKEY);
|
||||
} else if (ecdsa_bits == 384) {
|
||||
rc = system("ssh-keygen -t ecdsa -b 384 -q -N \"\" -f " LIBSSH_ECDSA_TESTKEY);
|
||||
} else if (ecdsa_bits == 521) {
|
||||
rc = system("ssh-keygen -t ecdsa -b 521 -q -N \"\" -f " LIBSSH_ECDSA_TESTKEY);
|
||||
}
|
||||
|
||||
assert_true(rc == 0);
|
||||
}
|
||||
|
||||
static void setup_ecdsa_key_521(void **state) {
|
||||
setup_ecdsa_key(state, 521);
|
||||
}
|
||||
|
||||
static void setup_ecdsa_key_384(void **state) {
|
||||
setup_ecdsa_key(state, 384);
|
||||
}
|
||||
|
||||
static void setup_ecdsa_key_256(void **state) {
|
||||
setup_ecdsa_key(state, 256);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void setup_both_keys(void **state) {
|
||||
@@ -766,6 +785,39 @@ static void torture_pki_duplicate_key_ecdsa(void **state)
|
||||
ssh_string_free_char(b64_key);
|
||||
ssh_string_free_char(b64_key_gen);
|
||||
}
|
||||
|
||||
/* Test case for bug #147: Private ECDSA key duplication did not carry
|
||||
* over parts of the key that then caused subsequent key demotion to
|
||||
* fail.
|
||||
*/
|
||||
static void torture_pki_ecdsa_duplicate_then_demote(void **state)
|
||||
{
|
||||
ssh_key pubkey;
|
||||
ssh_key privkey;
|
||||
ssh_key privkey_dup;
|
||||
int rc;
|
||||
|
||||
(void) state;
|
||||
|
||||
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&privkey);
|
||||
assert_true(rc == 0);
|
||||
|
||||
privkey_dup = ssh_key_dup(privkey);
|
||||
assert_true(privkey_dup != NULL);
|
||||
assert_int_equal(privkey->ecdsa_nid, privkey_dup->ecdsa_nid);
|
||||
|
||||
rc = ssh_pki_export_privkey_to_pubkey(privkey_dup, &pubkey);
|
||||
assert_true(rc == 0);
|
||||
assert_int_equal(pubkey->ecdsa_nid, privkey->ecdsa_nid);
|
||||
|
||||
ssh_key_free(pubkey);
|
||||
ssh_key_free(privkey);
|
||||
ssh_key_free(privkey_dup);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void torture_pki_generate_key_rsa(void **state)
|
||||
@@ -906,6 +958,9 @@ static void torture_pki_generate_key_ecdsa(void **state)
|
||||
int rc;
|
||||
ssh_key key;
|
||||
ssh_signature sign;
|
||||
enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN;
|
||||
const char *type_char = NULL;
|
||||
const char *etype_char = NULL;
|
||||
ssh_session session=ssh_new();
|
||||
(void) state;
|
||||
|
||||
@@ -916,6 +971,13 @@ static void torture_pki_generate_key_ecdsa(void **state)
|
||||
assert_true(sign != NULL);
|
||||
rc = pki_signature_verify(session,sign,key,HASH,20);
|
||||
assert_true(rc == SSH_OK);
|
||||
type = ssh_key_type(key);
|
||||
assert_true(type == SSH_KEYTYPE_ECDSA);
|
||||
type_char = ssh_key_type_to_char(type);
|
||||
assert_true(strcmp(type_char, "ssh-ecdsa") == 0);
|
||||
etype_char = ssh_pki_key_ecdsa_name(key);
|
||||
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp256") == 0);
|
||||
|
||||
ssh_signature_free(sign);
|
||||
ssh_key_free(key);
|
||||
key=NULL;
|
||||
@@ -927,6 +989,13 @@ static void torture_pki_generate_key_ecdsa(void **state)
|
||||
assert_true(sign != NULL);
|
||||
rc = pki_signature_verify(session,sign,key,HASH,20);
|
||||
assert_true(rc == SSH_OK);
|
||||
type = ssh_key_type(key);
|
||||
assert_true(type == SSH_KEYTYPE_ECDSA);
|
||||
type_char = ssh_key_type_to_char(type);
|
||||
assert_true(strcmp(type_char, "ssh-ecdsa") == 0);
|
||||
etype_char =ssh_pki_key_ecdsa_name(key);
|
||||
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp384") == 0);
|
||||
|
||||
ssh_signature_free(sign);
|
||||
ssh_key_free(key);
|
||||
key=NULL;
|
||||
@@ -938,6 +1007,13 @@ static void torture_pki_generate_key_ecdsa(void **state)
|
||||
assert_true(sign != NULL);
|
||||
rc = pki_signature_verify(session,sign,key,HASH,20);
|
||||
assert_true(rc == SSH_OK);
|
||||
type = ssh_key_type(key);
|
||||
assert_true(type == SSH_KEYTYPE_ECDSA);
|
||||
type_char = ssh_key_type_to_char(type);
|
||||
assert_true(strcmp(type_char, "ssh-ecdsa") == 0);
|
||||
etype_char =ssh_pki_key_ecdsa_name(key);
|
||||
assert_true(strcmp(etype_char, "ecdsa-sha2-nistp521") == 0);
|
||||
|
||||
ssh_signature_free(sign);
|
||||
ssh_key_free(key);
|
||||
key=NULL;
|
||||
@@ -1070,6 +1146,42 @@ static void torture_pki_write_privkey_ecdsa(void **state)
|
||||
#endif
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
static void torture_pki_ecdsa_name(void **state, const char *expected_name)
|
||||
{
|
||||
int rc;
|
||||
ssh_key key;
|
||||
const char *etype_char = NULL;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
ssh_set_log_level(5);
|
||||
|
||||
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &key);
|
||||
assert_true(rc == 0);
|
||||
|
||||
etype_char =ssh_pki_key_ecdsa_name(key);
|
||||
assert_true(strcmp(etype_char, expected_name) == 0);
|
||||
|
||||
ssh_key_free(key);
|
||||
}
|
||||
|
||||
static void torture_pki_ecdsa_name256(void **state)
|
||||
{
|
||||
torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp256");
|
||||
}
|
||||
|
||||
static void torture_pki_ecdsa_name384(void **state)
|
||||
{
|
||||
torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp384");
|
||||
}
|
||||
|
||||
static void torture_pki_ecdsa_name521(void **state)
|
||||
{
|
||||
torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp521");
|
||||
}
|
||||
#endif
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
const UnitTest tests[] = {
|
||||
@@ -1092,7 +1204,13 @@ int torture_run_tests(void) {
|
||||
teardown),
|
||||
#ifdef HAVE_ECC
|
||||
unit_test_setup_teardown(torture_pki_import_privkey_base64_ECDSA,
|
||||
setup_ecdsa_key,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_import_privkey_base64_ECDSA,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_import_privkey_base64_ECDSA,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
#endif
|
||||
unit_test_setup_teardown(torture_pki_import_privkey_base64_passphrase,
|
||||
@@ -1107,7 +1225,22 @@ int torture_run_tests(void) {
|
||||
teardown),
|
||||
#ifdef HAVE_ECC
|
||||
unit_test_setup_teardown(torture_pki_publickey_from_privatekey_ECDSA,
|
||||
setup_ecdsa_key,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_publickey_from_privatekey_ECDSA,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_publickey_from_privatekey_ECDSA,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
#endif
|
||||
/* public key */
|
||||
@@ -1119,7 +1252,13 @@ int torture_run_tests(void) {
|
||||
teardown),
|
||||
#ifdef HAVE_ECC
|
||||
unit_test_setup_teardown(torture_pki_publickey_ecdsa_base64,
|
||||
setup_ecdsa_key,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_publickey_ecdsa_base64,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_publickey_ecdsa_base64,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
#endif
|
||||
|
||||
@@ -1131,7 +1270,13 @@ int torture_run_tests(void) {
|
||||
teardown),
|
||||
#ifdef HAVE_ECC
|
||||
unit_test_setup_teardown(torture_generate_pubkey_from_privkey_ecdsa,
|
||||
setup_ecdsa_key,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_generate_pubkey_from_privkey_ecdsa,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_generate_pubkey_from_privkey_ecdsa,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
#endif
|
||||
|
||||
@@ -1143,7 +1288,13 @@ int torture_run_tests(void) {
|
||||
teardown),
|
||||
#ifdef HAVE_ECC
|
||||
unit_test_setup_teardown(torture_pki_duplicate_key_ecdsa,
|
||||
setup_ecdsa_key,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_duplicate_key_ecdsa,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_duplicate_key_ecdsa,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
#endif
|
||||
unit_test(torture_pki_generate_key_rsa),
|
||||
@@ -1161,10 +1312,27 @@ int torture_run_tests(void) {
|
||||
teardown),
|
||||
#ifdef HAVE_ECC
|
||||
unit_test_setup_teardown(torture_pki_write_privkey_ecdsa,
|
||||
setup_ecdsa_key,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_write_privkey_ecdsa,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_write_privkey_ecdsa,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
#endif
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
#ifdef HAVE_ECC
|
||||
unit_test_setup_teardown(torture_pki_ecdsa_name256,
|
||||
setup_ecdsa_key_256,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_ecdsa_name384,
|
||||
setup_ecdsa_key_384,
|
||||
teardown),
|
||||
unit_test_setup_teardown(torture_pki_ecdsa_name521,
|
||||
setup_ecdsa_key_521,
|
||||
teardown),
|
||||
#endif
|
||||
};
|
||||
|
||||
(void)setup_both_keys;
|
||||
|
||||
Reference in New Issue
Block a user