diff --git a/CHANGELOG b/CHANGELOG index 74782f510..190bdfadc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,6 @@ #Nmap Changelog ($Id$); -*-text-*- -o Upgraded included libraries: Lua 5.4.7 +o Upgraded included libraries: Lua 5.4.7, libssh2 1.11.1 o [NSE] New script targets-ipv6-eui64 generates target IPv6 addresses from a user-provided file of MAC addresses, using the EUI-64 method. [Daniel Miller] diff --git a/libssh2/CMakeLists.txt b/libssh2/CMakeLists.txt index 8d51f4654..6b51ac642 100644 --- a/libssh2/CMakeLists.txt +++ b/libssh2/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright (c) 2014, 2015 Alexander Lamaison -# Copyright (c) 2023 Viktor Szakats +# Copyright (C) Alexander Lamaison +# Copyright (C) Viktor Szakats # # Redistribution and use in source and binary forms, # with or without modification, are permitted provided @@ -33,80 +33,85 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. +# +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.7) +message(STATUS "Using CMake version ${CMAKE_VERSION}") + +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) include(CheckFunctionExists) include(CheckSymbolExists) include(CheckIncludeFiles) -include(CheckSymbolExists) include(CMakePushCheckState) include(FeatureSummary) -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}") include(CheckFunctionExistsMayNeedLibrary) include(CheckNonblockingSocketSupport) -cmake_minimum_required(VERSION 3.1) - -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) - project(libssh2 C) -set(CMAKE_UNITY_BUILD_BATCH_SIZE 32) +function(libssh2_dumpvars) # Dump all defined variables with their values + message("::group::CMake Variable Dump") + get_cmake_property(_vars VARIABLES) + foreach(_var ${_vars}) + message("${_var} = ${${_var}}") + endforeach() + message("::endgroup::") +endfunction() -option(BUILD_STATIC_LIBS "Build Static Libraries" ON) -add_feature_info("Static library" BUILD_STATIC_LIBS - "creating libssh2 static library") +if(NOT DEFINED CMAKE_UNITY_BUILD_BATCH_SIZE) + set(CMAKE_UNITY_BUILD_BATCH_SIZE 0) +endif() -option(BUILD_SHARED_LIBS "Build Shared Libraries" ON) -add_feature_info("Shared library" BUILD_SHARED_LIBS - "creating libssh2 shared library (.so/.dll)") +option(BUILD_STATIC_LIBS "Build static libraries" ON) +add_feature_info("Static library" BUILD_STATIC_LIBS "creating libssh2 static library") + +option(BUILD_SHARED_LIBS "Build shared libraries" ON) +add_feature_info("Shared library" BUILD_SHARED_LIBS "creating libssh2 shared library (.so/.dll)") # Parse version -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/include/libssh2.h _HEADER_CONTENTS) -string( - REGEX REPLACE ".*#define LIBSSH2_VERSION[ \t]+\"([^\"]+)\".*" "\\1" - LIBSSH2_VERSION "${_HEADER_CONTENTS}") -string( - REGEX REPLACE ".*#define LIBSSH2_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" - LIBSSH2_VERSION_MAJOR "${_HEADER_CONTENTS}") -string( - REGEX REPLACE ".*#define LIBSSH2_VERSION_MINOR[ \t]+([0-9]+).*" "\\1" - LIBSSH2_VERSION_MINOR "${_HEADER_CONTENTS}") -string( - REGEX REPLACE ".*#define LIBSSH2_VERSION_PATCH[ \t]+([0-9]+).*" "\\1" - LIBSSH2_VERSION_PATCH "${_HEADER_CONTENTS}") +file(READ "${PROJECT_SOURCE_DIR}/include/libssh2.h" _header_contents) +string(REGEX REPLACE ".*#define LIBSSH2_VERSION[ \t]+\"([^\"]+)\".*" "\\1" LIBSSH2_VERSION "${_header_contents}") +string(REGEX REPLACE ".*#define LIBSSH2_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" LIBSSH2_VERSION_MAJOR "${_header_contents}") +string(REGEX REPLACE ".*#define LIBSSH2_VERSION_MINOR[ \t]+([0-9]+).*" "\\1" LIBSSH2_VERSION_MINOR "${_header_contents}") +string(REGEX REPLACE ".*#define LIBSSH2_VERSION_PATCH[ \t]+([0-9]+).*" "\\1" LIBSSH2_VERSION_PATCH "${_header_contents}") +unset(_header_contents) if(NOT LIBSSH2_VERSION OR NOT LIBSSH2_VERSION_MAJOR MATCHES "^[0-9]+$" OR NOT LIBSSH2_VERSION_MINOR MATCHES "^[0-9]+$" OR NOT LIBSSH2_VERSION_PATCH MATCHES "^[0-9]+$") - message( - FATAL_ERROR - "Unable to parse version from" - "${CMAKE_CURRENT_SOURCE_DIR}/include/libssh2.h") + message(FATAL_ERROR "Unable to parse version from ${PROJECT_SOURCE_DIR}/include/libssh2.h") endif() include(GNUInstallDirs) install( FILES - COPYING README RELEASE-NOTES + COPYING NEWS README RELEASE-NOTES docs/AUTHORS docs/BINDINGS.md docs/HACKING.md DESTINATION ${CMAKE_INSTALL_DOCDIR}) -include(max_warnings) +include(PickyWarnings) + +set(LIBSSH2_LIBS_SOCKET "") +set(LIBSSH2_LIBS "") +set(LIBSSH2_LIBDIRS "") +set(LIBSSH2_PC_REQUIRES_PRIVATE "") # Add socket libraries if(WIN32) - list(APPEND SOCKET_LIBRARIES ws2_32) + list(APPEND LIBSSH2_LIBS_SOCKET "ws2_32") else() - check_function_exists_may_need_library(socket HAVE_SOCKET socket) + check_function_exists_may_need_library("socket" HAVE_SOCKET "socket") if(NEED_LIB_SOCKET) - list(APPEND SOCKET_LIBRARIES socket) + list(APPEND LIBSSH2_LIBS_SOCKET "socket") endif() - check_function_exists_may_need_library(inet_addr HAVE_INET_ADDR nsl) + check_function_exists_may_need_library("inet_addr" HAVE_INET_ADDR "nsl") if(NEED_LIB_NSL) - list(APPEND SOCKET_LIBRARIES nsl) + list(APPEND LIBSSH2_LIBS_SOCKET "nsl") endif() endif() @@ -117,8 +122,9 @@ if(NOT BUILD_STATIC_LIBS AND NOT BUILD_SHARED_LIBS) set(BUILD_STATIC_LIBS ON) endif() -set(LIB_STATIC "libssh2_static") -set(LIB_SHARED "libssh2_shared") +set(LIB_NAME "libssh2") +set(LIB_STATIC "${LIB_NAME}_static") +set(LIB_SHARED "${LIB_NAME}_shared") # lib flavour selected for example and test programs. if(BUILD_SHARED_LIBS) @@ -129,18 +135,18 @@ endif() # Symbol hiding -option(HIDE_SYMBOLS "Set to ON to hide all libssh2 symbols that are not officially external" ON) +option(HIDE_SYMBOLS "Hide all libssh2 symbols that are not officially external" ON) mark_as_advanced(HIDE_SYMBOLS) if(HIDE_SYMBOLS) - set(LIB_SHARED_DEFINITIONS LIBSSH2_EXPORTS) + set(LIB_SHARED_DEFINITIONS "LIBSSH2_EXPORTS") if(WIN32) elseif((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0) OR (CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.1)) - set(LIB_SHARED_C_FLAGS -fvisibility=hidden) + set(LIB_SHARED_C_FLAGS "-fvisibility=hidden") set(LIBSSH2_API "__attribute__ ((__visibility__ (\"default\")))") elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0) - set(LIB_SHARED_C_FLAGS -xldscope=hidden) + set(LIB_SHARED_C_FLAGS "-xldscope=hidden") set(LIBSSH2_API "__global") endif() endif() @@ -153,13 +159,17 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") else() set(DEBUG_LOGGING_DEFAULT OFF) endif() -option(ENABLE_DEBUG_LOGGING "log execution with debug trace" - ${DEBUG_LOGGING_DEFAULT}) -add_feature_info(Logging ENABLE_DEBUG_LOGGING - "Logging of execution with debug trace") +option(ENABLE_DEBUG_LOGGING "Log execution with debug trace" ${DEBUG_LOGGING_DEFAULT}) +add_feature_info(Logging ENABLE_DEBUG_LOGGING "Logging of execution with debug trace") if(ENABLE_DEBUG_LOGGING) # Must be visible to the library and tests using internals - add_definitions(-DLIBSSH2DEBUG) + add_definitions("-DLIBSSH2DEBUG") +endif() + +option(LIBSSH2_NO_DEPRECATED "Build without deprecated APIs" OFF) +add_feature_info("Without deprecated APIs" LIBSSH2_NO_DEPRECATED "") +if(LIBSSH2_NO_DEPRECATED) + add_definitions("-DLIBSSH2_NO_DEPRECATED") endif() # Auto-detection @@ -172,7 +182,6 @@ if(WIN32) set(HAVE_UNISTD_H 1) set(HAVE_INTTYPES_H 1) set(HAVE_SYS_TIME_H 1) - set(HAVE_SYS_PARAM_H 1) set(HAVE_GETTIMEOFDAY 1) set(HAVE_STRTOLL 1) elseif(MSVC) @@ -182,29 +191,31 @@ if(WIN32) set(HAVE_STRTOLL 1) else() set(HAVE_INTTYPES_H 0) + set(HAVE_STRTOLL 0) set(HAVE_STRTOI64 1) endif() if(NOT MSVC_VERSION LESS 1900) set(HAVE_SNPRINTF 1) + else() + set(HAVE_SNPRINTF 0) endif() endif() endif() ## Platform checks -check_include_files(inttypes.h HAVE_INTTYPES_H) +check_include_files("inttypes.h" HAVE_INTTYPES_H) if(NOT MSVC) - check_include_files(unistd.h HAVE_UNISTD_H) - check_include_files(sys/time.h HAVE_SYS_TIME_H) - check_include_files(sys/param.h HAVE_SYS_PARAM_H) # tests + check_include_files("unistd.h" HAVE_UNISTD_H) + check_include_files("sys/time.h" HAVE_SYS_TIME_H) endif() if(NOT WIN32) - check_include_files(sys/select.h HAVE_SYS_SELECT_H) - check_include_files(sys/uio.h HAVE_SYS_UIO_H) - check_include_files(sys/socket.h HAVE_SYS_SOCKET_H) - check_include_files(sys/ioctl.h HAVE_SYS_IOCTL_H) - check_include_files(sys/un.h HAVE_SYS_UN_H) - check_include_files(arpa/inet.h HAVE_ARPA_INET_H) # example and tests - check_include_files(netinet/in.h HAVE_NETINET_IN_H) # example and tests + check_include_files("sys/select.h" HAVE_SYS_SELECT_H) + check_include_files("sys/uio.h" HAVE_SYS_UIO_H) + check_include_files("sys/socket.h" HAVE_SYS_SOCKET_H) + check_include_files("sys/ioctl.h" HAVE_SYS_IOCTL_H) + check_include_files("sys/un.h" HAVE_SYS_UN_H) + check_include_files("arpa/inet.h" HAVE_ARPA_INET_H) # example and tests + check_include_files("netinet/in.h" HAVE_NETINET_IN_H) # example and tests endif() # CMake uses C syntax in check_symbol_exists() that generates a warning with @@ -216,28 +227,28 @@ if(MSVC AND ENABLE_WERROR) endif() if(HAVE_SYS_TIME_H) - check_symbol_exists(gettimeofday sys/time.h HAVE_GETTIMEOFDAY) + check_symbol_exists("gettimeofday" "sys/time.h" HAVE_GETTIMEOFDAY) else() - check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) + check_function_exists("gettimeofday" HAVE_GETTIMEOFDAY) endif() -check_symbol_exists(strtoll stdlib.h HAVE_STRTOLL) +check_symbol_exists("strtoll" "stdlib.h" HAVE_STRTOLL) if(NOT HAVE_STRTOLL) # Try _strtoi64() if strtoll() is not available - check_symbol_exists(_strtoi64 stdlib.h HAVE_STRTOI64) + check_symbol_exists("_strtoi64" "stdlib.h" HAVE_STRTOI64) endif() -check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF) +check_symbol_exists("snprintf" "stdio.h" HAVE_SNPRINTF) if(NOT WIN32) - check_symbol_exists(explicit_bzero string.h HAVE_EXPLICIT_BZERO) - check_symbol_exists(explicit_memset string.h HAVE_EXPLICIT_MEMSET) - check_symbol_exists(memset_s string.h HAVE_MEMSET_S) + check_symbol_exists("explicit_bzero" "string.h" HAVE_EXPLICIT_BZERO) + check_symbol_exists("explicit_memset" "string.h" HAVE_EXPLICIT_MEMSET) + check_symbol_exists("memset_s" "string.h" HAVE_MEMSET_S) endif() if(MSVC AND ENABLE_WERROR) cmake_pop_check_state() endif() -if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR - ${CMAKE_SYSTEM_NAME} STREQUAL "Interix") +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR + CMAKE_SYSTEM_NAME STREQUAL "Interix") # poll() does not work on these platforms # # Interix: "does provide poll(), but the implementing developer must @@ -249,14 +260,14 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR # not being able to poll on some files (like anything in /dev) # not having reliable timeout support # inconsistent return of POLLHUP where other implementations give POLLIN - message("poll use is disabled on this platform") + message(STATUS "poll use is disabled on this platform") elseif(NOT WIN32) - check_function_exists(poll HAVE_POLL) + check_function_exists("poll" HAVE_POLL) endif() if(WIN32) set(HAVE_SELECT 1) else() - check_function_exists(select HAVE_SELECT) + check_function_exists("select" HAVE_SELECT) endif() # Non-blocking socket support tests. Use a separate, yet unset variable @@ -264,145 +275,134 @@ endif() # dependencies which might not have been built yet. if(NOT WIN32) cmake_push_check_state() - set(CMAKE_REQUIRED_LIBRARIES ${SOCKET_LIBRARIES}) + set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBS_SOCKET}) check_nonblocking_socket_support() cmake_pop_check_state() endif() # Config file -add_definitions(-DHAVE_CONFIG_H) +add_definitions("-DHAVE_CONFIG_H") -configure_file(src/libssh2_config_cmake.h.in - ${CMAKE_CURRENT_BINARY_DIR}/src/libssh2_config.h) +configure_file("src/libssh2_config_cmake.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/src/libssh2_config.h") ## Cryptography backend choice -set(CRYPTO_BACKEND - "" - CACHE - STRING - "The backend to use for cryptography: OpenSSL, wolfSSL, Libgcrypt, -WinCNG, mbedTLS, or empty to try any available") +set(CRYPTO_BACKEND "" CACHE + STRING "The backend to use for cryptography: OpenSSL, wolfSSL, Libgcrypt, WinCNG, mbedTLS, or empty to try any available") # If the crypto backend was given, rather than searching for the first # we are able to find, the find_package commands must abort configuration # and report to the user. if(CRYPTO_BACKEND) - set(SPECIFIC_CRYPTO_REQUIREMENT REQUIRED) + set(_specific_crypto_requirement "REQUIRED") endif() if(CRYPTO_BACKEND STREQUAL "OpenSSL" OR NOT CRYPTO_BACKEND) - find_package(OpenSSL ${SPECIFIC_CRYPTO_REQUIREMENT}) + find_package(OpenSSL ${_specific_crypto_requirement}) if(OPENSSL_FOUND) set(CRYPTO_BACKEND "OpenSSL") set(CRYPTO_BACKEND_DEFINE "LIBSSH2_OPENSSL") set(CRYPTO_BACKEND_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR}) - list(APPEND LIBRARIES ${OPENSSL_LIBRARIES}) - list(APPEND PC_REQUIRES_PRIVATE libssl libcrypto) + list(APPEND LIBSSH2_LIBS OpenSSL::Crypto) + list(APPEND LIBSSH2_PC_REQUIRES_PRIVATE "libcrypto") if(WIN32) # Statically linking to OpenSSL requires crypt32 for some Windows APIs. # This should really be handled by FindOpenSSL.cmake. - list(APPEND LIBRARIES crypt32 bcrypt) - list(APPEND PC_LIBS -lcrypt32 -lbcrypt) + list(APPEND LIBSSH2_LIBS "crypt32" "bcrypt") - #set(CMAKE_FIND_DEBUG_MODE TRUE) + #set(CMAKE_FIND_DEBUG_MODE ON) find_file(DLL_LIBCRYPTO - NAMES crypto.dll - libcrypto-1_1.dll libcrypto-1_1-x64.dll - libcrypto-3.dll libcrypto-3-x64.dll + NAMES "crypto.dll" + "libcrypto-1_1.dll" "libcrypto-1_1-x64.dll" + "libcrypto-3.dll" "libcrypto-3-x64.dll" HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS} - PATH_SUFFIXES bin NO_DEFAULT_PATH) + PATH_SUFFIXES "bin" NO_DEFAULT_PATH) if(DLL_LIBCRYPTO) + list(APPEND _RUNTIME_DEPENDENCIES ${DLL_LIBCRYPTO}) message(STATUS "Found libcrypto DLL: ${DLL_LIBCRYPTO}") else() - message(WARNING - "Unable to find OpenSSL libcrypto DLL, executables may not run") + message(WARNING "Unable to find OpenSSL libcrypto DLL, executables may not run") endif() - find_file(DLL_LIBSSL - NAMES ssl.dll - libssl-1_1.dll libssl-1_1-x64.dll - libssl-3.dll libssl-3-x64.dll - HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS} - PATH_SUFFIXES bin NO_DEFAULT_PATH) - if(DLL_LIBSSL) - message(STATUS "Found libssl DLL: ${DLL_LIBSSL}") - else() - message(WARNING - "Unable to find OpenSSL libssl DLL, executables may not run") - endif() - - #set(CMAKE_FIND_DEBUG_MODE FALSE) - - if(DLL_LIBCRYPTO AND DLL_LIBSSL) - list(APPEND _RUNTIME_DEPENDENCIES ${DLL_LIBCRYPTO} ${DLL_LIBSSL}) - endif() + #set(CMAKE_FIND_DEBUG_MODE OFF) endif() find_package(ZLIB) if(ZLIB_FOUND) - list(APPEND LIBRARIES ${ZLIB_LIBRARIES}) - list(APPEND PC_REQUIRES_PRIVATE zlib) + list(APPEND LIBSSH2_LIBS ${ZLIB_LIBRARIES}) endif() endif() endif() if(CRYPTO_BACKEND STREQUAL "wolfSSL" OR NOT CRYPTO_BACKEND) - find_package(wolfssl ${SPECIFIC_CRYPTO_REQUIREMENT}) + find_package(WolfSSL ${_specific_crypto_requirement}) if(WOLFSSL_FOUND) set(CRYPTO_BACKEND "wolfSSL") set(CRYPTO_BACKEND_DEFINE "LIBSSH2_WOLFSSL") - set(CRYPTO_BACKEND_INCLUDE_DIR ${WOLFSSL_INCLUDE_DIR} ${WOLFSSL_INCLUDE_DIR}/wolfssl) - list(APPEND LIBRARIES ${WOLFSSL_LIBRARIES}) - list(APPEND PC_LIBS -lwolfssl) + set(CRYPTO_BACKEND_INCLUDE_DIR ${WOLFSSL_INCLUDE_DIRS}) + list(APPEND LIBSSH2_LIBS ${WOLFSSL_LIBRARIES}) + list(APPEND LIBSSH2_LIBDIRS ${WOLFSSL_LIBRARY_DIRS}) + list(APPEND LIBSSH2_PC_REQUIRES_PRIVATE "wolfssl") + link_directories(${WOLFSSL_LIBRARY_DIRS}) + if(WOLFSSL_CFLAGS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WOLFSSL_CFLAGS}") + endif() if(WIN32) - list(APPEND LIBRARIES crypt32) - list(APPEND PC_LIBS -lcrypt32) + list(APPEND LIBSSH2_LIBS "crypt32") endif() find_package(ZLIB) if(ZLIB_FOUND) list(APPEND CRYPTO_BACKEND_INCLUDE_DIR ${ZLIB_INCLUDE_DIR}) # Public wolfSSL headers require zlib headers - list(APPEND LIBRARIES ${ZLIB_LIBRARIES}) - list(APPEND PC_REQUIRES_PRIVATE zlib) + list(APPEND LIBSSH2_LIBS ${ZLIB_LIBRARIES}) endif() endif() endif() if(CRYPTO_BACKEND STREQUAL "Libgcrypt" OR NOT CRYPTO_BACKEND) - find_package(Libgcrypt ${SPECIFIC_CRYPTO_REQUIREMENT}) + find_package(Libgcrypt ${_specific_crypto_requirement}) if(LIBGCRYPT_FOUND) set(CRYPTO_BACKEND "Libgcrypt") set(CRYPTO_BACKEND_DEFINE "LIBSSH2_LIBGCRYPT") set(CRYPTO_BACKEND_INCLUDE_DIR ${LIBGCRYPT_INCLUDE_DIRS}) - list(APPEND LIBRARIES ${LIBGCRYPT_LIBRARIES}) - list(APPEND PC_LIBS -lgcrypt) + list(APPEND LIBSSH2_LIBS ${LIBGCRYPT_LIBRARIES}) + list(APPEND LIBSSH2_LIBDIRS ${LIBGCRYPT_LIBRARY_DIRS}) + list(APPEND LIBSSH2_PC_REQUIRES_PRIVATE "libgcrypt") + link_directories(${LIBGCRYPT_LIBRARY_DIRS}) + if(LIBGCRYPT_CFLAGS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBGCRYPT_CFLAGS}") + endif() endif() endif() if(CRYPTO_BACKEND STREQUAL "mbedTLS" OR NOT CRYPTO_BACKEND) - find_package(mbedTLS ${SPECIFIC_CRYPTO_REQUIREMENT}) + find_package(MbedTLS ${_specific_crypto_requirement}) if(MBEDTLS_FOUND) set(CRYPTO_BACKEND "mbedTLS") set(CRYPTO_BACKEND_DEFINE "LIBSSH2_MBEDTLS") - set(CRYPTO_BACKEND_INCLUDE_DIR ${MBEDTLS_INCLUDE_DIR}) - list(APPEND LIBRARIES ${MBEDTLS_LIBRARIES}) - list(APPEND PC_LIBS -lmbedcrypto) - link_directories(${MBEDTLS_LIBRARY_DIR}) + set(CRYPTO_BACKEND_INCLUDE_DIR ${MBEDTLS_INCLUDE_DIRS}) + list(APPEND LIBSSH2_LIBS ${MBEDTLS_LIBRARIES}) + list(APPEND LIBSSH2_LIBDIRS ${MBEDTLS_LIBRARY_DIRS}) + list(APPEND LIBSSH2_PC_REQUIRES_PRIVATE "mbedcrypto") + link_directories(${MBEDTLS_LIBRARY_DIRS}) + if(MBEDTLS_CFLAGS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MBEDTLS_CFLAGS}") + endif() endif() endif() @@ -413,10 +413,19 @@ if(CRYPTO_BACKEND STREQUAL "WinCNG" OR NOT CRYPTO_BACKEND) set(CRYPTO_BACKEND "WinCNG") set(CRYPTO_BACKEND_DEFINE "LIBSSH2_WINCNG") set(CRYPTO_BACKEND_INCLUDE_DIR "") + list(APPEND LIBSSH2_LIBS "crypt32" "bcrypt") - list(APPEND LIBRARIES crypt32 bcrypt) - list(APPEND PC_LIBS -lcrypt32 -lbcrypt) - elseif(${SPECIFIC_CRYPTO_REQUIREMENT} STREQUAL ${REQUIRED}) + option(ENABLE_ECDSA_WINCNG "Enable WinCNG ECDSA support (requires Windows 10 or later)" OFF) + add_feature_info(WinCNG ENABLE_ECDSA_WINCNG "WinCNG ECDSA support") + if(ENABLE_ECDSA_WINCNG) + add_definitions("-DLIBSSH2_ECDSA_WINCNG") + if(MSVC) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,10") + elseif(MINGW) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--subsystem,windows:10") + endif() + endif() + elseif(_specific_crypto_requirement STREQUAL "REQUIRED") message(FATAL_ERROR "WinCNG not available") endif() endif() @@ -424,14 +433,14 @@ endif() # Global functions # Convert GNU Make assignments into CMake ones. -function(transform_makefile_inc INPUT_FILE OUTPUT_FILE) - file(READ ${INPUT_FILE} MAKEFILE_INC_CMAKE) +function(transform_makefile_inc _input_file _output_file) + file(READ ${_input_file} _makefile_inc_cmake) - string(REGEX REPLACE "\\\\\n" "" MAKEFILE_INC_CMAKE ${MAKEFILE_INC_CMAKE}) - string(REGEX REPLACE "([A-Za-z_]+) *= *([^\n]*)" "set(\\1 \\2)" MAKEFILE_INC_CMAKE ${MAKEFILE_INC_CMAKE}) + string(REGEX REPLACE "\\\\\n" "" _makefile_inc_cmake ${_makefile_inc_cmake}) + string(REGEX REPLACE "([A-Za-z_]+) *= *([^\n]*)" "set(\\1 \\2)" _makefile_inc_cmake ${_makefile_inc_cmake}) - file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_CMAKE}) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${INPUT_FILE}") + file(WRITE ${_output_file} ${_makefile_inc_cmake}) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_input_file}") endfunction() # @@ -449,9 +458,7 @@ endif() option(LINT "Check style while building" OFF) if(LINT) - add_custom_target(lint ALL - ./ci/checksrc.sh - WORKING_DIRECTORY ${libssh2_SOURCE_DIR}) + add_custom_target(lint ALL "./ci/checksrc.sh" WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) if(BUILD_STATIC_LIBS) add_dependencies(${LIB_STATIC} lint) else() diff --git a/libssh2/COPYING b/libssh2/COPYING index af4d874cd..6eb514684 100644 --- a/libssh2/COPYING +++ b/libssh2/COPYING @@ -1,11 +1,11 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2005,2006 Mikhail Gusarov - * Copyright (c) 2006-2007 The Written Word, Inc. - * Copyright (c) 2007 Eli Fant - * Copyright (c) 2009-2023 Daniel Stenberg +/* Copyright (C) 2004-2007 Sara Golemon + * Copyright (C) 2005,2006 Mikhail Gusarov + * Copyright (C) 2006-2007 The Written Word, Inc. + * Copyright (C) 2007 Eli Fant + * Copyright (C) 2009-2023 Daniel Stenberg * Copyright (C) 2008, 2009 Simon Josefsson - * Copyright (c) 2000 Markus Friedl - * Copyright (c) 2015 Microsoft Corp. + * Copyright (C) 2000 Markus Friedl + * Copyright (C) 2015 Microsoft Corp. * All rights reserved. * * Redistribution and use in source and binary forms, diff --git a/libssh2/Makefile.am b/libssh2/Makefile.am index cc7e5eed1..b33ed5f93 100644 --- a/libssh2/Makefile.am +++ b/libssh2/Makefile.am @@ -1,12 +1,8 @@ +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause AUTOMAKE_OPTIONS = foreign nostdinc SUBDIRS = src -if ENABLE_TESTS -SUBDIRS += tests -endif -if BUILD_EXAMPLES -SUBDIRS += example -endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libssh2.pc @@ -22,13 +18,14 @@ VMSFILES = vms/libssh2_make_example.dcl vms/libssh2_make_help.dcl \ vms/libssh2_make_kit.dcl vms/libssh2_make_lib.dcl vms/man2help.c \ vms/readme.vms vms/libssh2_config.h -WIN32FILES = src/libssh2.rc NMakefile +WIN32FILES = src/libssh2.rc OS400FILES = os400/README400 os400/initscript.sh os400/make.sh \ os400/make-src.sh os400/make-rpg.sh os400/make-include.sh \ + os400/config400.default \ os400/os400sys.c os400/ccsid.c \ os400/libssh2_config.h os400/macros.h os400/libssh2_ccsid.h \ - os400/include/alloca.h os400/include/sys/socket.h os400/include/stdio.h \ + os400/include/alloca.h os400/include/sys/socket.h \ os400/include/assert.h \ os400/libssh2rpg/libssh2.rpgle.in \ os400/libssh2rpg/libssh2_ccsid.rpgle.in \ @@ -37,8 +34,7 @@ OS400FILES = os400/README400 os400/initscript.sh os400/make.sh \ EXTRA_DIST = $(WIN32FILES) get_ver.awk \ maketgz RELEASE-NOTES libssh2.pc.in $(VMSFILES) config.rpath \ - CMakeLists.txt cmake git2news.pl libssh2-style.el README.md $(OS400FILES) \ - buildconf Makefile.mk + CMakeLists.txt cmake git2news.pl libssh2-style.el README.md $(OS400FILES) ACLOCAL_AMFLAGS = -I m4 @@ -53,7 +49,7 @@ dist-hook: (distit=`find $(srcdir) -name "*.dist"`; \ for file in $$distit; do \ strip=`echo $$file | sed -e s/^$(srcdir)// -e s/\.dist//`; \ - cp $$file $(distdir)$$strip; \ + cp -p $$file $(distdir)$$strip; \ done) # Code Coverage @@ -62,8 +58,8 @@ init-coverage: make clean lcov --directory . --zerocounters -COVERAGE_CCOPTS ?= "-g --coverage" -COVERAGE_OUT ?= docs/coverage +COVERAGE_CCOPTS := "-g --coverage" +COVERAGE_OUT := docs/coverage build-coverage: make CFLAGS=$(COVERAGE_CCOPTS) check @@ -80,10 +76,4 @@ gen-coverage: coverage: init-coverage build-coverage gen-coverage checksrc: - perl ci/checksrc.pl -i4 -m79 \ - -ASNPRINTF \ - -ACOPYRIGHT \ - -AFOPENMODE \ - -ATYPEDEFSTRUCT \ - -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c \ - tests/*.[ch] + ci/checksrc.sh diff --git a/libssh2/Makefile.in b/libssh2/Makefile.in index 333eff84d..6860eac25 100644 --- a/libssh2/Makefile.in +++ b/libssh2/Makefile.in @@ -89,16 +89,14 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@ENABLE_TESTS_TRUE@am__append_1 = tests -@BUILD_EXAMPLES_TRUE@am__append_2 = example subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ @@ -192,9 +190,9 @@ am__define_uniq_tagged_files = \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` -DIST_SUBDIRS = src docs tests example +DIST_SUBDIRS = src am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libssh2.pc.in \ - COPYING README compile config.guess \ + COPYING ChangeLog NEWS README compile config.guess \ config.rpath config.sub depcomp install-sh ltmain.sh missing \ tap-driver.sh DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -298,8 +296,12 @@ LIBMBEDCRYPTO = @LIBMBEDCRYPTO@ LIBMBEDCRYPTO_PREFIX = @LIBMBEDCRYPTO_PREFIX@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ -LIBSREQUIRED = @LIBSREQUIRED@ -LIBSSH2VER = @LIBSSH2VER@ +LIBSSH2_CFLAG_EXTRAS = @LIBSSH2_CFLAG_EXTRAS@ +LIBSSH2_PC_LIBS = @LIBSSH2_PC_LIBS@ +LIBSSH2_PC_LIBS_PRIVATE = @LIBSSH2_PC_LIBS_PRIVATE@ +LIBSSH2_PC_REQUIRES = @LIBSSH2_PC_REQUIRES@ +LIBSSH2_PC_REQUIRES_PRIVATE = @LIBSSH2_PC_REQUIRES_PRIVATE@ +LIBSSH2_VERSION = @LIBSSH2_VERSION@ LIBSSL = @LIBSSL@ LIBSSL_PREFIX = @LIBSSL_PREFIX@ LIBTOOL = @LIBTOOL@ @@ -398,8 +400,11 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ + +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause AUTOMAKE_OPTIONS = foreign nostdinc -SUBDIRS = src docs $(am__append_1) $(am__append_2) +SUBDIRS = src pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libssh2.pc include_HEADERS = \ @@ -412,12 +417,13 @@ VMSFILES = vms/libssh2_make_example.dcl vms/libssh2_make_help.dcl \ vms/libssh2_make_kit.dcl vms/libssh2_make_lib.dcl vms/man2help.c \ vms/readme.vms vms/libssh2_config.h -WIN32FILES = src/libssh2.rc NMakefile +WIN32FILES = src/libssh2.rc OS400FILES = os400/README400 os400/initscript.sh os400/make.sh \ os400/make-src.sh os400/make-rpg.sh os400/make-include.sh \ + os400/config400.default \ os400/os400sys.c os400/ccsid.c \ os400/libssh2_config.h os400/macros.h os400/libssh2_ccsid.h \ - os400/include/alloca.h os400/include/sys/socket.h os400/include/stdio.h \ + os400/include/alloca.h os400/include/sys/socket.h \ os400/include/assert.h \ os400/libssh2rpg/libssh2.rpgle.in \ os400/libssh2rpg/libssh2_ccsid.rpgle.in \ @@ -426,10 +432,11 @@ OS400FILES = os400/README400 os400/initscript.sh os400/make.sh \ EXTRA_DIST = $(WIN32FILES) get_ver.awk \ maketgz RELEASE-NOTES libssh2.pc.in $(VMSFILES) config.rpath \ - CMakeLists.txt cmake git2news.pl libssh2-style.el README.md $(OS400FILES) \ - buildconf Makefile.mk + CMakeLists.txt cmake git2news.pl libssh2-style.el README.md $(OS400FILES) ACLOCAL_AMFLAGS = -I m4 +COVERAGE_CCOPTS := "-g --coverage" +COVERAGE_OUT := docs/coverage all: all-recursive .SUFFIXES: @@ -967,7 +974,7 @@ dist-hook: (distit=`find $(srcdir) -name "*.dist"`; \ for file in $$distit; do \ strip=`echo $$file | sed -e s/^$(srcdir)// -e s/\.dist//`; \ - cp $$file $(distdir)$$strip; \ + cp -p $$file $(distdir)$$strip; \ done) # Code Coverage @@ -976,9 +983,6 @@ init-coverage: make clean lcov --directory . --zerocounters -COVERAGE_CCOPTS ?= "-g --coverage" -COVERAGE_OUT ?= docs/coverage - build-coverage: make CFLAGS=$(COVERAGE_CCOPTS) check mkdir -p $(COVERAGE_OUT) @@ -994,13 +998,7 @@ gen-coverage: coverage: init-coverage build-coverage gen-coverage checksrc: - perl ci/checksrc.pl -i4 -m79 \ - -ASNPRINTF \ - -ACOPYRIGHT \ - -AFOPENMODE \ - -ATYPEDEFSTRUCT \ - -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c \ - tests/*.[ch] + ci/checksrc.sh # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/libssh2/Makefile.mk b/libssh2/Makefile.mk index b5c13d568..08c77b390 100644 --- a/libssh2/Makefile.mk +++ b/libssh2/Makefile.mk @@ -194,10 +194,6 @@ ifdef WIN32 LIBSSH2_LDFLAGS_DYN += -Wl,--output-def,$(libssh2_def_LIBRARY),--out-implib,$(libssh2_dyn_a_LIBRARY) endif -# Get noinst_PROGRAMS define -include example/Makefile.am -TARGETS_EXAMPLES := $(patsubst %.c,%$(BIN_EXT),$(strip $(wildcard example/*.c))) - all: lib dyn # For compatibility @@ -211,29 +207,6 @@ prebuild: $(OBJ_DIR) $(OBJ_DIR)/version.inc example: $(TARGETS_EXAMPLES) -# Get DOCKER_TESTS, STANDALONE_TESTS, SSHD_TESTS, TESTS_WITH_LIB_STATIC, -# librunner_la_SOURCES defines -include tests/Makefile.inc -TARGETS_RUNNER := $(TARGET)-runner.a -TARGETS_RUNNER_OBJS := $(addprefix $(OBJ_DIR)/,$(patsubst %.c,%.o,$(filter %.c,$(librunner_la_SOURCES)))) -TARGETS_TESTS := $(patsubst %.c,%$(BIN_EXT),$(addprefix tests/,$(addsuffix .c,$(DOCKER_TESTS) $(STANDALONE_TESTS) $(SSHD_TESTS)))) -ifdef DYN -TARGETS_TESTS := $(filter-out $(patsubst %.c,%$(BIN_EXT),$(addprefix tests/,$(addsuffix .c,$(TESTS_WITH_LIB_STATIC)))),$(TARGETS_TESTS)) -endif - -test: $(TARGETS_RUNNER) $(TARGETS_TESTS) - -$(TARGETS_RUNNER_OBJS): - $(CC) -W -Wall $(CFLAGS) $(CPPFLAGS) -c $(patsubst $(OBJ_DIR)/%.o,tests/%.c,$@) -o $@ - -$(TARGETS_RUNNER): $(TARGETS_RUNNER_OBJS) - @$(call DEL, $@) - $(AR) rcs $@ $^ - -test_%$(BIN_EXT): $(libssh2_DEPENDENCIES) $(TARGETS_RUNNER) - $(CC) -W -Wall $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LIBSSH2_LDFLAGS_BIN) \ - $(patsubst %$(BIN_EXT),%.c,$@) -o $@ $(TARGETS_RUNNER) $(LIBS) $(LIBS_BIN) - %$(BIN_EXT): %.c $(libssh2_DEPENDENCIES) $(CC) -W -Wall $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LIBSSH2_LDFLAGS_BIN) $< -o $@ $(LIBS) $(LIBS_BIN) diff --git a/libssh2/README b/libssh2/README index 89639ba7d..fca539dbb 100644 --- a/libssh2/README +++ b/libssh2/README @@ -4,7 +4,7 @@ libssh2 - SSH2 library libssh2 is a library implementing the SSH2 protocol, available under the revised BSD license. -Web site: https://www.libssh2.org/ +Web site: https://libssh2.org/ Mailing list: https://lists.haxx.se/listinfo/libssh2-devel diff --git a/libssh2/README.md b/libssh2/README.md index caa0b6708..9d167c070 100644 --- a/libssh2/README.md +++ b/libssh2/README.md @@ -3,11 +3,11 @@ libssh2 is a library implementing the SSH2 protocol, available under the revised BSD license. -[Web site](https://www.libssh2.org/) +[Web site](https://libssh2.org/) [Mailing list](https://lists.haxx.se/listinfo/libssh2-devel) -[BSD Licensed](https://www.libssh2.org/license.html) +[BSD Licensed](https://libssh2.org/license.html) [Web site source code](https://github.com/libssh2/www) diff --git a/libssh2/RELEASE-NOTES b/libssh2/RELEASE-NOTES index c1c73db96..d9af1689d 100644 --- a/libssh2/RELEASE-NOTES +++ b/libssh2/RELEASE-NOTES @@ -1,75 +1,325 @@ -libssh2 1.11 +libssh2 1.11.1 + +Deprecation notices: + +- Starting October 2024, the following algos go deprecated and will be + disabled in default builds (with an option to enable them): + + - DSA: `ssh-dss` hostkeys. + You can enable it now with `-DLIBSSH2_DSA_ENABLE`. + Disabled by default in OpenSSH 7.0 (2015-08-11). + Support to be removed by early 2025 from OpenSSH. + - MD5-based MACs and hashes: `hmac-md5`, `hmac-md5-96`, + `LIBSSH2_HOSTKEY_HASH_MD5` + You can disable it now with `-DLIBSSH2_NO_MD5`. + Disabled by default since OpenSSH 7.2 (2016-02-29). + - 3DES cipher: `3des-cbc` + You can disable it now with `-DLIBSSH2_NO_3DES`. + Disabled by default since OpenSSH 7.4 (2016-12-19). + - RIPEMD-160 MACs: `hmac-ripemd160`, `hmac-ripemd160@openssh.com` + You can disable it now with `-DLIBSSH2_NO_HMAC_RIPEMD`. + Removed in OpenSSH 7.6 (2017-10-03). + - Blowfish cipher: `blowfish-cbc` + You can disable it now with `-DLIBSSH2_NO_BLOWFISH`. + Removed in OpenSSH 7.6 (2017-10-03). + - RC4 ciphers: `arcfour`, `arcfour128` + You can disable it now with `-DLIBSSH2_NO_RC4`. + Removed in OpenSSH 7.6 (2017-10-03). + - CAST cipher: `cast128-cbc` + You can disable it now with `-DLIBSSH2_NO_CAST`. + Removed in OpenSSH 7.6 (2017-10-03). + +- Starting April 2025, above options will be deleted from the + libssh2 codebase. + + - Default builds will also disable support for old-style, MD5-based + encrypted private keys. + You can disable it now with `-DLIBSSH2_NO_MD5_PEM`. This release includes the following enhancements and bugfixes: - o Adds support for encrypt-then-mac (ETM) MACs - o Adds support for AES-GCM crypto protocols - o Adds support for sk-ecdsa-sha2-nistp256 and sk-ssh-ed25519 keys - o Adds support for RSA certificate authentication - o Adds FIDO support with *_sk() functions - o Adds RSA-SHA2 key upgrading to OpenSSL, WinCNG, mbedTLS, OS400 backends - o Adds Agent Forwarding and libssh2_agent_sign() - o Adds support for Channel Signal message libssh2_channel_signal_ex() - o Adds support to get the user auth banner message libssh2_userauth_banner() - o Adds LIBSSH2_NO_{MD5, HMAC_RIPEMD, DSA, RSA, RSA_SHA1, ECDSA, ED25519, - AES_CBC, AES_CTR, BLOWFISH, RC4, CAST, 3DES} options - o Adds direct stream UNIX sockets with libssh2_channel_direct_streamlocal_ex() - o Adds wolfSSL support to CMake file - o Adds mbedTLS 3.x support - o Adds LibreSSL 3.5 support - o Adds support for CMake "unity" builds - o Adds CMake support for building shared and static libs in a single pass - o Adds symbol hiding support to CMake - o Adds support for libssh2.rc for all build tools - o Adds .zip, .tar.xz and .tar.bz2 release tarballs - o Enables ed25519 key support for LibreSSL 3.7.0 or higher - o Improves OpenSSL 1.1 and 3 compatibility - o Now requires OpenSSL 1.0.2 or newer - o Now requires CMake 3.1 or newer - o SFTP: Adds libssh2_sftp_open_ex_r() and libssh2_sftp_open_r() extended APIs - o SFTP: No longer has a packet limit when reading a directory - o SFTP: now parses attribute extensions if they exist - o SFTP: no longer will busy loop if SFTP fails to initialize - o SFTP: now clear various errors as expected - o SFTP: no longer skips files if the line buffer is too small - o SCP: add option to not quote paths - o SCP: Enables 64-bit offset support unconditionally - o Now skips leading \r and \n characters in banner_receive() - o Enables secure memory zeroing with all build tools on all platforms - o No longer logs SSH_MSG_REQUEST_FAILURE packets from keepalive - o Speed up base64 encoding by 7x - o Assert if there is an attempt to write a value that is too large - o WinCNG: fix memory leak in _libssh2_dh_secret() - o Added protection against possible null pointer dereferences - o Agent now handles overly large comment lengths - o Now ensure KEX replies don't include extra bytes - o Fixed possible buffer overflow when receiving SSH_MSG_USERAUTH_BANNER - o Fixed possible buffer overflow in keyboard interactive code path - o Fixed overlapping memcpy() - o Fixed Windows UWP builds - o Fixed DLL import name - o Renamed local RANDOM_PADDING macro to avoid unexpected define on Windows - o Support for building with gcc versions older than 8 - o Improvements to CMake, Makefile, NMakefile, GNUmakefile, autoreconf files - o Restores ANSI C89 compliance - o Enabled new compiler warnings and fixed/silenced them - o Improved error messages - o Now uses CIFuzz - o Numerous minor code improvements - o Improvements to CI builds - o Improvements to unit tests - o Improvements to doc files - o Improvements to example files - o Removed "old gex" build option - o Removed no-encryption/no-mac builds - o Removed support for NetWare and Watcom wmake build files +- autotools: fix to update `LDFLAGS` for each detected dependency (d19b6190 #1384 #1381 #1377) +- autotools: delete `--disable-tests` option, fix CI tests (e051ae34 #1271 #715 revert: 7483edfa) +- autotools: show the default for `hidden-symbols` option (a3f5594a #1269) +- autotools: enable `-Wunused-macros` with gcc (ecdf5199 #1262 #1227 #1224) +- autotools: fix dotless gcc and Apple clang version detections (89ccc83c #1232 #1187) +- autotools: show more clang/gcc version details (fb580161 #1230) +- autotools: avoid warnings in libtool stub code (96682bd5 #1227 #1224) +- autotools: sync warning enabler code with curl (5996fefe #1223) +- autotools: rename variable (ce5f208a #1222) +- autotools: picky warning options tidy-up (cdca8cff #1221) +- autotools: fix `cp` to preserve attributes and timestamp in `Makefile.am` (f64e6318) +- autotools: fix selecting WinCNG in cross-builds (and more) (00a3b88c #1187 #1186) +- autotools: use comma separator in `Requires.private` of `libssh2.pc` (7f83de14 #1124) +- autotools: remove `AB_INIT` from `configure.ac` (f4f52ccc) +- autotools: improve libz position (c89174a7 #1077 #941 #1075 #1013 regr: 4f0f4bff) +- autotools: skip tests requiring static lib if `--disable-static` (572c57c9 #1072 #663 #1056 regr: 83853f8a) +- build: stop detecting `sys/param.h` header (2677d3b0 #1418 #1415) +- build: silence warnings inside `FD_SET()`/`FD_ISSET()` macros (323a14b2 #1379) +- build: drop `-Wformat-nonliteral` warning suppressions (c452c5cc #1342) +- build: enable `-pedantic-errors` (3ec53f3e #1286) +- build: add mingw-w64 support to `LIBSSH2_PRINTF()` attribute (f8c45794 #1287) +- build: add `LIBSSH2_NO_DEPRECATED` option (b1414503 #1267 #1266 #1260 #1259) +- build: enable missing OpenSSF-recommended warnings, with fixes (afa6b865 #1257) +- build: enable more compiler warnings and fix them (7ecc309c #1224) +- build: picky warning updates (328a96b3 #1219) +- build: revert: respect autotools `DLL_EXPORT` in `libssh2.h` (481be044 #1141 #917 revert: fb1195cf) +- build: stop requiring libssl from openssl (c84745e3 #1128) +- build: tidy-up `libssh2.pc.in` variable names (5720dd9f #1125) +- build: add/fix `Requires.private` packages in `libssh2.pc` (ef538069 #1123) +- buildconf: drop (814a850c #1441 follow: fc5d7788) +- checksrc: update, check all sources, fix fallouts (1117b677 #1457) +- checksrc: sync with curl (8cd473c9 #1272) +- checksrc: fix spelling in comment (a95d401f) +- checksrc: modernise Perl file open (3d309f9b) +- checksrc: switch to dot file (d67a91aa #1052) +- ci: use Ninja with cmake (20ad047d #1458) +- ci: disable dependency tracking in autotools builds (e44f0418 #1396) +- ci: fix mbedtls runners on macOS (84411539 #1381) +- ci: enable Unity mode for most CMake builds (1bfae57b #1367 #1034) +- ci: add shellcheck job and script (d88b9bcd) +- ci: verify build and install from tarball (a86e27e8 #1362) +- ci: add reproducibility test for `maketgz` (2d765e45 #1360) +- ci: use Linux runner for BSDs, add arm64 FreeBSD 14 job (6f86b196 #1343) +- ci: do not parallelize `distcheck` job (5e65dd87 #1339) +- ci: add FreeBSD 14 job, fix issues (46333adf #1277) +- ci: add OmniOS job, fix issues (5e0ec991) +- ci: show compiler in cross/cygwin job names (c9124088) +- ci: add OpenBSD (v7.4) job + fix build error in example (0c9a8e35 #1250) +- ci: add NetBSD (v9.3) job (65c7a7a5) +- ci: update and speed up FreeBSD job (eee4e805) +- ci: use absolute path in `CMAKE_INSTALL_PREFIX` (74948816 #1247) +- ci: boost mbedTLS build speed (236e79a1 #1245) +- ci: add BoringSSL job (cmake, gcc, amd64) (c9dd3566 #1233) +- ci: fixup FreeBSD version, bump mbedTLS (fea6664e #1217) +- ci: add FreeBSD 13.2 job (a7d2a573 #1215) +- ci: mbedTLS 3.5.0 (5e190442 #1202) +- ci: update actions, use shallow clones with appveyor (d468a33f #1199) +- ci: replace `mv` + `chmod` with `install` in `Dockerfile` (5754fed6 #1175) +- ci: set file mode early in `appveyor_docker.yml` (633db55f) +- ci: add spellcheck (codespell) (a79218d3) +- ci: add MSYS builds (autotools and cmake) (d43b8d9b #1162) +- ci: add Cygwin builds (autotools and cmake) (f1e96e73 #1161) +- ci: add mingw-w64 UWP build (1215aa5f #1155 #1147) +- ci: add missing timeout to 'autotools distcheck' step (6265ffdb) +- ci: add non-static autotools i386 build, ignore GHA updates on AppVeyor (c6e137f7 #1074 #1072) +- ci: prefer `=` operator in shell snippets (e5c03043 #1073) +- ci: drop redundant/unused vars, sync var names (ab8e95bc #1059) +- ci: add i386 Linux build (with mbedTLS) (abdf40c7 #1057 #1053) +- ci/appveyor: reduce test runs (workaround for infrastructure permafails) (b5e68bdc #1461) +- ci/appveyor: increase wait for SSH server on GHA (bf3af90b) +- ci/appveyor: bump to OpenSSL 3.2.1 (53d9c1a6 #1363 #1348) +- ci/appveyor: re-enable parallel mode (e190e5b2 #1294 #884 #867) +- ci/appveyor: delete UWP job broken since Visual Studio upgrade (d0a7f1da #1275) +- ci/appveyor: YAML/PowerShell formatting, shorten variable name (06fd721f #1200) +- ci/appveyor: move to pure PowerShell (8a081fd9 #1197) +- ci/GHA: revert concurrency and improve permissions (e4c042f6) +- ci/GHA: FreeBSD 14.1, actions bump (ae04b1b9 #1424) +- ci/GHA: fix wolfSSL-from-source AES-GCM tests (1c0b07a7 #1409 #1408) +- ci/GHA: add Linux job with latest wolfSSL built from source (d4cea53f #1408 #1299 #1020) +- ci/GHA: tidy up build-from-source steps (2c633033) +- ci/GHA: show configure logs on failure and other tidy-ups (dab48398 #1403) +- ci/GHA: bump parallel jobs to nproc+1 (6f3d3bc8 #1402) +- ci/GHA: show test logs on failure (b8ffa7a5 #1401) +- ci/GHA: fix `Dockerfile` failing after Ubuntu package update (839bb84e #1400) +- ci/GHA: use ubuntu-latest with OmniOS job (50143d58) +- ci/GHA: shell syntax tidy-up (3b23e039 #1390) +- ci/GHA: bump NetBSD/OpenBSD, add NetBSD arm64 job (e980af72 #1388) +- ci/GHA: tidy up wolfSSL autotools config on macOS (5953c1f1 #1383) +- ci/GHA: shorter mbedTLS autotools workaround (736e3d7d #1382 #1381) +- ci/GHA: fix gcrypt with autotools/macOS/Homebrew/ARM64 (ae2770de #1377) +- ci/GHA: fix verbose option for autotools jobs (499b27ae #1376) +- ci/GHA: dump `config.log` on failure for macOS autotools jobs (4fa69214 #1375) +- ci/GHA: fix `autoreconf` failure on macOS/Homebrew (0b64b30b #1374) +- ci/GHA: fixup Homebrew location (for ARM runners) (6128aee0 #1373) +- ci/GHA: review/fixup auto-cancel settings (b08cfbc9 #1292) +- ci/GHA: restore curly braces in `if` (36748270 #1145) +- ci/GHA: simplify `if` strings (cab3db58 #1140) +- cmake: sync and improve Find modules, add `pkg-config` native detection (45064137 #1445 #1420) +- cmake: generate `LIBSSH2_PC_LIBS_PRIVATE` dynamically (c87f1296 #1466) +- cmake: add comment about `ibssh2.pc.in` variables (14b1b9d0) +- cmake: support absolute `CMAKE_INSTALL_INCLUDEDIR`/`CMAKE_INSTALL_LIBDIR` (d70cee36 #1465) +- cmake: rename two variables and initialize them (0fce9dcc #1464) +- cmake: prefer `find_dependency()` in `libssh2-config.cmake` (d9c2e550 #1460) +- cmake: tidy up syntax, minor improvements (9d9ee780 #1446) +- cmake: rename mbedTLS and wolfSSL Find modules (570de0f2) +- cmake: fixup version detection in mbedTLS Find module (8e3c40b2 #1444) +- cmake: mbedTLS detection tidy-ups (6d1d13c2 #1438) +- cmake: add quotes, delete ending dirseps (2bb46d44 #1437 #1166) +- cmake: sync formatting in `cmake/Find*` modules (a0310699) +- cmake: tidy up function name casing in `CopyRuntimeDependencies.cmake` (03547cb8) +- cmake: use the imported target of FindOpenSSL module (82b09f9b #1322) +- cmake: rename picky warnings script (64d6789f #1225) +- cmake: fix multiple include of libssh2 package (932d6a32 #1216) +- cmake: show crypto backend in feature summary (20387285 #1211) +- cmake: simplify showing CMake version (fc00bdd7 #1203) +- cmake: cleanup mbedTLS version detection more (4c241d5c #1196 #1192) +- cmake: delete duplicate `include()` (30eef0a6) +- cmake: improve/fix mbedTLS detection (41594675 #1192 #1191) +- cmake: tidy-up `foreach()` syntax (4a64ca14 #1180) +- cmake: verify `libssh2_VERSION` in integration tests (a20572e9) +- cmake: show cmake versions in ci (87f5769b) +- cmake: quote more strings (e9c7d3af #1173) +- cmake: add `ExternalProject` integration test (aeaefaf6 #1171) +- cmake: add integration tests (8715c3d5 #1170) +- cmake: (re-)add aliases for `add_subdirectory()` builds (4ff64ae3 #1169) +- cmake: style tidy-up (3fa5282d #1166) +- cmake: add `LIB_NAME` variable (5453fc80 #1159) +- cmake: tidy-up concatenation in `CMAKE_MODULE_PATH` (ae7d5108 #1157) +- cmake: replace `libssh2` literals with `PROJECT_NAME` variable (72fd2595 #1152) +- cmake: fix `STREQUAL` check in error branch (42d3bf13 #1151) +- cmake: cache more config values on Windows (11a03690 #1142) +- cmake: streamline invocation (f58f77b5 #1138) +- cmake: merge `set_target_properties()` calls (a9091007 #1132) +- cmake: (re-)add zlib to `Libs.private` in `libssh2.pc` (64643018 #1131) +- cmake: use `wolfssl/options.h` for detection, like autotools (c5ec6c49 #1130) +- cmake: add openssl libs to `Libs.private` in `libssh2.pc` (5cfa59d3 #1127) +- cmake: bump minimum CMake version to v3.7.0 (9cd18f45 #1126) +- cmake: CMAKE_SOURCE_DIR -> PROJECT_SOURCE_DIR (0f396aa9 #1121) +- cmake: tidy-ups (2fc36790 #1122) +- cmake: re-add `Libssh2:libssh2` for compatibility + lowercase namespace (2da13c13 #1104 #731 #1103) +- copyright: remove years from copyright headers (187d89bb #1082) +- disable DSA by default (b7ab0faa #1435 #1433) +- docs: update `INSTALL_AUTOTOOLS` (2f0efde3 #1316) +- docs: replace SHA1 with SHA256 in CMake example (766bde9f) +- example: restore `sys/time.h` for AIX (24503cb9 #1340 #1335 #1334 #1001 regr: e53aae0e) +- example: use `libssh2_socket_t` in X11 example (3f60ccb7) +- example: replace remaining libssh2_scp_recv with libssh2_scp_recv2 in output messages (8d69e63d #1258 follow: 6c84a426) +- example: fix regression in `ssh2_exec.c` (279a2e57 #1106 #861 #846 #1105 regr: b13936bd) +- example, tests: call `WSACleanup()` for each `WSAStartup()` (94b6bad3 #1283) +- example, tests: fix/silence `-Wformat-truncation=2` gcc warnings (744e059f) +- hostkey: do not advertise ssh-rsa when SHA1 is disabled (82d1b8ff #1093 #1092) +- kex: prevent possible double free of hostkey (b3465418 #1452) +- kex: always check for null pointers before calling _libssh2_bn_set_word (9f23a3bb #1423) +- kex: fix a memory leak in key exchange (19101843 #1412 #1404) +- kex: always add extension indicators to kex_algorithms (00e2a07e #1327 #1326) +- libssh2.h: add deprecated function warnings (9839ebe5 #1289 #1260) +- libssh2.h: add portable `LIBSSH2_SOCKET_CLOSE()` macro (28dbf016 #1278) +- libssh2.h: use `_WIN32` for Windows detection instead of rolling our own (631e7734 #1238) +- libssh2.pc: reference mbedcrypto pkgconfig (c149a127 #1405) +- libssh2.pc: re-add & extend support for static-only libssh2 builds (624abe27 #1119 #1114) +- libssh2.pc: don't put `@LIBS@` in pc file (1209c16d) +- mac: add empty hash functions for `mac_method_hmac_aesgcm` to not crash when e.g. setting `LIBSSH2_METHOD_CRYPT_CS` (b2738391 #1321) +- mac: handle low-level errors (f64885b6 #1297) +- Makefile.mk: delete Windows-focused raw GNU Make build (43485579 #1204) +- maketgz: reproducible tarballs/zip, display tarball hashes (d52fe1b4 #1357 #1359) +- maketgz: `set -eu`, reproducibility, improve zip, add CI test (cba7f975 #1353) +- man: improve `libssh2_userauth_publickey_from*` manpages (581b72aa #1347 #1308 #652) +- man: fix double spaces and dash escaping (a3ffc422 #1210) +- man: add description to `libssh2_session_get_blocking.3` (67e39091 #1185) +- mbedtls: always init ECDSA mbedtls_pk_context (a50d7deb #1430) +- mbedtls: correctly initialize values (ECDSA) (1701d5c0 #1428 #1421) +- mbedtls: expose `mbedtls_pk_load_file()` for our use (1628f6ca #1421 #1393 #1349 follow: e973493f) +- mbedtls: add workaround + FIXME to build with 3.6.0 (2e4c5ec4 #1349) +- mbedtls: improve disabling `-Wredundant-decls` (ecec68a2 #1226 #1224) +- mbedtls: include `version.h` for `MBEDTLS_VERSION_NUMBER` (9d7bc253 #1095 #1094) +- mbedtls: use more `size_t` to sync up with `crypto.h` (1153ebde #1054 #879 #846 #1053) +- md5: allow disabling old-style encrypted private keys at build-time (eb9f9de2 #1181) +- mingw: fix printf mask for 64-bit integers (36c1e1d1 #1091 #876 #846 #1090) +- misc: flatten `_libssh2_explicit_zero` if tree (74e74288 #1149) +- NMakefile: delete (c515eed3 #1134 #1129) +- openssl: free allocated resources when using openssl3 (b942bad1 #1459) +- openssl: fix memory leaks in `_libssh2_ecdsa_curve_name_with_octal_new` and `_libssh2_ecdsa_verify` (8d3bc19b #1449) +- openssl: fix calculating DSA public key with OpenSSL 3 (8b3c6e9d #1380) +- openssl: initialize BIGNUMs to NULL in `gen_publickey_from_dsa` for OpenSSL 3 (f1133c75 #1320) +- openssl: fix cppcheck found NULL dereferences (f2945905 #1304) +- openssl: delete internal `read_openssh_private_key_from_memory()` (34aff5ff #1306) +- openssl: use OpenSSL 3 HMAC API, add `no-deprecated` CI job (363dcbf4 #1243 #1235 #1207) +- openssl: make a function static, add `#ifdef` comments (efee9133 #1246 #248 follow: 03092292) +- openssl: fix DSA code to use OpenSSL 3 API (82581941 #1244 #1207) +- openssl: fix `EC_KEY` reference with OpenSSL 3 `no-deprecated` build (487152f4 #1236 #1235 #1207) +- openssl: use non-deprecated APIs with OpenSSL 3.x (b0ab005f #1207) +- openssl: silence `-Wunused-value` warnings (bf285500 #1205) +- openssl: use automatic initialization with LibreSSL 2.7.0+ (d79047c9 #1146 #302) +- openssl: add missing check for `LIBRESSL_VERSION_NUMBER` before use (4a42f42e #1117 #1115) +- os400: drop vsprintf() use (40e817ff #1462 #1457) +- os400: Add two recent files to the distribution (e4c65e5b #1364) +- os400: fix shellcheck warnings in scripts (fixups) (81341e1e #1366 #1364 #1358) +- os400: fix shellcheck warnings in scripts (c6625707 #1358) +- os400: maintain up to date (8457c37a #1309) +- packet: properly bounds check packet_authagent_open() (88a960a8 #1179) +- pem: fix private keys encrypted with AES-GCM methods (e87bdefa #1133) +- reuse: upgrade to `REUSE.toml` (70b8bf31 #1419) +- reuse: fix duplicate copyright warning (b9a4ed83) +- reuse: comply with 3.1 spec and 2.0.0 checker (fe6239a1 #1102 #1101 #1098) +- reuse: provide SPDX identifiers (f6aa31f4 #1084) +- scp: fix missing cast for targets without large file support (c317e06f #1060 #1057 #1002 regr: 5db836b2) +- session: support server banners up to 8192 bytes (was: 256) (1a9e8811 #1443 #1442) +- session: add `libssh2_session_callback_set2()` (c0f69548 #1285) +- session: handle EINTR from send/recv/poll/select to try again as the error is not fatal (798ed4a7 #1058 #955) +- sftp: increase SFTP_HANDLE_MAXLEN back to 4092 (75de6a37 #1422) +- sftp: implement posix-rename@openssh.com (fb652746 #1386) +- src: implement chacha20-poly1305@openssh.com (492bc543 #1426 #584) +- src: use `UINT32_MAX` (dc206408 #1413) +- src: fix type warning in `libssh2_sftp_unlink` macro (ac2e8c73 #1406) +- src: check the return value from `_libssh2_bn_*()` functions (95c824d5 #1354) +- src: support RSA-SHA2 cert-based authentication (rsa-sha2-512_cert and rsa-sha2-256_cert) (3a6ab70d #1314) +- src: check hash update/final success (4718ede4 #1303 #1301) +- src: check hash init success (2ed9eb92 #1301) +- src: add 'strict KEX' to fix CVE-2023-48795 "Terrapin Attack" (d34d9258 #1291 #1290) +- src: disable `-Wsign-conversion` warnings, add option to re-enable (6e451669 #1284 #1257) +- src: fix gcc 13 `-Wconversion` warning on Darwin (8cca7b77 #1209 follow: 08354e0a) +- src: drop a redundant `#include` (1f0174d0 #1153) +- src: improve MSVC C4701 warning fix (8b924999 #1086 #876 #1083) +- src: bump `hash_len` to `size_t` in `LIBSSH2_HOSTKEY_METHOD` (8b917d76 #1076) +- src: bump DSA and ECDSA sign `hash_len` to `size_t` (7b8e0225 #1055) +- tests: avoid using `MAXPATHLEN`, for portability (12427f4f #1415 #198 #1414) +- tests: fix excluding AES-GCM tests (fbd9d192 #1410) +- tests: drop default cygpath option `-u` (38e50aa0) +- tests: fix shellcheck issues in `test_sshd.test` (a2ac8c55) +- tests: sync port number type with the rest of codebase (eb996af8) +- tests: fall back to `$LOGNAME` for username (5326a5ce #1241 #1240) +- tests: show cmake version used in integration tests (2cd2f40e #1201) +- tests: formatting and tidy-ups (e61987a3) +- tests: replace FIXME with comments (1a99a86a) +- tests: add aes256-gcm encrypted key test (802336cf #1135 #1133) +- tests: trap signals in scripts (b2916b28 #1098) +- tests: cast to avoid `-Wchar-subscripts` with Cygwin (43df6a46 #1081 #1080) +- test_read: make it run without Docker (57e9d18e #1139) +- test_sshd.test: show sshd and test connect logs on harness failure (299c2040 #1097) +- test_sshd.test: set a safe PID directory (e8cabdcf #1089) +- test_sshd.test: minor cleanups (d29eea1d) +- tidy-up: link updates (c905bfd2 #1434) +- tidy-up: typo in comment (792e1b6f) +- tidy-up: fix typo found by codespell (706ec36d) +- tidy-up: bump casts from int to long for large C99 types in printfs (2e5a8719 #1264 #1257) +- tidy-up: `unsigned` -> `unsigned int` (b136c379) +- tidy-up: stop using leading underscores in macro names (c6589b88 #1248) +- tidy-up: around `stdint.h` (bfa00f1b #1212) +- tidy-up: fix typo in `readme.vms` (a9a79e7a) +- tidy-up: use built-in `_WIN32` macro to detect Windows (6fbc9505 #1195) +- tidy-up: drop `www.` from `www.libssh2.org` (6e3e8839 #1172) +- tidy-up: delete duplicate word from comment (76307435) +- tidy-up: avoid exclamations, prefer single quotes, in outputs (003fb454 #1079) +- TODO: disable or drop weak algos (0b4bdc85 #1261) +- transport: fix unstable connections over non-blocking sockets (de004875 #1454 #720 #1431 #1397) +- transport: check ETM on remote end when receiving (bde10825 #1332 #1331) +- transport: fix incorrect byte offset in debug message (2388a3aa #1096) +- userauth: avoid oob with huge interactive kbd response (f3a85cad #1337) +- userauth: add a new structure to separate memory read and file read (63b4c20e #773) +- userauth: check whether `*key_method` is a NULL pointer instead of `key_method` (bec57c40) +- wincng: fix `DH_GEX_MAXGROUP` set higher than supported (48584671 #1372 #493) +- wincng: add to ci/GHA, add `./configure` option `--enable-ecdsa-wincng` (3f98bfb0 #1368 #1315) +- wincng: add ECDSA support for host and user authentication (3e723437 #1315) +- wincng: prefer `ULONG`/`DWORD` over `unsigned long` (186c1d63 #1165) +- wincng: tidy-ups (7bb669b5 #1164) +- wolfssl: drop header path hack (8ae1b2d7 #1439) +- wolfssl: fix `EVP_Cipher()` use with v5.6.0 and older (a5b0fac2 #1407 #1394 #797 #1299 #1020) +- wolfssl: bump version in upstream issue comment (5cab802c) +- wolfssl: require v5.4.0 for AES-GCM (260a721c #1411 #1299 #1020) +- wolfssl: enable debug logging in wolfSSL when compiled in (76e7a68a #1310) This release would not have looked like this without help, code, reports and advice from friends like these: - Viktor Szakats, Dan Fandrich, Will Cosgrove, Daniel Stenberg, Michael Buckley, - Zenju, Miguel de Icaza, Nick Woodruff, Keith Dart, Anders Borum, - Jörgen Sigvardsson, vajdaakos, Gustavo Junior Alves, Marc Hörsken, iruis, - Nishit Majithia, Stefan Eissing, metab0t, Y. Yang, skundu07, Mike Harris, - Gabriel Smith, Leo Liu, Miguel de Icaza, Sandeep Bansal, Harry Sintonen, - xalopp, tihmstar, Sunil Nimmagadda + Viktor Szakats, Michael Buckley, Patrick Monnerat, Ren Mingshuai, + Will Cosgrove, Daniel Stenberg, Josef Cejka, Nicolas Mora, Ryan Kelley, + Aaron Stone, Adam, Anders Borum, András Fekete, Andrei Augustin, binary1248, + Brian Inglis, brucsc on GitHub, concussious on github, Dan Fandrich, + dksslq on github, Haowei Hsu, Harmen Stoppels, Harry Mallon, Jack L, + Jakob Egger, Jiwoo Park, João M. S. Silva, Joel Depooter, Johannes Passing, + Jose Quaresma, Juliusz Sosinowicz, Kai Pastor, Kenneth Davidson, + klux21 on github, Lyndon Brown, Marc Hoersken, mike-jumper, naddy, + Nursan Valeyev, Paul Howarth, PewPewPew, Radek Brich, rahmanih on github, + rolag on github, Seo Suchan, shubhamhii on github, Steve McIntyre, + Tejaswi Kandula, Tobias Stoeckmann, Trzik, Xi Ruoyao diff --git a/libssh2/acinclude.m4 b/libssh2/acinclude.m4 index 1d7121e71..e06476fd6 100644 --- a/libssh2/acinclude.m4 +++ b/libssh2/acinclude.m4 @@ -1,3 +1,5 @@ +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause dnl CURL_CPP_P dnl dnl Check if $cpp -P should be used for extract define values due to gcc 5 @@ -119,19 +121,6 @@ AC_DEFUN([CURL_CHECK_COMPILER_CLANG], [ AC_MSG_RESULT([no]) compiler_id="CLANG" fi - fullclangver=`$CC -v 2>&1 | grep version` - clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*)/\1/'` - if test -z "$clangver"; then - if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then - dnl Starting with Xcode 7 / clang 3.7, Apple clang won't tell its upstream version - clangver="3.7" - else - clangver=`echo $fullclangver | "$SED" 's/.*version \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'` - fi - fi - clangvhi=`echo $clangver | cut -d . -f1` - clangvlo=`echo $clangver | cut -d . -f2` - compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null` flags_dbg_yes="-g" flags_opt_all="-O -O0 -O1 -O2 -Os -O3 -O4" flags_opt_yes="-O2" @@ -149,24 +138,24 @@ dnl sets the $ICC variable to "yes" or "no" dnl ********************************************************************** AC_DEFUN([CURL_DETECT_ICC], [ - ICC="no" - AC_MSG_CHECKING([for icc in use]) - if test "$GCC" = "yes"; then - dnl check if this is icc acting as gcc in disguise - AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER], - dnl action if the text is found, this it has not been replaced by the - dnl cpp - ICC="no", - dnl the text was not found, it was replaced by the cpp - ICC="yes" - AC_MSG_RESULT([yes]) - [$1] - ) - fi - if test "$ICC" = "no"; then - # this is not ICC - AC_MSG_RESULT([no]) - fi + ICC="no" + AC_MSG_CHECKING([for icc in use]) + if test "$GCC" = "yes"; then + dnl check if this is icc acting as gcc in disguise + AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER], + dnl action if the text is found, this it has not been replaced by the + dnl cpp + ICC="no", + dnl the text was not found, it was replaced by the cpp + ICC="yes" + AC_MSG_RESULT([yes]) + [$1] + ) + fi + if test "$ICC" = "no"; then + # this is not ICC + AC_MSG_RESULT([no]) + fi ]) dnl We create a function for detecting which compiler we use and then set as @@ -175,306 +164,401 @@ dnl options are only used for debug-builds. AC_DEFUN([CURL_CC_DEBUG_OPTS], [ - if test "z$CLANG" = "z"; then - CURL_CHECK_COMPILER_CLANG - if test "z$compiler_id" = "zCLANG"; then - CLANG="yes" - else - CLANG="no" - fi - fi - if test "z$ICC" = "z"; then - CURL_DETECT_ICC + if test "z$CLANG" = "z"; then + CURL_CHECK_COMPILER_CLANG + if test "z$compiler_id" = "zCLANG"; then + CLANG="yes" + else + CLANG="no" fi + fi + if test "z$ICC" = "z"; then + CURL_DETECT_ICC + fi - if test "$CLANG" = "yes"; then + if test "$CLANG" = "yes"; then - dnl figure out clang version! - AC_MSG_CHECKING([clang version]) - fullclangver=`$CC -v 2>&1 | grep version` - clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*)/\1/'` - if test -z "$clangver"; then - if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then - dnl Starting with Xcode 7 / clang 3.7, Apple clang won't tell its upstream version - clangver="3.7" - else - clangver=`echo $fullclangver | "$SED" 's/.*version \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'` - fi - fi - clangvhi=`echo $clangver | cut -d . -f1` - clangvlo=`echo $clangver | cut -d . -f2` - compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null` - AC_MSG_RESULT($compiler_num) + # indentation to match curl's m4/curl-compilers.m4 - WARN="-pedantic" - CURL_ADD_COMPILER_WARNINGS([WARN], [all extra]) - CURL_ADD_COMPILER_WARNINGS([WARN], [pointer-arith write-strings]) - CURL_ADD_COMPILER_WARNINGS([WARN], [shadow]) - CURL_ADD_COMPILER_WARNINGS([WARN], [inline nested-externs]) - CURL_ADD_COMPILER_WARNINGS([WARN], [missing-declarations]) - CURL_ADD_COMPILER_WARNINGS([WARN], [missing-prototypes]) - WARN="$WARN -Wno-long-long" - CURL_ADD_COMPILER_WARNINGS([WARN], [float-equal]) - CURL_ADD_COMPILER_WARNINGS([WARN], [no-multichar sign-compare]) - CURL_ADD_COMPILER_WARNINGS([WARN], [undef]) - WARN="$WARN -Wno-format-nonliteral" - CURL_ADD_COMPILER_WARNINGS([WARN], [endif-labels strict-prototypes]) - CURL_ADD_COMPILER_WARNINGS([WARN], [declaration-after-statement]) - CURL_ADD_COMPILER_WARNINGS([WARN], [cast-align]) - WARN="$WARN -Wno-system-headers" - CURL_ADD_COMPILER_WARNINGS([WARN], [shorten-64-to-32]) - # - dnl Only clang 1.1 or later - if test "$compiler_num" -ge "101"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [unused]) - fi - # - dnl Only clang 2.8 or later - if test "$compiler_num" -ge "208"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [vla]) - fi - # - dnl Only clang 2.9 or later - if test "$compiler_num" -ge "209"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [shift-sign-overflow]) - fi - # - dnl Only clang 3.0 or later (possibly earlier) - if test "$compiler_num" -ge "300"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [bad-function-cast]) - CURL_ADD_COMPILER_WARNINGS([WARN], [conversion]) - CURL_ADD_COMPILER_WARNINGS([WARN], [empty-body]) - CURL_ADD_COMPILER_WARNINGS([WARN], [ignored-qualifiers]) - CURL_ADD_COMPILER_WARNINGS([WARN], [type-limits]) - CURL_ADD_COMPILER_WARNINGS([WARN], [no-sign-conversion]) - fi - # - dnl Only clang 3.2 or later - if test "$compiler_num" -ge "302"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [enum-conversion]) - case $host_os in - cygwin* | mingw*) - dnl skip missing-variable-declarations warnings for cygwin and - dnl mingw because the libtool wrapper executable causes them - ;; - *) - CURL_ADD_COMPILER_WARNINGS([WARN], [missing-variable-declarations]) - ;; - esac - fi - # - dnl Only clang 3.4 or later - if test "$compiler_num" -ge "304"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [unused-const-variable]) - fi - # - dnl Only clang 3.6 or later - if test "$compiler_num" -ge "306"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [double-promotion]) - fi - # - dnl Only clang 3.9 or later - if test "$compiler_num" -ge "309"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [comma]) - # avoid the varargs warning, fixed in 4.0 - # https://bugs.llvm.org/show_bug.cgi?id=29140 - if test "$compiler_num" -lt "400"; then - WARN="$WARN -Wno-varargs" - fi - fi - dnl clang 7 or later - if test "$compiler_num" -ge "700"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [assign-enum]) - CURL_ADD_COMPILER_WARNINGS([WARN], [extra-semi-stmt]) - fi + dnl figure out clang version! + AC_MSG_CHECKING([compiler version]) + fullclangver=`$CC -v 2>&1 | grep version` + if echo $fullclangver | grep 'Apple' >/dev/null; then + appleclang=1 + else + appleclang=0 + fi + clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*)/\1/'` + if test -z "$clangver"; then + clangver=`echo $fullclangver | "$SED" 's/.*version \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'` + oldapple=0 + else + oldapple=1 + fi + clangvhi=`echo $clangver | cut -d . -f1` + clangvlo=`echo $clangver | cut -d . -f2` + compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null` + if test "$appleclang" = '1' && test "$oldapple" = '0'; then + dnl Starting with Xcode 7 / clang 3.7, Apple clang won't tell its upstream version + if test "$compiler_num" -ge '1300'; then compiler_num='1200' + elif test "$compiler_num" -ge '1205'; then compiler_num='1101' + elif test "$compiler_num" -ge '1204'; then compiler_num='1000' + elif test "$compiler_num" -ge '1107'; then compiler_num='900' + elif test "$compiler_num" -ge '1103'; then compiler_num='800' + elif test "$compiler_num" -ge '1003'; then compiler_num='700' + elif test "$compiler_num" -ge '1001'; then compiler_num='600' + elif test "$compiler_num" -ge '904'; then compiler_num='500' + elif test "$compiler_num" -ge '902'; then compiler_num='400' + elif test "$compiler_num" -ge '803'; then compiler_num='309' + elif test "$compiler_num" -ge '703'; then compiler_num='308' + else compiler_num='307' + fi + fi + AC_MSG_RESULT([clang '$compiler_num' (raw: '$fullclangver' / '$clangver')]) - CFLAGS="$CFLAGS $WARN" - - AC_MSG_NOTICE([Added this set of compiler options: $WARN]) - - elif test "$GCC" = "yes"; then - - dnl figure out gcc version! - AC_MSG_CHECKING([gcc version]) - gccver=`$CC -dumpversion` - num1=`echo $gccver | cut -d . -f1` - num2=`echo $gccver | cut -d . -f2` - compiler_num=`(expr $num1 "*" 100 + $num2) 2>/dev/null` - AC_MSG_RESULT($gccver) - - if test "$ICC" = "yes"; then - dnl this is icc, not gcc. - - dnl ICC warnings we ignore: - dnl * 269 warns on our "%Od" printf formatters for curl_off_t output: - dnl "invalid format string conversion" - dnl * 279 warns on static conditions in while expressions - dnl * 981 warns on "operands are evaluated in unspecified order" - dnl * 1418 "external definition with no prior declaration" - dnl * 1419 warns on "external declaration in primary source file" - dnl which we know and do on purpose. - - WARN="-wd279,269,981,1418,1419" - - if test "$compiler_num" -gt "600"; then - dnl icc 6.0 and older doesn't have the -Wall flag - WARN="-Wall $WARN" - fi - else dnl $ICC = yes - dnl this is a set of options we believe *ALL* gcc versions support: - WARN="-W -Wall -Wwrite-strings -pedantic -Wpointer-arith -Wnested-externs -Winline -Wmissing-prototypes" - - if test "$compiler_num" -ge "207"; then - dnl gcc 2.7 or later - WARN="$WARN -Wmissing-declarations" - fi - - if test "$compiler_num" -gt "295"; then - dnl only if the compiler is newer than 2.95 since we got lots of - dnl "`_POSIX_C_SOURCE' is not defined" in system headers with - dnl gcc 2.95.4 on FreeBSD 4.9! - WARN="$WARN -Wbad-function-cast -Wundef -Wno-long-long -Wno-multichar -Wshadow -Wsign-compare -Wunused" - fi - - if test "$compiler_num" -ge "296"; then - dnl gcc 2.96 or later - WARN="$WARN -Wfloat-equal" - fi - - if test "$compiler_num" -gt "296"; then - dnl this option does not exist in 2.96 - WARN="$WARN -Wno-format-nonliteral" - fi - - dnl -Wunreachable-code seems totally unreliable on my gcc 3.3.2 on - dnl on i686-Linux as it gives us heaps with false positives. - dnl Also, on gcc 4.0.X it is totally unbearable and complains all - dnl over making it unusable for generic purposes. Let's not use it. - - if test "$compiler_num" -ge "303"; then - dnl gcc 3.3 and later - WARN="$WARN -Wendif-labels -Wstrict-prototypes" - fi - - if test "$compiler_num" -ge "304"; then - # try these on gcc 3.4 - WARN="$WARN -Wdeclaration-after-statement" - fi - - dnl Only gcc 4.0 or later - if test "$compiler_num" -ge "400"; then - WARN="$WARN -Wstrict-aliasing=3" - fi - # - dnl Only gcc 4.1 or later (possibly earlier) - if test "$compiler_num" -ge "401"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [no-system-headers]) - fi - # - dnl Only gcc 4.2 or later - if test "$compiler_num" -ge "402"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [cast-align]) - fi - # - dnl Only gcc 4.3 or later - if test "$compiler_num" -ge "403"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [type-limits old-style-declaration]) - CURL_ADD_COMPILER_WARNINGS([WARN], [missing-parameter-type empty-body]) - CURL_ADD_COMPILER_WARNINGS([WARN], [ignored-qualifiers]) - CURL_ADD_COMPILER_WARNINGS([WARN], [conversion]) - WARN="$WARN -Wno-sign-conversion" - CURL_ADD_COMPILER_WARNINGS([WARN], [vla]) - dnl required for -Warray-bounds, included in -Wall - WARN="$WARN -ftree-vrp" - fi - # - dnl Only gcc 4.5 or later - if test "$compiler_num" -ge "405"; then - dnl Only windows targets - case $host_os in - mingw*) - WARN="$WARN -Wno-pedantic-ms-format" - ;; - esac - fi - # - dnl Only gcc 4.6 or later - if test "$compiler_num" -ge "406"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [double-promotion]) - fi - # - dnl only gcc 4.8 or later - if test "$compiler_num" -ge "408"; then - WARN="$WARN -Wformat=2" - fi - # - dnl Only gcc 5 or later - if test "$compiler_num" -ge "500"; then - WARN="$WARN -Warray-bounds=2" - fi - # - dnl Only gcc 6 or later - if test "$compiler_num" -ge "600"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [shift-negative-value]) - WARN="$WARN -Wshift-overflow=2" - CURL_ADD_COMPILER_WARNINGS([WARN], [null-dereference]) - WARN="$WARN -fdelete-null-pointer-checks" - CURL_ADD_COMPILER_WARNINGS([WARN], [duplicated-cond]) - CURL_ADD_COMPILER_WARNINGS([WARN], [unused-const-variable]) - fi - # - dnl Only gcc 7 or later - if test "$compiler_num" -ge "700"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [duplicated-branches]) - CURL_ADD_COMPILER_WARNINGS([WARN], [restrict]) - CURL_ADD_COMPILER_WARNINGS([WARN], [alloc-zero]) - WARN="$WARN -Wformat-overflow=2" - WARN="$WARN -Wformat-truncation=1" - fi - # - dnl Only gcc 10 or later - if test "$compiler_num" -ge "1000"; then - CURL_ADD_COMPILER_WARNINGS([WARN], [arith-conversion]) - CURL_ADD_COMPILER_WARNINGS([WARN], [enum-conversion]) - fi - - for flag in $CPPFLAGS; do - case "$flag" in - -I*) - dnl Include path, provide a -isystem option for the same dir - dnl to prevent warnings in those dirs. The -isystem was not very - dnl reliable on earlier gcc versions. - add=`echo $flag | sed 's/^-I/-isystem /g'` - WARN="$WARN $add" + tmp_CFLAGS="-pedantic" + if test "$want_werror" = "yes"; then + LIBSSH2_CFLAG_EXTRAS="$LIBSSH2_CFLAG_EXTRAS -pedantic-errors" + fi + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [all extra]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pointer-arith write-strings]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [shadow]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [inline nested-externs]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-declarations]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-prototypes]) + tmp_CFLAGS="$tmp_CFLAGS -Wno-long-long" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [float-equal]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sign-compare]) + tmp_CFLAGS="$tmp_CFLAGS -Wno-multichar" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [undef]) + tmp_CFLAGS="$tmp_CFLAGS -Wno-format-nonliteral" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [endif-labels strict-prototypes]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [declaration-after-statement]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [cast-align]) + tmp_CFLAGS="$tmp_CFLAGS -Wno-system-headers" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [shorten-64-to-32]) + # + dnl Only clang 1.1 or later + if test "$compiler_num" -ge "101"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused]) + fi + # + dnl Only clang 2.7 or later + if test "$compiler_num" -ge "207"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [address]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [attributes]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [bad-function-cast]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [div-by-zero format-security]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [empty-body]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-field-initializers]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-noreturn]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [old-style-definition]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [redundant-decls]) + # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits]) + if test "x$have_windows_h" != "xyes"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-macros]) # Seen to clash with libtool-generated stub code + fi + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code unused-parameter]) + fi + # + dnl Only clang 2.8 or later + if test "$compiler_num" -ge "208"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [ignored-qualifiers]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [vla]) + fi + # + dnl Only clang 2.9 or later + if test "$compiler_num" -ge "209"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sign-conversion]) + tmp_CFLAGS="$tmp_CFLAGS -Wno-error=sign-conversion" # FIXME + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [shift-sign-overflow]) + # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs + fi + # + dnl Only clang 3.0 or later + if test "$compiler_num" -ge "300"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [language-extension-token]) + tmp_CFLAGS="$tmp_CFLAGS -Wformat=2" + fi + # + dnl Only clang 3.2 or later + if test "$compiler_num" -ge "302"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [enum-conversion]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sometimes-uninitialized]) + case $host_os in + cygwin* | mingw*) + dnl skip missing-variable-declarations warnings for cygwin and + dnl mingw because the libtool wrapper executable causes them ;; - esac - done + *) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-variable-declarations]) + ;; + esac + fi + # + dnl Only clang 3.4 or later + if test "$compiler_num" -ge "304"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [header-guard]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-const-variable]) + fi + # + dnl Only clang 3.5 or later + if test "$compiler_num" -ge "305"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pragmas]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code-break]) + fi + # + dnl Only clang 3.6 or later + if test "$compiler_num" -ge "306"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [double-promotion]) + fi + # + dnl Only clang 3.9 or later + if test "$compiler_num" -ge "309"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [comma]) + # avoid the varargs warning, fixed in 4.0 + # https://bugs.llvm.org/show_bug.cgi?id=29140 + if test "$compiler_num" -lt "400"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-varargs" + fi + fi + dnl clang 7 or later + if test "$compiler_num" -ge "700"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [assign-enum]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [extra-semi-stmt]) + fi + dnl clang 10 or later + if test "$compiler_num" -ge "1000"; then + tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough" # we have silencing markup for clang 10.0 and above only + fi - fi dnl $ICC = no + CFLAGS="$CFLAGS $tmp_CFLAGS" - CFLAGS="$CFLAGS $WARN" + AC_MSG_NOTICE([Added this set of compiler options: $tmp_CFLAGS]) - AC_MSG_NOTICE([Added this set of compiler options: $WARN]) + elif test "$GCC" = "yes"; then - else dnl $GCC = yes + # indentation to match curl's m4/curl-compilers.m4 - AC_MSG_NOTICE([Added no extra compiler options]) + dnl figure out gcc version! + AC_MSG_CHECKING([compiler version]) + # strip '-suffix' parts, e.g. Ubuntu Windows cross-gcc returns '10-win32' + gccver=`$CC -dumpversion | sed -E 's/-.+$//'` + gccvhi=`echo $gccver | cut -d . -f1` + if echo $gccver | grep -F "." >/dev/null; then + gccvlo=`echo $gccver | cut -d . -f2` + else + gccvlo="0" + fi + compiler_num=`(expr $gccvhi "*" 100 + $gccvlo) 2>/dev/null` + AC_MSG_RESULT([gcc '$compiler_num' (raw: '$gccver')]) - fi dnl $GCC = yes + if test "$ICC" = "yes"; then + dnl this is icc, not gcc. - dnl strip off optimizer flags - NEWFLAGS="" - for flag in $CFLAGS; do - case "$flag" in - -O*) - dnl echo "cut off $flag" - ;; - *) - NEWFLAGS="$NEWFLAGS $flag" - ;; - esac - done - CFLAGS=$NEWFLAGS + dnl ICC warnings we ignore: + dnl * 269 warns on our "%Od" printf formatters for curl_off_t output: + dnl "invalid format string conversion" + dnl * 279 warns on static conditions in while expressions + dnl * 981 warns on "operands are evaluated in unspecified order" + dnl * 1418 "external definition with no prior declaration" + dnl * 1419 warns on "external declaration in primary source file" + dnl which we know and do on purpose. + + tmp_CFLAGS="-wd279,269,981,1418,1419" + + if test "$compiler_num" -gt "600"; then + dnl icc 6.0 and older doesn't have the -Wall flag + tmp_CFLAGS="-Wall $tmp_CFLAGS" + fi + else dnl $ICC = yes + dnl this is a set of options we believe *ALL* gcc versions support: + tmp_CFLAGS="-pedantic" + if test "$want_werror" = "yes"; then + LIBSSH2_CFLAG_EXTRAS="$LIBSSH2_CFLAG_EXTRAS -pedantic-errors" + fi + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [all]) + tmp_CFLAGS="$tmp_CFLAGS -W" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pointer-arith write-strings]) + # + dnl Only gcc 2.7 or later + if test "$compiler_num" -ge "207"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [inline nested-externs]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-declarations]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-prototypes]) + fi + # + dnl Only gcc 2.95 or later + if test "$compiler_num" -ge "295"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-long-long" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [bad-function-cast]) + fi + # + dnl Only gcc 2.96 or later + if test "$compiler_num" -ge "296"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [float-equal]) + tmp_CFLAGS="$tmp_CFLAGS -Wno-multichar" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sign-compare]) + dnl -Wundef used only if gcc is 2.96 or later since we get + dnl lots of "`_POSIX_C_SOURCE' is not defined" in system + dnl headers with gcc 2.95.4 on FreeBSD 4.9 + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [undef]) + fi + # + dnl Only gcc 2.97 or later + if test "$compiler_num" -ge "297"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-format-nonliteral" + fi + # + dnl Only gcc 3.0 or later + if test "$compiler_num" -ge "300"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-system-headers" + dnl -Wunreachable-code seems totally unreliable on my gcc 3.3.2 on + dnl on i686-Linux as it gives us heaps with false positives. + dnl Also, on gcc 4.0.X it is totally unbearable and complains all + dnl over making it unusable for generic purposes. Let's not use it. + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused shadow]) + fi + # + dnl Only gcc 3.3 or later + if test "$compiler_num" -ge "303"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [endif-labels strict-prototypes]) + fi + # + dnl Only gcc 3.4 or later + if test "$compiler_num" -ge "304"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [declaration-after-statement]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [old-style-definition]) + fi + # + dnl Only gcc 4.0 or later + if test "$compiler_num" -ge "400"; then + tmp_CFLAGS="$tmp_CFLAGS -Wstrict-aliasing=3" + fi + # + dnl Only gcc 4.1 or later (possibly earlier) + if test "$compiler_num" -ge "401"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [attributes]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [div-by-zero format-security]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-field-initializers]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-noreturn]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code unused-parameter]) + # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pragmas]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [redundant-decls]) + # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-macros]) + fi + # + dnl Only gcc 4.2 or later + if test "$compiler_num" -ge "402"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [cast-align]) + fi + # + dnl Only gcc 4.3 or later + if test "$compiler_num" -ge "403"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [address]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits old-style-declaration]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-parameter-type empty-body]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [clobbered ignored-qualifiers]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion trampolines]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sign-conversion]) + tmp_CFLAGS="$tmp_CFLAGS -Wno-error=sign-conversion" # FIXME + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [vla]) + dnl required for -Warray-bounds, included in -Wall + tmp_CFLAGS="$tmp_CFLAGS -ftree-vrp" + fi + # + dnl Only gcc 4.5 or later + if test "$compiler_num" -ge "405"; then + dnl Only windows targets + case $host_os in + mingw*) + tmp_CFLAGS="$tmp_CFLAGS -Wno-pedantic-ms-format" + ;; + esac + fi + # + dnl Only gcc 4.6 or later + if test "$compiler_num" -ge "406"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [double-promotion]) + fi + # + dnl only gcc 4.8 or later + if test "$compiler_num" -ge "408"; then + tmp_CFLAGS="$tmp_CFLAGS -Wformat=2" + fi + # + dnl Only gcc 5 or later + if test "$compiler_num" -ge "500"; then + tmp_CFLAGS="$tmp_CFLAGS -Warray-bounds=2" + fi + # + dnl Only gcc 6 or later + if test "$compiler_num" -ge "600"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [shift-negative-value]) + tmp_CFLAGS="$tmp_CFLAGS -Wshift-overflow=2" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [null-dereference]) + tmp_CFLAGS="$tmp_CFLAGS -fdelete-null-pointer-checks" + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [duplicated-cond]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-const-variable]) + fi + # + dnl Only gcc 7 or later + if test "$compiler_num" -ge "700"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [duplicated-branches]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [restrict]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [alloc-zero]) + tmp_CFLAGS="$tmp_CFLAGS -Wformat-overflow=2" + tmp_CFLAGS="$tmp_CFLAGS -Wformat-truncation=2" + tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough" + fi + # + dnl Only gcc 10 or later + if test "$compiler_num" -ge "1000"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [arith-conversion]) + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [enum-conversion]) + fi + + for flag in $CPPFLAGS; do + case "$flag" in + -I*) + dnl Include path, provide a -isystem option for the same dir + dnl to prevent warnings in those dirs. The -isystem was not very + dnl reliable on earlier gcc versions. + add=`echo $flag | sed 's/^-I/-isystem /g'` + tmp_CFLAGS="$tmp_CFLAGS $add" + ;; + esac + done + + fi dnl $ICC = no + + CFLAGS="$CFLAGS $tmp_CFLAGS" + + AC_MSG_NOTICE([Added this set of compiler options: $tmp_CFLAGS]) + + else dnl $GCC = yes + + AC_MSG_NOTICE([Added no extra compiler options]) + + fi dnl $GCC = yes + + dnl strip off optimizer flags + NEWFLAGS="" + for flag in $CFLAGS; do + case "$flag" in + -O*) + dnl echo "cut off $flag" + ;; + *) + NEWFLAGS="$NEWFLAGS $flag" + ;; + esac + done + CFLAGS=$NEWFLAGS ]) dnl end of AC_DEFUN() @@ -748,7 +832,7 @@ dnl autoconf only checks $prefix/lib64 if gcc -print-search-dirs output dnl includes a directory named lib64. So, to find libraries in $prefix/lib dnl we append -L$prefix/lib to LDFLAGS before checking. dnl -dnl For conveniece, $4 is expanded if [lib]$1 is found. +dnl For convenience, $4 is expanded if [lib]$1 is found. AC_DEFUN([LIBSSH2_LIB_HAVE_LINKFLAGS], [ libssh2_save_CPPFLAGS="$CPPFLAGS" @@ -761,12 +845,11 @@ AC_DEFUN([LIBSSH2_LIB_HAVE_LINKFLAGS], [ AC_LIB_HAVE_LINKFLAGS([$1], [$2], [$3]) - LDFLAGS="$libssh2_save_LDFLAGS" - if test "$ac_cv_lib$1" = "yes"; then : $4 else CPPFLAGS="$libssh2_save_CPPFLAGS" + LDFLAGS="$libssh2_save_LDFLAGS" fi ]) @@ -776,21 +859,16 @@ m4_case([$1], [openssl], [ LIBSSH2_LIB_HAVE_LINKFLAGS([ssl], [crypto], [#include ], [ AC_DEFINE(LIBSSH2_OPENSSL, 1, [Use $1]) - LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }libssl libcrypto" + LIBSSH2_PC_REQUIRES_PRIVATE="$LIBSSH2_PC_REQUIRES_PRIVATE${LIBSSH2_PC_REQUIRES_PRIVATE:+,}libcrypto" found_crypto="$1" found_crypto_str="OpenSSL" ]) ], [wolfssl], [ - if test "${with_libwolfssl_prefix+set}" = set; then - CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I${with_libwolfssl_prefix}/include/wolfssl" - else - AC_MSG_ERROR([When using wolfSSL, must specify prefix with --with-libwolfssl-prefix in order to find OpenSSL compatibility headers.]) - fi LIBSSH2_LIB_HAVE_LINKFLAGS([wolfssl], [], [#include ], [ AC_DEFINE(LIBSSH2_WOLFSSL, 1, [Use $1]) - LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }libwolfssl" + LIBSSH2_PC_REQUIRES_PRIVATE="$LIBSSH2_PC_REQUIRES_PRIVATE${LIBSSH2_PC_REQUIRES_PRIVATE:+,}wolfssl" found_crypto="$1" ]) ], @@ -798,6 +876,7 @@ m4_case([$1], [libgcrypt], [ LIBSSH2_LIB_HAVE_LINKFLAGS([gcrypt], [], [#include ], [ AC_DEFINE(LIBSSH2_LIBGCRYPT, 1, [Use $1]) + LIBSSH2_PC_REQUIRES_PRIVATE="$LIBSSH2_PC_REQUIRES_PRIVATE${LIBSSH2_PC_REQUIRES_PRIVATE:+,}libgcrypt" found_crypto="$1" ]) ], @@ -811,19 +890,21 @@ m4_case([$1], ], [wincng], [ - # Look for Windows Cryptography API: Next Generation + if test "x$have_windows_h" = "xyes"; then + # Look for Windows Cryptography API: Next Generation - LIBS="$LIBS -lcrypt32" + LIBS="$LIBS -lcrypt32" - # Check necessary for old-MinGW - LIBSSH2_LIB_HAVE_LINKFLAGS([bcrypt], [], [ - #include - #include - ], [ - AC_DEFINE(LIBSSH2_WINCNG, 1, [Use $1]) - found_crypto="$1" - found_crypto_str="Windows Cryptography API: Next Generation" - ]) + # Check necessary for old-MinGW + LIBSSH2_LIB_HAVE_LINKFLAGS([bcrypt], [], [ + #include + #include + ], [ + AC_DEFINE(LIBSSH2_WINCNG, 1, [Use $1]) + found_crypto="$1" + found_crypto_str="Windows Cryptography API: Next Generation" + ]) + fi ], ) test "$found_crypto" = "none" && @@ -864,6 +945,6 @@ AS_HELP_STRING([--disable-werror],[Disable compiler warnings as errors]), AC_MSG_RESULT([$want_werror]) if test X"$want_werror" = Xyes; then - CFLAGS="$CFLAGS -Werror" + LIBSSH2_CFLAG_EXTRAS="$LIBSSH2_CFLAG_EXTRAS -Werror" fi ]) diff --git a/libssh2/aclocal.m4 b/libssh2/aclocal.m4 index a5f826bab..390d9b403 100644 --- a/libssh2/aclocal.m4 +++ b/libssh2/aclocal.m4 @@ -14,8 +14,8 @@ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, -[m4_warning([this file was generated for autoconf 2.71. +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.72],, +[m4_warning([this file was generated for autoconf 2.72. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) @@ -1184,7 +1184,6 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR -m4_include([m4/autobuild.m4]) m4_include([m4/lib-ld.m4]) m4_include([m4/lib-link.m4]) m4_include([m4/lib-prefix.m4]) diff --git a/libssh2/cmake/CheckFunctionExistsMayNeedLibrary.cmake b/libssh2/cmake/CheckFunctionExistsMayNeedLibrary.cmake index 2de0a70e3..d11b20193 100644 --- a/libssh2/cmake/CheckFunctionExistsMayNeedLibrary.cmake +++ b/libssh2/cmake/CheckFunctionExistsMayNeedLibrary.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014 Alexander Lamaison +# Copyright (C) Alexander Lamaison # # Redistribution and use in source and binary forms, # with or without modification, are permitted provided @@ -32,6 +32,8 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. +# +# SPDX-License-Identifier: BSD-3-Clause # - check_function_exists_maybe_need_library( [lib1 ... libn]) @@ -58,21 +60,19 @@ include(CheckFunctionExists) include(CheckLibraryExists) -function(check_function_exists_may_need_library function variable) +function(check_function_exists_may_need_library _function _variable) - check_function_exists(${function} ${variable}) + check_function_exists(${_function} ${_variable}) - if(NOT ${variable}) - foreach(lib ${ARGN}) - string(TOUPPER ${lib} UP_LIB) + if(NOT ${_variable}) + foreach(_lib IN LISTS ARGN) + string(TOUPPER ${_lib} _up_lib) # Use new variable to prevent cache from previous step shortcircuiting # new test - check_library_exists(${lib} ${function} "" HAVE_${function}_IN_${lib}) - if(HAVE_${function}_IN_${lib}) - set(${variable} 1 CACHE INTERNAL - "Function ${function} found in library ${lib}") - set(NEED_LIB_${UP_LIB} 1 CACHE INTERNAL - "Need to link ${lib}") + check_library_exists(${_lib} ${_function} "" HAVE_${_function}_IN_${_lib}) + if(HAVE_${_function}_IN_${_lib}) + set(${_variable} 1 CACHE INTERNAL "Function ${_function} found in library ${_lib}") + set(NEED_LIB_${_up_lib} 1 CACHE INTERNAL "Need to link ${_lib}") break() endif() endforeach() diff --git a/libssh2/cmake/CheckNonblockingSocketSupport.cmake b/libssh2/cmake/CheckNonblockingSocketSupport.cmake index 4af73a29a..bb3229cf3 100644 --- a/libssh2/cmake/CheckNonblockingSocketSupport.cmake +++ b/libssh2/cmake/CheckNonblockingSocketSupport.cmake @@ -1,3 +1,5 @@ +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause include(CheckCSourceCompiles) # - check_nonblocking_socket_support() diff --git a/libssh2/cmake/CopyRuntimeDependencies.cmake b/libssh2/cmake/CopyRuntimeDependencies.cmake index 083f76268..9181e4dfe 100644 --- a/libssh2/cmake/CopyRuntimeDependencies.cmake +++ b/libssh2/cmake/CopyRuntimeDependencies.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2014 Alexander Lamaison +# Copyright (C) Alexander Lamaison # # Redistribution and use in source and binary forms, # with or without modification, are permitted provided @@ -32,15 +32,16 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. +# +# SPDX-License-Identifier: BSD-3-Clause include(CMakeParseArguments) -function(ADD_TARGET_TO_COPY_DEPENDENCIES) +function(add_target_to_copy_dependencies) set(options) set(oneValueArgs TARGET) set(multiValueArgs DEPENDENCIES BEFORE_TARGETS) - cmake_parse_arguments(COPY - "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + cmake_parse_arguments(COPY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT COPY_DEPENDENCIES) return() @@ -50,23 +51,18 @@ function(ADD_TARGET_TO_COPY_DEPENDENCIES) # parallel builds trying to kick off the commands at the same time add_custom_target(${COPY_TARGET}) - foreach(target ${COPY_BEFORE_TARGETS}) - add_dependencies(${target} ${COPY_TARGET}) + foreach(_target IN LISTS COPY_BEFORE_TARGETS) + add_dependencies(${_target} ${COPY_TARGET}) endforeach() - foreach(dependency ${COPY_DEPENDENCIES}) - + foreach(_dependency IN LISTS COPY_DEPENDENCIES) add_custom_command( TARGET ${COPY_TARGET} - DEPENDS ${dependency} + DEPENDS ${_dependency} # Make directory first otherwise file is copied in place of # directory instead of into it - COMMAND ${CMAKE_COMMAND} - ARGS -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - COMMAND ${CMAKE_COMMAND} - ARGS -E copy ${dependency} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + COMMAND ${CMAKE_COMMAND} ARGS -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" + COMMAND ${CMAKE_COMMAND} ARGS -E copy ${_dependency} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" VERBATIM) - endforeach() - endfunction() diff --git a/libssh2/cmake/FindLibgcrypt.cmake b/libssh2/cmake/FindLibgcrypt.cmake index 4de3888d1..4582ce9b2 100644 --- a/libssh2/cmake/FindLibgcrypt.cmake +++ b/libssh2/cmake/FindLibgcrypt.cmake @@ -1,53 +1,59 @@ -# Copyright (c) 2014 Alexander Lamaison +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause # -# Redistribution and use in source and binary forms, -# with or without modification, are permitted provided -# that the following conditions are met: +########################################################################### +# Find the libgcrypt library # -# Redistributions of source code must retain the above -# copyright notice, this list of conditions and the -# following disclaimer. +# Input variables: # -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials -# provided with the distribution. +# LIBGCRYPT_INCLUDE_DIR The libgcrypt include directory +# LIBGCRYPT_LIBRARY Path to libgcrypt library # -# Neither the name of the copyright holder nor the names -# of any other contributors may be used to endorse or -# promote products derived from this software without -# specific prior written permission. +# Result variables: # -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -# OF SUCH DAMAGE. +# LIBGCRYPT_FOUND System has libgcrypt +# LIBGCRYPT_INCLUDE_DIRS The libgcrypt include directories +# LIBGCRYPT_LIBRARIES The libgcrypt library names +# LIBGCRYPT_LIBRARY_DIRS The libgcrypt library directories +# LIBGCRYPT_CFLAGS Required compiler flags +# LIBGCRYPT_VERSION Version of libgcrypt -# - Try to find Libgcrypt -# This will define all or none of: -# LIBGCRYPT_FOUND - if Libgcrypt headers and library was found -# LIBGCRYPT_INCLUDE_DIRS - The Libgcrypt include directories -# LIBGCRYPT_LIBRARIES - The libraries needed to use Libgcrypt +if((UNIX OR VCPKG_TOOLCHAIN OR (MINGW AND NOT CMAKE_CROSSCOMPILING)) AND + NOT DEFINED LIBGCRYPT_INCLUDE_DIR AND + NOT DEFINED LIBGCRYPT_LIBRARY) + find_package(PkgConfig QUIET) + pkg_check_modules(LIBGCRYPT "libgcrypt") +endif() -find_path(LIBGCRYPT_INCLUDE_DIR gcrypt.h) +if(LIBGCRYPT_FOUND) + string(REPLACE ";" " " LIBGCRYPT_CFLAGS "${LIBGCRYPT_CFLAGS}") + message(STATUS "Found Libgcrypt (via pkg-config): ${LIBGCRYPT_INCLUDE_DIRS} (found version \"${LIBGCRYPT_VERSION}\")") +else() + find_path(LIBGCRYPT_INCLUDE_DIR NAMES "gcrypt.h") + find_library(LIBGCRYPT_LIBRARY NAMES "gcrypt" "libgcrypt") -find_library(LIBGCRYPT_LIBRARY NAMES gcrypt libgcrypt) + if(LIBGCRYPT_INCLUDE_DIR AND EXISTS "${LIBGCRYPT_INCLUDE_DIR}/gcrypt.h") + set(_version_regex "#[\t ]*define[\t ]+GCRYPT_VERSION[\t ]+\"([^\"]*)\"") + file(STRINGS "${LIBGCRYPT_INCLUDE_DIR}/gcrypt.h" _version_str REGEX "${_version_regex}") + string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}") + set(LIBGCRYPT_VERSION "${_version_str}") + unset(_version_regex) + unset(_version_str) + endif() -set(LIBGCRYPT_LIBRARIES ${LIBGCRYPT_LIBRARY}) -set(LIBGCRYPT_INCLUDE_DIRS ${LIBGCRYPT_INCLUDE_DIR}) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Libgcrypt + REQUIRED_VARS + LIBGCRYPT_INCLUDE_DIR + LIBGCRYPT_LIBRARY + VERSION_VAR + LIBGCRYPT_VERSION + ) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Libgcrypt DEFAULT_MSG - LIBGCRYPT_LIBRARY LIBGCRYPT_INCLUDE_DIR) + if(LIBGCRYPT_FOUND) + set(LIBGCRYPT_INCLUDE_DIRS ${LIBGCRYPT_INCLUDE_DIR}) + set(LIBGCRYPT_LIBRARIES ${LIBGCRYPT_LIBRARY}) + endif() -mark_as_advanced(LIBGCRYPT_INCLUDE_DIR LIBGCRYPT_LIBRARY) + mark_as_advanced(LIBGCRYPT_INCLUDE_DIR LIBGCRYPT_LIBRARY) +endif() diff --git a/libssh2/cmake/FindMbedTLS.cmake b/libssh2/cmake/FindMbedTLS.cmake new file mode 100644 index 000000000..26bc56557 --- /dev/null +++ b/libssh2/cmake/FindMbedTLS.cmake @@ -0,0 +1,69 @@ +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause +# +########################################################################### +# Find the mbedtls library +# +# Input variables: +# +# MBEDTLS_INCLUDE_DIR The mbedtls include directory +# MBEDCRYPTO_LIBRARY Path to mbedcrypto library +# +# Result variables: +# +# MBEDTLS_FOUND System has mbedtls +# MBEDTLS_INCLUDE_DIRS The mbedtls include directories +# MBEDTLS_LIBRARIES The mbedtls library names +# MBEDTLS_LIBRARY_DIRS The mbedtls library directories +# MBEDTLS_CFLAGS Required compiler flags +# MBEDTLS_VERSION Version of mbedtls + +if((UNIX OR VCPKG_TOOLCHAIN OR (MINGW AND NOT CMAKE_CROSSCOMPILING)) AND + NOT DEFINED MBEDTLS_INCLUDE_DIR AND + NOT DEFINED MBEDCRYPTO_LIBRARY) + find_package(PkgConfig QUIET) + pkg_check_modules(MBEDTLS "mbedcrypto") +endif() + +if(MBEDTLS_FOUND) + string(REPLACE ";" " " MBEDTLS_CFLAGS "${MBEDTLS_CFLAGS}") + message(STATUS "Found MbedTLS (via pkg-config): ${MBEDTLS_INCLUDE_DIRS} (found version \"${MBEDTLS_VERSION}\")") +else() + find_path(MBEDTLS_INCLUDE_DIR NAMES "mbedtls/version.h") + find_library(MBEDCRYPTO_LIBRARY NAMES "mbedcrypto" "libmbedcrypto") + + if(MBEDTLS_INCLUDE_DIR) + if(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h") # 3.x + set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h") + elseif(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h") # 2.x + set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h") + else() + unset(_version_header) + endif() + if(_version_header) + set(_version_regex "#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"([0-9.]+)\"") + file(STRINGS "${_version_header}" _version_str REGEX "${_version_regex}") + string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}") + set(MBEDTLS_VERSION "${_version_str}") + unset(_version_regex) + unset(_version_str) + unset(_version_header) + endif() + endif() + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(MbedTLS + REQUIRED_VARS + MBEDTLS_INCLUDE_DIR + MBEDCRYPTO_LIBRARY + VERSION_VAR + MBEDTLS_VERSION + ) + + if(MBEDTLS_FOUND) + set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR}) + set(MBEDTLS_LIBRARIES ${MBEDCRYPTO_LIBRARY}) + endif() + + mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDCRYPTO_LIBRARY) +endif() diff --git a/libssh2/cmake/FindWolfSSL.cmake b/libssh2/cmake/FindWolfSSL.cmake new file mode 100644 index 000000000..f66a59dfe --- /dev/null +++ b/libssh2/cmake/FindWolfSSL.cmake @@ -0,0 +1,59 @@ +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause +# +########################################################################### +# Find the wolfssl library +# +# Input variables: +# +# WOLFSSL_INCLUDE_DIR The wolfssl include directory +# WOLFSSL_LIBRARY Path to wolfssl library +# +# Result variables: +# +# WOLFSSL_FOUND System has wolfssl +# WOLFSSL_INCLUDE_DIRS The wolfssl include directories +# WOLFSSL_LIBRARIES The wolfssl library names +# WOLFSSL_LIBRARY_DIRS The wolfssl library directories +# WOLFSSL_CFLAGS Required compiler flags +# WOLFSSL_VERSION Version of wolfssl + +if((UNIX OR VCPKG_TOOLCHAIN OR (MINGW AND NOT CMAKE_CROSSCOMPILING)) AND + NOT DEFINED WOLFSSL_INCLUDE_DIR AND + NOT DEFINED WOLFSSL_LIBRARY) + find_package(PkgConfig QUIET) + pkg_check_modules(WOLFSSL "wolfssl") +endif() + +if(WOLFSSL_FOUND) + string(REPLACE ";" " " WOLFSSL_CFLAGS "${WOLFSSL_CFLAGS}") + message(STATUS "Found WolfSSL (via pkg-config): ${WOLFSSL_INCLUDE_DIRS} (found version \"${WOLFSSL_VERSION}\")") +else() + find_path(WOLFSSL_INCLUDE_DIR NAMES "wolfssl/options.h") + find_library(WOLFSSL_LIBRARY NAMES "wolfssl") + + if(WOLFSSL_INCLUDE_DIR AND EXISTS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h") + set(_version_regex "#[\t ]*define[\t ]+LIBWOLFSSL_VERSION_STRING[\t ]+\"([^\"]*)\"") + file(STRINGS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h" _version_str REGEX "${_version_regex}") + string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}") + set(WOLFSSL_VERSION "${_version_str}") + unset(_version_regex) + unset(_version_str) + endif() + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(WolfSSL + REQUIRED_VARS + WOLFSSL_INCLUDE_DIR + WOLFSSL_LIBRARY + VERSION_VAR + WOLFSSL_VERSION + ) + + if(WOLFSSL_FOUND) + set(WOLFSSL_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR}) + set(WOLFSSL_LIBRARIES ${WOLFSSL_LIBRARY}) + endif() + + mark_as_advanced(WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY) +endif() diff --git a/libssh2/cmake/PickyWarnings.cmake b/libssh2/cmake/PickyWarnings.cmake new file mode 100644 index 000000000..94feee87d --- /dev/null +++ b/libssh2/cmake/PickyWarnings.cmake @@ -0,0 +1,247 @@ +# Copyright (C) Viktor Szakats +# SPDX-License-Identifier: BSD-3-Clause + +include(CheckCCompilerFlag) + +option(ENABLE_WERROR "Turn compiler warnings into errors" OFF) +option(PICKY_COMPILER "Enable picky compiler options" ON) + +if(ENABLE_WERROR) + if(MSVC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") + else() # llvm/clang and gcc style options + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + endif() +endif() + +if(MSVC) + # Use the highest warning level for Visual Studio. + if(PICKY_COMPILER) + if(CMAKE_CXX_FLAGS MATCHES "[/-]W[0-4]") + string(REGEX REPLACE "[/-]W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + endif() + if(CMAKE_C_FLAGS MATCHES "[/-]W[0-4]") + string(REGEX REPLACE "[/-]W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") + endif() + endif() +elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang") + + # https://clang.llvm.org/docs/DiagnosticsReference.html + # https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html + + if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") + endif() + if(NOT CMAKE_C_FLAGS MATCHES "-Wall") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") + endif() + + if(PICKY_COMPILER) + + # WPICKY_ENABLE = Options we want to enable as-is. + # WPICKY_DETECT = Options we want to test first and enable if available. + + # Prefer the -Wextra alias with clang. + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set(WPICKY_ENABLE "-Wextra") + else() + set(WPICKY_ENABLE "-W") + endif() + + list(APPEND WPICKY_ENABLE + -pedantic + ) + + if(ENABLE_WERROR) + list(APPEND WPICKY_ENABLE + -pedantic-errors + ) + endif() + + # ---------------------------------- + # Add new options here, if in doubt: + # ---------------------------------- + set(WPICKY_DETECT + ) + + # Assume these options always exist with both clang and gcc. + # Require clang 3.0 / gcc 2.95 or later. + list(APPEND WPICKY_ENABLE + -Wbad-function-cast # clang 2.7 gcc 2.95 + -Wconversion # clang 2.7 gcc 2.95 + -Winline # clang 1.0 gcc 1.0 + -Wmissing-declarations # clang 1.0 gcc 2.7 + -Wmissing-prototypes # clang 1.0 gcc 1.0 + -Wnested-externs # clang 1.0 gcc 2.7 + -Wno-long-long # clang 1.0 gcc 2.95 + -Wno-multichar # clang 1.0 gcc 2.95 + -Wpointer-arith # clang 1.0 gcc 1.4 + -Wshadow # clang 1.0 gcc 2.95 + -Wsign-compare # clang 1.0 gcc 2.95 + -Wundef # clang 1.0 gcc 2.95 + -Wunused # clang 1.1 gcc 2.95 + -Wwrite-strings # clang 1.0 gcc 1.4 + ) + + # Always enable with clang, version dependent with gcc + set(WPICKY_COMMON_OLD + -Waddress # clang 2.7 gcc 4.3 + -Wattributes # clang 2.7 gcc 4.1 + -Wcast-align # clang 1.0 gcc 4.2 + -Wdeclaration-after-statement # clang 1.0 gcc 3.4 + -Wdiv-by-zero # clang 2.7 gcc 4.1 + -Wempty-body # clang 2.7 gcc 4.3 + -Wendif-labels # clang 1.0 gcc 3.3 + -Wfloat-equal # clang 1.0 gcc 2.96 (3.0) + -Wformat-security # clang 2.7 gcc 4.1 + -Wignored-qualifiers # clang 2.8 gcc 4.3 + -Wmissing-field-initializers # clang 2.7 gcc 4.1 + -Wmissing-noreturn # clang 2.7 gcc 4.1 + -Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0) + -Wno-system-headers # clang 1.0 gcc 3.0 + # -Wpadded # clang 2.9 gcc 4.1 # Not used because we cannot change public structs + -Wold-style-definition # clang 2.7 gcc 3.4 + -Wredundant-decls # clang 2.7 gcc 4.1 + -Wsign-conversion # clang 2.9 gcc 4.3 + -Wno-error=sign-conversion # FIXME + -Wstrict-prototypes # clang 1.0 gcc 3.3 + # -Wswitch-enum # clang 2.7 gcc 4.1 # Not used because this basically disallows default case + -Wtype-limits # clang 2.7 gcc 4.3 + -Wunreachable-code # clang 2.7 gcc 4.1 + -Wunused-macros # clang 2.7 gcc 4.1 + -Wunused-parameter # clang 2.7 gcc 4.1 + -Wvla # clang 2.8 gcc 4.3 + ) + + set(WPICKY_COMMON + -Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.3 + -Wenum-conversion # clang 3.2 gcc 10.0 appleclang 4.6 g++ 11.0 + -Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0 + -Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1 + ) + + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + list(APPEND WPICKY_ENABLE + ${WPICKY_COMMON_OLD} + -Wshift-sign-overflow # clang 2.9 + -Wshorten-64-to-32 # clang 1.0 + -Wlanguage-extension-token # clang 3.0 + -Wformat=2 # clang 3.0 gcc 4.8 + ) + # Enable based on compiler version + if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR + (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3)) + list(APPEND WPICKY_ENABLE + ${WPICKY_COMMON} + -Wunreachable-code-break # clang 3.5 appleclang 6.0 + -Wheader-guard # clang 3.4 appleclang 5.1 + -Wsometimes-uninitialized # clang 3.2 appleclang 4.6 + ) + endif() + if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR + (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.3)) + list(APPEND WPICKY_ENABLE + -Wcomma # clang 3.9 appleclang 8.3 + -Wmissing-variable-declarations # clang 3.2 appleclang 4.6 + ) + endif() + if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0) OR + (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.3)) + list(APPEND WPICKY_ENABLE + -Wassign-enum # clang 7.0 appleclang 10.3 + -Wextra-semi-stmt # clang 7.0 appleclang 10.3 + ) + endif() + if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0) OR + (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.4)) + list(APPEND WPICKY_ENABLE + -Wimplicit-fallthrough # clang 4.0 gcc 7.0 appleclang 12.4 # we have silencing markup for clang 10.0 and above only + ) + endif() + else() # gcc + list(APPEND WPICKY_DETECT + ${WPICKY_COMMON} + ) + # Enable based on compiler version + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3) + list(APPEND WPICKY_ENABLE + ${WPICKY_COMMON_OLD} + -Wclobbered # gcc 4.3 + -Wmissing-parameter-type # gcc 4.3 + -Wold-style-declaration # gcc 4.3 + -Wstrict-aliasing=3 # gcc 4.0 + -Wtrampolines # gcc 4.3 + ) + endif() + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5 AND MINGW) + list(APPEND WPICKY_ENABLE + -Wno-pedantic-ms-format # gcc 4.5 (mingw-only) + ) + endif() + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8) + list(APPEND WPICKY_ENABLE + -Wformat=2 # clang 3.0 gcc 4.8 + ) + endif() + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0) + list(APPEND WPICKY_ENABLE + -Warray-bounds=2 -ftree-vrp # clang 3.0 gcc 5.0 (clang default: -Warray-bounds) + ) + endif() + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.0) + list(APPEND WPICKY_ENABLE + -Wduplicated-cond # gcc 6.0 + -Wnull-dereference # clang 3.0 gcc 6.0 (clang default) + -fdelete-null-pointer-checks + -Wshift-negative-value # clang 3.7 gcc 6.0 (clang default) + -Wshift-overflow=2 # clang 3.0 gcc 6.0 (clang default: -Wshift-overflow) + ) + endif() + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0) + list(APPEND WPICKY_ENABLE + -Walloc-zero # gcc 7.0 + -Wduplicated-branches # gcc 7.0 + -Wformat-overflow=2 # gcc 7.0 + -Wformat-truncation=2 # gcc 7.0 + -Wimplicit-fallthrough # clang 4.0 gcc 7.0 + -Wrestrict # gcc 7.0 + ) + endif() + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0) + list(APPEND WPICKY_ENABLE + -Warith-conversion # gcc 10.0 + ) + endif() + endif() + + # + + unset(WPICKY) + + foreach(_CCOPT IN LISTS WPICKY_ENABLE) + set(WPICKY "${WPICKY} ${_CCOPT}") + endforeach() + + foreach(_CCOPT IN LISTS WPICKY_DETECT) + # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new + # test result in. + string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname) + # GCC only warns about unknown -Wno- options if there are also other diagnostic messages, + # so test for the positive form instead + string(REPLACE "-Wno-" "-W" _CCOPT_ON "${_CCOPT}") + check_c_compiler_flag(${_CCOPT_ON} ${_optvarname}) + if(${_optvarname}) + set(WPICKY "${WPICKY} ${_CCOPT}") + endif() + endforeach() + + message(STATUS "Picky compiler options:${WPICKY}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WPICKY}") + endif() +endif() diff --git a/libssh2/cmake/libssh2-config.cmake.in b/libssh2/cmake/libssh2-config.cmake.in new file mode 100644 index 000000000..edc86d7c5 --- /dev/null +++ b/libssh2/cmake/libssh2-config.cmake.in @@ -0,0 +1,31 @@ +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause + +include(CMakeFindDependencyMacro) +list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +if("@CRYPTO_BACKEND@" STREQUAL "OpenSSL") + find_dependency(OpenSSL) +elseif("@CRYPTO_BACKEND@" STREQUAL "wolfSSL") + find_dependency(WolfSSL) +elseif("@CRYPTO_BACKEND@" STREQUAL "Libgcrypt") + find_dependency(Libgcrypt) +elseif("@CRYPTO_BACKEND@" STREQUAL "mbedTLS") + find_dependency(MbedTLS) +endif() + +if(@ZLIB_FOUND@) + find_dependency(ZLIB) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") + +# Alias for either shared or static library +if(NOT TARGET @PROJECT_NAME@::@LIB_NAME@) + add_library(@PROJECT_NAME@::@LIB_NAME@ ALIAS @PROJECT_NAME@::@LIB_SELECTED@) +endif() + +# Compatibility alias +if(NOT TARGET Libssh2::@LIB_NAME@) + add_library(Libssh2::@LIB_NAME@ ALIAS @PROJECT_NAME@::@LIB_SELECTED@) +endif() diff --git a/libssh2/config.rpath b/libssh2/config.rpath index e082db6bb..5e39f28d8 100755 --- a/libssh2/config.rpath +++ b/libssh2/config.rpath @@ -24,6 +24,8 @@ # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. +# +# SPDX-License-Identifier: FSFULLR # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). diff --git a/libssh2/configure b/libssh2/configure index e008784f5..a238b1add 100755 --- a/libssh2/configure +++ b/libssh2/configure @@ -663,6 +663,11 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS +LIBSSH2_PC_LIBS +LIBSSH2_PC_REQUIRES +LIBSSH2_PC_LIBS_PRIVATE +HAVE_LIB_STATIC_FALSE +HAVE_LIB_STATIC_TRUE HAVE_WINDRES_FALSE HAVE_WINDRES_TRUE ALLOCA @@ -679,10 +684,9 @@ RUN_SSHD_TESTS_FALSE RUN_SSHD_TESTS_TRUE RUN_DOCKER_TESTS_FALSE RUN_DOCKER_TESTS_TRUE -ENABLE_TESTS_FALSE -ENABLE_TESTS_TRUE +LIBSSH2_CFLAG_EXTRAS CPP -LIBSREQUIRED +LIBSSH2_PC_REQUIRES_PRIVATE LIBZ_PREFIX LTLIBZ LIBZ @@ -765,7 +769,7 @@ build_os build_vendor build_cpu build -LIBSSH2VER +LIBSSH2_VERSION CSCOPE ETAGS CTAGS @@ -862,17 +866,18 @@ with_libgcrypt_prefix with_libmbedcrypto_prefix with_libbcrypt_prefix with_libwolfssl_prefix +enable_ecdsa_wincng with_libz with_libz_prefix enable_clear_memory +enable_werror enable_debug enable_hidden_symbols -enable_tests +enable_deprecated enable_docker_tests enable_sshd_tests enable_examples_build enable_ossfuzzers -enable_werror ' ac_precious_vars='build_alias host_alias @@ -1531,21 +1536,23 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --disable-largefile omit support for large files --disable-rpath do not hardcode runtime library paths + --enable-ecdsa-wincng WinCNG ECDSA support (requires Windows 10 or later) --disable-clear-memory Disable clearing of memory before being freed + --enable-werror Enable compiler warnings as errors + --disable-werror Disable compiler warnings as errors --enable-debug Enable pedantic and debug options --disable-debug Disable debug options --enable-hidden-symbols Hide internal symbols in library --disable-hidden-symbols Leave all symbols with default visibility in library - --disable-tests Disable tests [default=enabled] + (default) + --disable-deprecated Build without deprecated APIs [default=no] --disable-docker-tests Do not run tests requiring Docker --disable-sshd-tests Do not run tests requiring sshd --enable-examples-build Build example applications (this is the default) --disable-examples-build Do not build example applications --enable-ossfuzzers Whether to generate the fuzzers for OSS-Fuzz - --enable-werror Enable compiler warnings as errors - --disable-werror Disable compiler warnings as errors Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -3235,7 +3242,7 @@ if test "x$SED" = "xsed-was-not-found-by-configure"; then printf "%s\n" "$as_me: WARNING: sed was not found, this may ruin your chances to build fine" >&2;} fi -LIBSSH2VER=`$SED -ne 's/^#define LIBSSH2_VERSION *"\(.*\)"/\1/p' ${srcdir}/include/libssh2.h` +LIBSSH2_VERSION=`$SED -ne 's/^#define LIBSSH2_VERSION *"\(.*\)"/\1/p' ${srcdir}/include/libssh2.h` am__api_version='1.16' @@ -3813,13 +3820,14 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking libssh2 version" >&5 printf %s "checking libssh2 version... " >&6; } -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIBSSH2VER" >&5 -printf "%s\n" "$LIBSSH2VER" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIBSSH2_VERSION" >&5 +printf "%s\n" "$LIBSSH2_VERSION" >&6; } -AB_VERSION=$LIBSSH2VER - +# Check for the OS. +# Daniel's note: this should not be necessary and we need to work to +# get this removed. # Make sure we can run config.sub. @@ -3895,44 +3903,6 @@ IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - - - - if test -z "$AB_PACKAGE"; then - AB_PACKAGE=${PACKAGE_NAME:-$PACKAGE} - fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: autobuild project... $AB_PACKAGE" >&5 -printf "%s\n" "$as_me: autobuild project... $AB_PACKAGE" >&6;} - - if test -z "$AB_VERSION"; then - AB_VERSION=${PACKAGE_VERSION:-$VERSION} - fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: autobuild revision... $AB_VERSION" >&5 -printf "%s\n" "$as_me: autobuild revision... $AB_VERSION" >&6;} - - hostname=`hostname` - if test "$hostname"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: autobuild hostname... $hostname" >&5 -printf "%s\n" "$as_me: autobuild hostname... $hostname" >&6;} - fi - - - - date=`date +%Y%m%d-%H%M%S` - if test "$?" != 0; then - date=`date` - fi - if test "$date"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: autobuild timestamp... $date" >&5 -printf "%s\n" "$as_me: autobuild timestamp... $date" >&6;} - fi - - -# Check for the OS. -# Daniel's note: this should not be necessary and we need to work to -# get this removed. - case "$host" in *-mingw*) LIBS="$LIBS -lws2_32" @@ -19114,6 +19084,26 @@ CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS +case $host in + *-*-msys | *-*-cygwin* | *-*-cegcc*) + # These are POSIX-like systems using BSD-like sockets API. + ;; + *) + for ac_header in windows.h +do : + ac_fn_c_check_header_compile "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" +if test "x$ac_cv_header_windows_h" = xyes +then : + printf "%s\n" "#define HAVE_WINDOWS_H 1" >>confdefs.h + have_windows_h=yes +else $as_nop + have_windows_h=no +fi + +done + ;; +esac + # Check whether --enable-largefile was given. if test ${enable_largefile+y} then : @@ -20069,19 +20059,18 @@ printf "%s\n" "$LIBSSL" >&6; } - LDFLAGS="$libssh2_save_LDFLAGS" - if test "$ac_cv_libssl" = "yes"; then : printf "%s\n" "#define LIBSSH2_OPENSSL 1" >>confdefs.h - LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }libssl libcrypto" + LIBSSH2_PC_REQUIRES_PRIVATE="$LIBSSH2_PC_REQUIRES_PRIVATE${LIBSSH2_PC_REQUIRES_PRIVATE:+,}libcrypto" found_crypto="openssl" found_crypto_str="OpenSSL" else CPPFLAGS="$libssh2_save_CPPFLAGS" + LDFLAGS="$libssh2_save_LDFLAGS" fi @@ -20626,17 +20615,17 @@ printf "%s\n" "$LIBGCRYPT" >&6; } - LDFLAGS="$libssh2_save_LDFLAGS" - if test "$ac_cv_libgcrypt" = "yes"; then : printf "%s\n" "#define LIBSSH2_LIBGCRYPT 1" >>confdefs.h + LIBSSH2_PC_REQUIRES_PRIVATE="$LIBSSH2_PC_REQUIRES_PRIVATE${LIBSSH2_PC_REQUIRES_PRIVATE:+,}libgcrypt" found_crypto="libgcrypt" else CPPFLAGS="$libssh2_save_CPPFLAGS" + LDFLAGS="$libssh2_save_LDFLAGS" fi @@ -21181,8 +21170,6 @@ printf "%s\n" "$LIBMBEDCRYPTO" >&6; } - LDFLAGS="$libssh2_save_LDFLAGS" - if test "$ac_cv_libmbedcrypto" = "yes"; then : @@ -21193,6 +21180,7 @@ printf "%s\n" "#define LIBSSH2_MBEDTLS 1" >>confdefs.h else CPPFLAGS="$libssh2_save_CPPFLAGS" + LDFLAGS="$libssh2_save_LDFLAGS" fi @@ -21203,11 +21191,12 @@ fi if test "$use_crypto" = "auto" && test "$found_crypto" = "none" || test "$use_crypto" = "wincng"; then - # Look for Windows Cryptography API: Next Generation + if test "x$have_windows_h" = "xyes"; then + # Look for Windows Cryptography API: Next Generation - LIBS="$LIBS -lcrypt32" + LIBS="$LIBS -lcrypt32" - # Check necessary for old-MinGW + # Check necessary for old-MinGW libssh2_save_CPPFLAGS="$CPPFLAGS" libssh2_save_LDFLAGS="$LDFLAGS" @@ -21697,8 +21686,8 @@ else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - #include + #include + #include int main (void) @@ -21745,20 +21734,20 @@ printf "%s\n" "$LIBBCRYPT" >&6; } - LDFLAGS="$libssh2_save_LDFLAGS" - if test "$ac_cv_libbcrypt" = "yes"; then : printf "%s\n" "#define LIBSSH2_WINCNG 1" >>confdefs.h - found_crypto="wincng" - found_crypto_str="Windows Cryptography API: Next Generation" + found_crypto="wincng" + found_crypto_str="Windows Cryptography API: Next Generation" else CPPFLAGS="$libssh2_save_CPPFLAGS" + LDFLAGS="$libssh2_save_LDFLAGS" fi + fi test "$found_crypto" = "none" && crypto_errors="${crypto_errors}No wincng crypto library found! @@ -21767,11 +21756,6 @@ fi if test "$use_crypto" = "auto" && test "$found_crypto" = "none" || test "$use_crypto" = "wolfssl"; then - if test "${with_libwolfssl_prefix+set}" = set; then - CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I${with_libwolfssl_prefix}/include/wolfssl" - else - as_fn_error $? "When using wolfSSL, must specify prefix with --with-libwolfssl-prefix in order to find OpenSSL compatibility headers." "$LINENO" 5 - fi libssh2_save_CPPFLAGS="$CPPFLAGS" libssh2_save_LDFLAGS="$LDFLAGS" @@ -22306,18 +22290,17 @@ printf "%s\n" "$LIBWOLFSSL" >&6; } - LDFLAGS="$libssh2_save_LDFLAGS" - if test "$ac_cv_libwolfssl" = "yes"; then : printf "%s\n" "#define LIBSSH2_WOLFSSL 1" >>confdefs.h - LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }libwolfssl" + LIBSSH2_PC_REQUIRES_PRIVATE="$LIBSSH2_PC_REQUIRES_PRIVATE${LIBSSH2_PC_REQUIRES_PRIVATE:+,}wolfssl" found_crypto="wolfssl" else CPPFLAGS="$libssh2_save_CPPFLAGS" + LDFLAGS="$libssh2_save_LDFLAGS" fi @@ -22328,10 +22311,10 @@ fi ;; yes|"") - crypto_errors="No crypto backend specified!" + crypto_errors="No crypto backend specified." ;; *) - crypto_errors="Unknown crypto backend '${use_crypto}' specified!" + crypto_errors="Unknown crypto backend '${use_crypto}' specified." ;; esac @@ -22346,6 +22329,21 @@ else test "$found_crypto_str" = "" && found_crypto_str="$found_crypto" fi +# ECDSA support with WinCNG +# Check whether --enable-ecdsa-wincng was given. +if test ${enable_ecdsa_wincng+y} +then : + enableval=$enable_ecdsa_wincng; wincng_ecdsa=$enableval +fi + +if test "$wincng_ecdsa" = yes; then + +printf "%s\n" "#define LIBSSH2_ECDSA_WINCNG 1" >>confdefs.h + +else + wincng_ecdsa=no +fi + # libz @@ -22892,7 +22890,7 @@ printf "%s\n" "$LIBZ" >&6; } printf "%s\n" "$as_me: Cannot find libz, disabling compression" >&6;} found_libz="disabled; no libz found" else - libz_errors="No libz found! + libz_errors="No libz found. Try --with-libz-prefix=PATH if you know that you have it." { printf "%s\n" "$as_me:${as_lineno-$LINENO}: ERROR: $libz_errors" >&5 printf "%s\n" "$as_me: ERROR: $libz_errors" >&6;} @@ -22901,7 +22899,7 @@ printf "%s\n" "$as_me: ERROR: $libz_errors" >&6;} printf "%s\n" "#define LIBSSH2_HAVE_ZLIB 1" >>confdefs.h - LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }zlib" + LIBSSH2_PC_REQUIRES_PRIVATE="$LIBSSH2_PC_REQUIRES_PRIVATE${LIBSSH2_PC_REQUIRES_PRIVATE:+,}zlib" found_libz="yes" fi fi @@ -22926,6 +22924,37 @@ else enable_clear_memory=yes fi +LIBSSH2_CFLAG_EXTRAS="" + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable compiler warnings as errors" >&5 +printf %s "checking whether to enable compiler warnings as errors... " >&6; } + OPT_COMPILER_WERROR="default" + # Check whether --enable-werror was given. +if test ${enable_werror+y} +then : + enableval=$enable_werror; OPT_COMPILER_WERROR=$enableval +fi + + case "$OPT_COMPILER_WERROR" in + no) + want_werror="no" + ;; + default) + want_werror="no" + ;; + *) + want_werror="yes" + ;; + esac + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $want_werror" >&5 +printf "%s\n" "$want_werror" >&6; } + + if test X"$want_werror" = Xyes; then + LIBSSH2_CFLAG_EXTRAS="$LIBSSH2_CFLAG_EXTRAS -Werror" + fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable pedantic and debug compiler options" >&5 printf %s "checking whether to enable pedantic and debug compiler options... " >&6; } ac_ext=c @@ -23153,7 +23182,7 @@ printf "%s\n" "yes" >&6; } CFLAGS="$CFLAGS -g" - if test "z$CLANG" = "z"; then + if test "z$CLANG" = "z"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler is clang" >&5 printf %s "checking if compiler is clang... " >&6; } @@ -23261,18 +23290,6 @@ printf "%s\n" "yes" >&6; } printf "%s\n" "no" >&6; } compiler_id="CLANG" fi - fullclangver=`$CC -v 2>&1 | grep version` - clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \([0-9]*\.[0-9]*\).*)/\1/'` - if test -z "$clangver"; then - if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then - clangver="3.7" - else - clangver=`echo $fullclangver | "$SED" 's/.*version \([0-9]*\.[0-9]*\).*/\1/'` - fi - fi - clangvhi=`echo $clangver | cut -d . -f1` - clangvlo=`echo $clangver | cut -d . -f2` - compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null` flags_dbg_yes="-g" flags_opt_all="-O -O0 -O1 -O2 -Os -O3 -O4" flags_opt_yes="-O2" @@ -23282,64 +23299,88 @@ printf "%s\n" "no" >&6; } printf "%s\n" "no" >&6; } fi - if test "z$compiler_id" = "zCLANG"; then - CLANG="yes" - else - CLANG="no" - fi + if test "z$compiler_id" = "zCLANG"; then + CLANG="yes" + else + CLANG="no" fi - if test "z$ICC" = "z"; then + fi + if test "z$ICC" = "z"; then - ICC="no" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for icc in use" >&5 + ICC="no" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for icc in use" >&5 printf %s "checking for icc in use... " >&6; } - if test "$GCC" = "yes"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "$GCC" = "yes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ __INTEL_COMPILER _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "^__INTEL_COMPILER" >/dev/null 2>&1 then : - ICC="no" + ICC="no" else $as_nop - ICC="yes" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + ICC="yes" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi rm -rf conftest* - fi - if test "$ICC" = "no"; then - # this is not ICC - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + fi + if test "$ICC" = "no"; then + # this is not ICC + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - fi + fi - fi + fi - if test "$CLANG" = "yes"; then + if test "$CLANG" = "yes"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking clang version" >&5 -printf %s "checking clang version... " >&6; } - fullclangver=`$CC -v 2>&1 | grep version` - clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \([0-9]*\.[0-9]*\).*)/\1/'` - if test -z "$clangver"; then - if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then - clangver="3.7" - else - clangver=`echo $fullclangver | "$SED" 's/.*version \([0-9]*\.[0-9]*\).*/\1/'` - fi - fi - clangvhi=`echo $clangver | cut -d . -f1` - clangvlo=`echo $clangver | cut -d . -f2` - compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $compiler_num" >&5 -printf "%s\n" "$compiler_num" >&6; } + # indentation to match curl's m4/curl-compilers.m4 - WARN="-pedantic" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler version" >&5 +printf %s "checking compiler version... " >&6; } + fullclangver=`$CC -v 2>&1 | grep version` + if echo $fullclangver | grep 'Apple' >/dev/null; then + appleclang=1 + else + appleclang=0 + fi + clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \([0-9]*\.[0-9]*\).*)/\1/'` + if test -z "$clangver"; then + clangver=`echo $fullclangver | "$SED" 's/.*version \([0-9]*\.[0-9]*\).*/\1/'` + oldapple=0 + else + oldapple=1 + fi + clangvhi=`echo $clangver | cut -d . -f1` + clangvlo=`echo $clangver | cut -d . -f2` + compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null` + if test "$appleclang" = '1' && test "$oldapple" = '0'; then + if test "$compiler_num" -ge '1300'; then compiler_num='1200' + elif test "$compiler_num" -ge '1205'; then compiler_num='1101' + elif test "$compiler_num" -ge '1204'; then compiler_num='1000' + elif test "$compiler_num" -ge '1107'; then compiler_num='900' + elif test "$compiler_num" -ge '1103'; then compiler_num='800' + elif test "$compiler_num" -ge '1003'; then compiler_num='700' + elif test "$compiler_num" -ge '1001'; then compiler_num='600' + elif test "$compiler_num" -ge '904'; then compiler_num='500' + elif test "$compiler_num" -ge '902'; then compiler_num='400' + elif test "$compiler_num" -ge '803'; then compiler_num='309' + elif test "$compiler_num" -ge '703'; then compiler_num='308' + else compiler_num='307' + fi + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: clang '$compiler_num' (raw: '$fullclangver' / '$clangver')" >&5 +printf "%s\n" "clang '$compiler_num' (raw: '$fullclangver' / '$clangver')" >&6; } + + tmp_CFLAGS="-pedantic" + if test "$want_werror" = "yes"; then + LIBSSH2_CFLAG_EXTRAS="$LIBSSH2_CFLAG_EXTRAS -pedantic-errors" + fi ac_var_added_warnings="" for warning in all extra; do @@ -23357,8 +23398,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23377,8 +23418,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23397,8 +23438,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23417,8 +23458,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23437,8 +23478,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23457,10 +23498,10 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - WARN="$WARN -Wno-long-long" + tmp_CFLAGS="$tmp_CFLAGS -Wno-long-long" ac_var_added_warnings="" for warning in float-equal; do @@ -23478,12 +23519,12 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" - for warning in no-multichar sign-compare; do + for warning in sign-compare; do ac_var_match_word="no" for word1 in $CFLAGS; do @@ -23498,9 +23539,10 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + tmp_CFLAGS="$tmp_CFLAGS -Wno-multichar" ac_var_added_warnings="" for warning in undef; do @@ -23518,10 +23560,10 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - WARN="$WARN -Wno-format-nonliteral" + tmp_CFLAGS="$tmp_CFLAGS -Wno-format-nonliteral" ac_var_added_warnings="" for warning in endif-labels strict-prototypes; do @@ -23539,8 +23581,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23559,8 +23601,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23579,10 +23621,10 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - WARN="$WARN -Wno-system-headers" + tmp_CFLAGS="$tmp_CFLAGS -Wno-system-headers" ac_var_added_warnings="" for warning in shorten-64-to-32; do @@ -23600,11 +23642,11 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - # - if test "$compiler_num" -ge "101"; then + # + if test "$compiler_num" -ge "101"; then ac_var_added_warnings="" for warning in unused; do @@ -23622,15 +23664,15 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi - # - if test "$compiler_num" -ge "208"; then + fi + # + if test "$compiler_num" -ge "207"; then ac_var_added_warnings="" - for warning in vla; do + for warning in address; do ac_var_match_word="no" for word1 in $CFLAGS; do @@ -23645,15 +23687,12 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi - # - if test "$compiler_num" -ge "209"; then ac_var_added_warnings="" - for warning in shift-sign-overflow; do + for warning in attributes; do ac_var_match_word="no" for word1 in $CFLAGS; do @@ -23668,12 +23707,9 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi - # - if test "$compiler_num" -ge "300"; then ac_var_added_warnings="" for warning in bad-function-cast; do @@ -23691,8 +23727,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23711,8 +23747,28 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in div-by-zero format-security; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23731,12 +23787,12 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" - for warning in ignored-qualifiers; do + for warning in missing-field-initializers; do ac_var_match_word="no" for word1 in $CFLAGS; do @@ -23751,10 +23807,71 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + ac_var_added_warnings="" + for warning in missing-noreturn; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in old-style-definition; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in redundant-decls; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case + ac_var_added_warnings="" for warning in type-limits; do @@ -23771,12 +23888,13 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + if test "x$have_windows_h" != "xyes"; then ac_var_added_warnings="" - for warning in no-sign-conversion; do + for warning in unused-macros; do ac_var_match_word="no" for word1 in $CFLAGS; do @@ -23791,12 +23909,145 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + # Seen to clash with libtool-generated stub code + fi + ac_var_added_warnings="" + for warning in unreachable-code unused-parameter; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" fi - # - if test "$compiler_num" -ge "302"; then + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "208"; then + + ac_var_added_warnings="" + for warning in ignored-qualifiers; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in vla; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "209"; then + + ac_var_added_warnings="" + for warning in sign-conversion; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + tmp_CFLAGS="$tmp_CFLAGS -Wno-error=sign-conversion" # FIXME + + ac_var_added_warnings="" + for warning in shift-sign-overflow; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs + fi + # + if test "$compiler_num" -ge "300"; then + + ac_var_added_warnings="" + for warning in language-extension-token; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + tmp_CFLAGS="$tmp_CFLAGS -Wformat=2" + fi + # + if test "$compiler_num" -ge "302"; then ac_var_added_warnings="" for warning in enum-conversion; do @@ -23814,13 +24065,33 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - case $host_os in - cygwin* | mingw*) - ;; - *) + + ac_var_added_warnings="" + for warning in sometimes-uninitialized; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + case $host_os in + cygwin* | mingw*) + ;; + *) ac_var_added_warnings="" for warning in missing-variable-declarations; do @@ -23838,14 +24109,34 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - ;; - esac + ;; + esac + fi + # + if test "$compiler_num" -ge "304"; then + + ac_var_added_warnings="" + for warning in header-guard; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" fi - # - if test "$compiler_num" -ge "304"; then + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + ac_var_added_warnings="" for warning in unused-const-variable; do @@ -23863,12 +24154,55 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + fi + # + if test "$compiler_num" -ge "305"; then + + ac_var_added_warnings="" + for warning in pragmas; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" fi - # - if test "$compiler_num" -ge "306"; then + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in unreachable-code-break; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "306"; then ac_var_added_warnings="" for warning in double-promotion; do @@ -23886,12 +24220,12 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi - # - if test "$compiler_num" -ge "309"; then + fi + # + if test "$compiler_num" -ge "309"; then ac_var_added_warnings="" for warning in comma; do @@ -23909,16 +24243,16 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - # avoid the varargs warning, fixed in 4.0 - # https://bugs.llvm.org/show_bug.cgi?id=29140 - if test "$compiler_num" -lt "400"; then - WARN="$WARN -Wno-varargs" - fi - fi - if test "$compiler_num" -ge "700"; then + # avoid the varargs warning, fixed in 4.0 + # https://bugs.llvm.org/show_bug.cgi?id=29140 + if test "$compiler_num" -lt "400"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-varargs" + fi + fi + if test "$compiler_num" -ge "700"; then ac_var_added_warnings="" for warning in assign-enum; do @@ -23936,8 +24270,8 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -23956,71 +24290,52 @@ printf "%s\n" "$compiler_num" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi + fi + if test "$compiler_num" -ge "1000"; then + tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough" # we have silencing markup for clang 10.0 and above only + fi - CFLAGS="$CFLAGS $WARN" + CFLAGS="$CFLAGS $tmp_CFLAGS" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Added this set of compiler options: $WARN" >&5 -printf "%s\n" "$as_me: Added this set of compiler options: $WARN" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Added this set of compiler options: $tmp_CFLAGS" >&5 +printf "%s\n" "$as_me: Added this set of compiler options: $tmp_CFLAGS" >&6;} - elif test "$GCC" = "yes"; then + elif test "$GCC" = "yes"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking gcc version" >&5 -printf %s "checking gcc version... " >&6; } - gccver=`$CC -dumpversion` - num1=`echo $gccver | cut -d . -f1` - num2=`echo $gccver | cut -d . -f2` - compiler_num=`(expr $num1 "*" 100 + $num2) 2>/dev/null` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gccver" >&5 -printf "%s\n" "$gccver" >&6; } + # indentation to match curl's m4/curl-compilers.m4 - if test "$ICC" = "yes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler version" >&5 +printf %s "checking compiler version... " >&6; } + # strip '-suffix' parts, e.g. Ubuntu Windows cross-gcc returns '10-win32' + gccver=`$CC -dumpversion | sed -E 's/-.+$//'` + gccvhi=`echo $gccver | cut -d . -f1` + if echo $gccver | grep -F "." >/dev/null; then + gccvlo=`echo $gccver | cut -d . -f2` + else + gccvlo="0" + fi + compiler_num=`(expr $gccvhi "*" 100 + $gccvlo) 2>/dev/null` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: gcc '$compiler_num' (raw: '$gccver')" >&5 +printf "%s\n" "gcc '$compiler_num' (raw: '$gccver')" >&6; } + + if test "$ICC" = "yes"; then - WARN="-wd279,269,981,1418,1419" + tmp_CFLAGS="-wd279,269,981,1418,1419" - if test "$compiler_num" -gt "600"; then - WARN="-Wall $WARN" - fi - else WARN="-W -Wall -Wwrite-strings -pedantic -Wpointer-arith -Wnested-externs -Winline -Wmissing-prototypes" - - if test "$compiler_num" -ge "207"; then - WARN="$WARN -Wmissing-declarations" - fi - - if test "$compiler_num" -gt "295"; then - WARN="$WARN -Wbad-function-cast -Wundef -Wno-long-long -Wno-multichar -Wshadow -Wsign-compare -Wunused" - fi - - if test "$compiler_num" -ge "296"; then - WARN="$WARN -Wfloat-equal" - fi - - if test "$compiler_num" -gt "296"; then - WARN="$WARN -Wno-format-nonliteral" - fi - - - if test "$compiler_num" -ge "303"; then - WARN="$WARN -Wendif-labels -Wstrict-prototypes" - fi - - if test "$compiler_num" -ge "304"; then - # try these on gcc 3.4 - WARN="$WARN -Wdeclaration-after-statement" - fi - - if test "$compiler_num" -ge "400"; then - WARN="$WARN -Wstrict-aliasing=3" - fi - # - if test "$compiler_num" -ge "401"; then + if test "$compiler_num" -gt "600"; then + tmp_CFLAGS="-Wall $tmp_CFLAGS" + fi + else tmp_CFLAGS="-pedantic" + if test "$want_werror" = "yes"; then + LIBSSH2_CFLAG_EXTRAS="$LIBSSH2_CFLAG_EXTRAS -pedantic-errors" + fi ac_var_added_warnings="" - for warning in no-system-headers; do + for warning in all; do ac_var_match_word="no" for word1 in $CFLAGS; do @@ -24035,12 +24350,446 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi - # - if test "$compiler_num" -ge "402"; then + tmp_CFLAGS="$tmp_CFLAGS -W" + + ac_var_added_warnings="" + for warning in pointer-arith write-strings; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + # + if test "$compiler_num" -ge "207"; then + + ac_var_added_warnings="" + for warning in inline nested-externs; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in missing-declarations; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in missing-prototypes; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "295"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-long-long" + + ac_var_added_warnings="" + for warning in bad-function-cast; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "296"; then + + ac_var_added_warnings="" + for warning in float-equal; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + tmp_CFLAGS="$tmp_CFLAGS -Wno-multichar" + + ac_var_added_warnings="" + for warning in sign-compare; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in undef; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "297"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-format-nonliteral" + fi + # + if test "$compiler_num" -ge "300"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-system-headers" + + ac_var_added_warnings="" + for warning in unused shadow; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "303"; then + + ac_var_added_warnings="" + for warning in endif-labels strict-prototypes; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "304"; then + + ac_var_added_warnings="" + for warning in declaration-after-statement; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in old-style-definition; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "400"; then + tmp_CFLAGS="$tmp_CFLAGS -Wstrict-aliasing=3" + fi + # + if test "$compiler_num" -ge "401"; then + + ac_var_added_warnings="" + for warning in attributes; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in div-by-zero format-security; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in missing-field-initializers; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in missing-noreturn; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in unreachable-code unused-parameter; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs + + ac_var_added_warnings="" + for warning in pragmas; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + + ac_var_added_warnings="" + for warning in redundant-decls; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case + + ac_var_added_warnings="" + for warning in unused-macros; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "402"; then ac_var_added_warnings="" for warning in cast-align; do @@ -24058,12 +24807,32 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + fi + # + if test "$compiler_num" -ge "403"; then + + ac_var_added_warnings="" + for warning in address; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi - # - if test "$compiler_num" -ge "403"; then ac_var_added_warnings="" for warning in type-limits old-style-declaration; do @@ -24081,8 +24850,8 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -24101,12 +24870,12 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" - for warning in ignored-qualifiers; do + for warning in clobbered ignored-qualifiers; do ac_var_match_word="no" for word1 in $CFLAGS; do @@ -24121,12 +24890,12 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" - for warning in conversion; do + for warning in conversion trampolines; do ac_var_match_word="no" for word1 in $CFLAGS; do @@ -24141,10 +24910,30 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - WARN="$WARN -Wno-sign-conversion" + + ac_var_added_warnings="" + for warning in sign-conversion; do + + ac_var_match_word="no" + for word1 in $CFLAGS; do + for word2 in -Wno-$warning -W$warning; do + if test "$word1" = "$word2"; then + ac_var_match_word="yes" + fi + done + done + + if test "$ac_var_match_word" = "no"; then + ac_var_added_warnings="$ac_var_added_warnings -W$warning" + fi + done + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS + + tmp_CFLAGS="$tmp_CFLAGS -Wno-error=sign-conversion" # FIXME ac_var_added_warnings="" for warning in vla; do @@ -24162,21 +24951,21 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - WARN="$WARN -ftree-vrp" - fi - # - if test "$compiler_num" -ge "405"; then - case $host_os in - mingw*) - WARN="$WARN -Wno-pedantic-ms-format" - ;; - esac - fi - # - if test "$compiler_num" -ge "406"; then + tmp_CFLAGS="$tmp_CFLAGS -ftree-vrp" + fi + # + if test "$compiler_num" -ge "405"; then + case $host_os in + mingw*) + tmp_CFLAGS="$tmp_CFLAGS -Wno-pedantic-ms-format" + ;; + esac + fi + # + if test "$compiler_num" -ge "406"; then ac_var_added_warnings="" for warning in double-promotion; do @@ -24194,20 +24983,20 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi - # - if test "$compiler_num" -ge "408"; then - WARN="$WARN -Wformat=2" - fi - # - if test "$compiler_num" -ge "500"; then - WARN="$WARN -Warray-bounds=2" - fi - # - if test "$compiler_num" -ge "600"; then + fi + # + if test "$compiler_num" -ge "408"; then + tmp_CFLAGS="$tmp_CFLAGS -Wformat=2" + fi + # + if test "$compiler_num" -ge "500"; then + tmp_CFLAGS="$tmp_CFLAGS -Warray-bounds=2" + fi + # + if test "$compiler_num" -ge "600"; then ac_var_added_warnings="" for warning in shift-negative-value; do @@ -24225,10 +25014,10 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - WARN="$WARN -Wshift-overflow=2" + tmp_CFLAGS="$tmp_CFLAGS -Wshift-overflow=2" ac_var_added_warnings="" for warning in null-dereference; do @@ -24246,10 +25035,10 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - WARN="$WARN -fdelete-null-pointer-checks" + tmp_CFLAGS="$tmp_CFLAGS -fdelete-null-pointer-checks" ac_var_added_warnings="" for warning in duplicated-cond; do @@ -24267,8 +25056,8 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -24287,12 +25076,12 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi - # - if test "$compiler_num" -ge "700"; then + fi + # + if test "$compiler_num" -ge "700"; then ac_var_added_warnings="" for warning in duplicated-branches; do @@ -24310,8 +25099,8 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -24330,8 +25119,8 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -24350,14 +25139,15 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - WARN="$WARN -Wformat-overflow=2" - WARN="$WARN -Wformat-truncation=1" - fi - # - if test "$compiler_num" -ge "1000"; then + tmp_CFLAGS="$tmp_CFLAGS -Wformat-overflow=2" + tmp_CFLAGS="$tmp_CFLAGS -Wformat-truncation=2" + tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough" + fi + # + if test "$compiler_num" -ge "1000"; then ac_var_added_warnings="" for warning in arith-conversion; do @@ -24375,8 +25165,8 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS ac_var_added_warnings="" @@ -24395,42 +25185,42 @@ printf "%s\n" "$gccver" >&6; } ac_var_added_warnings="$ac_var_added_warnings -W$warning" fi done - WARN="$WARN $ac_var_added_warnings" - squeeze WARN + tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings" + squeeze tmp_CFLAGS - fi + fi - for flag in $CPPFLAGS; do - case "$flag" in - -I*) - add=`echo $flag | sed 's/^-I/-isystem /g'` - WARN="$WARN $add" - ;; - esac - done - - fi - CFLAGS="$CFLAGS $WARN" - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Added this set of compiler options: $WARN" >&5 -printf "%s\n" "$as_me: Added this set of compiler options: $WARN" >&6;} - - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Added no extra compiler options" >&5 -printf "%s\n" "$as_me: Added no extra compiler options" >&6;} + for flag in $CPPFLAGS; do + case "$flag" in + -I*) + add=`echo $flag | sed 's/^-I/-isystem /g'` + tmp_CFLAGS="$tmp_CFLAGS $add" + ;; + esac + done fi - NEWFLAGS="" - for flag in $CFLAGS; do - case "$flag" in - -O*) - ;; - *) - NEWFLAGS="$NEWFLAGS $flag" - ;; - esac - done - CFLAGS=$NEWFLAGS + CFLAGS="$CFLAGS $tmp_CFLAGS" + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Added this set of compiler options: $tmp_CFLAGS" >&5 +printf "%s\n" "$as_me: Added this set of compiler options: $tmp_CFLAGS" >&6;} + + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Added no extra compiler options" >&5 +printf "%s\n" "$as_me: Added no extra compiler options" >&6;} + + fi + NEWFLAGS="" + for flag in $CFLAGS; do + case "$flag" in + -O*) + ;; + *) + NEWFLAGS="$NEWFLAGS $flag" + ;; + esac + done + CFLAGS=$NEWFLAGS ;; @@ -24444,6 +25234,8 @@ printf "%s\n" "no" >&6; } fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable hidden symbols in the library" >&5 printf %s "checking whether to enable hidden symbols in the library... " >&6; } # Check whether --enable-hidden-symbols was given. @@ -24492,25 +25284,17 @@ printf "%s\n" "no" >&6; } fi -# Build tests? -# Check whether --enable-tests was given. -if test ${enable_tests+y} +# Check whether --enable-deprecated was given. +if test ${enable_deprecated+y} then : - enableval=$enable_tests; - if ! test "x${enable_tests}" = "xyes"; then - enable_tests="no" - fi - + enableval=$enable_deprecated; case "$enableval" in + *) + with_deprecated="no" + CPPFLAGS="$CPPFLAGS -DLIBSSH2_NO_DEPRECATED" + ;; + esac else $as_nop - enable_tests="yes" -fi - - if test "x$enable_tests" = xyes; then - ENABLE_TESTS_TRUE= - ENABLE_TESTS_FALSE='#' -else - ENABLE_TESTS_TRUE='#' - ENABLE_TESTS_FALSE= + with_deprecated="yes" fi @@ -24643,12 +25427,6 @@ if test "x$ac_cv_header_unistd_h" = xyes then : printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_param_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_PARAM_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "sys/uio.h" "ac_cv_header_sys_uio_h" "$ac_includes_default" if test "x$ac_cv_header_sys_uio_h" = xyes @@ -24703,26 +25481,6 @@ then : fi -case $host in - *-*-cygwin* | *-*-cegcc*) - # These are POSIX-like systems using BSD-like sockets API. - ;; - *) - for ac_header in windows.h -do : - ac_fn_c_check_header_compile "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" -if test "x$ac_cv_header_windows_h" = xyes -then : - printf "%s\n" "#define HAVE_WINDOWS_H 1" >>confdefs.h - have_windows_h=yes -else $as_nop - have_windows_h=no -fi - -done - ;; -esac - case $host in *darwin*|*interix*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: poll use is disabled on this platform" >&5 @@ -25293,7 +26051,7 @@ printf "%s\n" "$as_me: ERROR: ${crypto_errors}" >&6;} fi if test $missing_required_deps = 1; then - as_fn_error $? "Required dependencies are missing!" "$LINENO" 5 + as_fn_error $? "Required dependencies are missing." "$LINENO" 5 fi if test "x$have_windows_h" = "xyes" && test "x${enable_shared}" = "xyes" && test -n "${RC}"; then @@ -25305,35 +26063,16 @@ else fi -# Configure parameters - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable compiler warnings as errors" >&5 -printf %s "checking whether to enable compiler warnings as errors... " >&6; } - OPT_COMPILER_WERROR="default" - # Check whether --enable-werror was given. -if test ${enable_werror+y} -then : - enableval=$enable_werror; OPT_COMPILER_WERROR=$enableval + if test "x$enable_static" != "xno"; then + HAVE_LIB_STATIC_TRUE= + HAVE_LIB_STATIC_FALSE='#' +else + HAVE_LIB_STATIC_TRUE='#' + HAVE_LIB_STATIC_FALSE= fi - case "$OPT_COMPILER_WERROR" in - no) - want_werror="no" - ;; - default) - want_werror="no" - ;; - *) - want_werror="yes" - ;; - esac - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $want_werror" >&5 -printf "%s\n" "$want_werror" >&6; } - - if test X"$want_werror" = Xyes; then - CFLAGS="$CFLAGS -Werror" - fi +# Configure parameters # Append crypto lib if test "$found_crypto" = "openssl"; then @@ -25348,6 +26087,21 @@ elif test "$found_crypto" = "mbedtls"; then LIBS="${LIBS} ${LTLIBMBEDCRYPTO}" fi +LIBS="${LIBS} ${LTLIBZ}" + +LIBSSH2_PC_LIBS_PRIVATE=$LIBS + + +if test "x$enable_shared" = "xyes"; then + LIBSSH2_PC_REQUIRES= + LIBSSH2_PC_LIBS= +else + LIBSSH2_PC_REQUIRES=$LIBSSH2_PC_REQUIRES_PRIVATE + LIBSSH2_PC_LIBS=$LIBSSH2_PC_LIBS_PRIVATE +fi + + + ac_config_files="$ac_config_files Makefile src/Makefile libssh2.pc" cat >confcache <<\_ACEOF @@ -25500,10 +26254,6 @@ if test -z "${SSHD_TRUE}" && test -z "${SSHD_FALSE}"; then Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_TESTS_TRUE}" && test -z "${ENABLE_TESTS_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_TESTS\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${RUN_DOCKER_TESTS_TRUE}" && test -z "${RUN_DOCKER_TESTS_FALSE}"; then as_fn_error $? "conditional \"RUN_DOCKER_TESTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25532,6 +26282,10 @@ if test -z "${HAVE_WINDRES_TRUE}" && test -z "${HAVE_WINDRES_FALSE}"; then as_fn_error $? "conditional \"HAVE_WINDRES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${HAVE_LIB_STATIC_TRUE}" && test -z "${HAVE_LIB_STATIC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LIB_STATIC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 @@ -28200,15 +28954,17 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: summary of build options: - version: ${LIBSSH2VER} + version: ${LIBSSH2_VERSION} Host type: ${host} Install prefix: ${prefix} Compiler: ${CC} Compiler flags: ${CFLAGS} Library types: Shared=${enable_shared}, Static=${enable_static} Crypto library: ${found_crypto_str} + WinCNG ECDSA: $wincng_ecdsa zlib compression: ${found_libz} Clear memory: $enable_clear_memory + Deprecated APIs: $with_deprecated Debug build: $enable_debug Build examples: $build_examples Run Docker tests: $run_docker_tests @@ -28217,15 +28973,17 @@ fi " >&5 printf "%s\n" "$as_me: summary of build options: - version: ${LIBSSH2VER} + version: ${LIBSSH2_VERSION} Host type: ${host} Install prefix: ${prefix} Compiler: ${CC} Compiler flags: ${CFLAGS} Library types: Shared=${enable_shared}, Static=${enable_static} Crypto library: ${found_crypto_str} + WinCNG ECDSA: $wincng_ecdsa zlib compression: ${found_libz} Clear memory: $enable_clear_memory + Deprecated APIs: $with_deprecated Debug build: $enable_debug Build examples: $build_examples Run Docker tests: $run_docker_tests diff --git a/libssh2/configure.ac b/libssh2/configure.ac index b34757f00..1cd896c48 100644 --- a/libssh2/configure.ac +++ b/libssh2/configure.ac @@ -1,3 +1,8 @@ +# Copyright (C) The libssh2 project and its contributors. +# +# SPDX-License-Identifier: BSD-3-Clause +# + # AC_PREREQ(2.59) AC_INIT([libssh2],[-],[libssh2-devel@lists.haxx.se]) AC_CONFIG_MACRO_DIR([m4]) @@ -17,16 +22,12 @@ if test "x$SED" = "xsed-was-not-found-by-configure"; then fi dnl figure out the libssh2 version -LIBSSH2VER=`$SED -ne 's/^#define LIBSSH2_VERSION *"\(.*\)"/\1/p' ${srcdir}/include/libssh2.h` +LIBSSH2_VERSION=`$SED -ne 's/^#define LIBSSH2_VERSION *"\(.*\)"/\1/p' ${srcdir}/include/libssh2.h` AM_INIT_AUTOMAKE AC_MSG_CHECKING([libssh2 version]) -AC_MSG_RESULT($LIBSSH2VER) +AC_MSG_RESULT($LIBSSH2_VERSION) -AC_SUBST(LIBSSH2VER) - -AB_VERSION=$LIBSSH2VER - -AB_INIT +AC_SUBST(LIBSSH2_VERSION) # Check for the OS. # Daniel's note: this should not be necessary and we need to work to @@ -78,6 +79,16 @@ AC_C_BIGENDIAN LT_LANG([Windows Resource]) +dnl check for windows.h +case $host in + *-*-msys | *-*-cygwin* | *-*-cegcc*) + # These are POSIX-like systems using BSD-like sockets API. + ;; + *) + AC_CHECK_HEADERS([windows.h], [have_windows_h=yes], [have_windows_h=no]) + ;; +esac + dnl check for how to do large files AC_SYS_LARGEFILE @@ -105,10 +116,10 @@ case "${use_crypto}" in m4_set_map([crypto_backends], [LIBSSH2_CHECK_CRYPTO]) ;; yes|"") - crypto_errors="No crypto backend specified!" + crypto_errors="No crypto backend specified." ;; *) - crypto_errors="Unknown crypto backend '${use_crypto}' specified!" + crypto_errors="Unknown crypto backend '${use_crypto}' specified." ;; esac @@ -122,6 +133,17 @@ else test "$found_crypto_str" = "" && found_crypto_str="$found_crypto" fi +# ECDSA support with WinCNG +AC_ARG_ENABLE(ecdsa-wincng, + AS_HELP_STRING([--enable-ecdsa-wincng], + WinCNG ECDSA support (requires Windows 10 or later)), + [wincng_ecdsa=$enableval]) +if test "$wincng_ecdsa" = yes; then + AC_DEFINE(LIBSSH2_ECDSA_WINCNG, 1, [Enable WinCNG ECDSA support]) +else + wincng_ecdsa=no +fi + # libz AC_ARG_WITH([libz], @@ -139,18 +161,18 @@ if test "$use_libz" != no; then AC_MSG_NOTICE([Cannot find libz, disabling compression]) found_libz="disabled; no libz found" else - libz_errors="No libz found! + libz_errors="No libz found. Try --with-libz-prefix=PATH if you know that you have it." AS_MESSAGE([ERROR: $libz_errors]) fi else AC_DEFINE(LIBSSH2_HAVE_ZLIB, 1, [Compile in zlib support]) - LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }zlib" + LIBSSH2_PC_REQUIRES_PRIVATE="$LIBSSH2_PC_REQUIRES_PRIVATE${LIBSSH2_PC_REQUIRES_PRIVATE:+,}zlib" found_libz="yes" fi fi -AC_SUBST(LIBSREQUIRED) +AC_SUBST(LIBSSH2_PC_REQUIRES_PRIVATE) # # Optional Settings @@ -165,6 +187,10 @@ else enable_clear_memory=yes fi +LIBSSH2_CFLAG_EXTRAS="" + +LIBSSH2_CHECK_OPTION_WERROR + dnl ************************************************************ dnl option to switch on compiler debug options dnl @@ -192,6 +218,8 @@ AS_HELP_STRING([--disable-debug],[Disable debug options]), AC_MSG_RESULT(no) ) +AC_SUBST(LIBSSH2_CFLAG_EXTRAS) + dnl ************************************************************ dnl Enable hiding of internal symbols in library to reduce its size and dnl speed dynamic linking of applications. This currently is only supported @@ -200,7 +228,7 @@ dnl AC_MSG_CHECKING([whether to enable hidden symbols in the library]) AC_ARG_ENABLE(hidden-symbols, AS_HELP_STRING([--enable-hidden-symbols],[Hide internal symbols in library]) -AS_HELP_STRING([--disable-hidden-symbols],[Leave all symbols with default visibility in library]), +AS_HELP_STRING([--disable-hidden-symbols],[Leave all symbols with default visibility in library (default)]), [ case "$enableval" in no) AC_MSG_RESULT(no) @@ -231,16 +259,16 @@ AS_HELP_STRING([--disable-hidden-symbols],[Leave all symbols with default visibi AC_MSG_RESULT(no) ) -# Build tests? -AC_ARG_ENABLE([tests], - [AS_HELP_STRING([--disable-tests], [Disable tests @<:@default=enabled@:>@])], - [ - if ! test "x${enable_tests}" = "xyes"; then - enable_tests="no" - fi - ], - [enable_tests="yes"]) -AM_CONDITIONAL([ENABLE_TESTS], [test "x$enable_tests" = xyes]) +dnl Build without deprecated APIs? +AC_ARG_ENABLE([deprecated], + [AS_HELP_STRING([--disable-deprecated], [Build without deprecated APIs @<:@default=no@:>@])], + [case "$enableval" in + *) + with_deprecated="no" + CPPFLAGS="$CPPFLAGS -DLIBSSH2_NO_DEPRECATED" + ;; + esac], + [with_deprecated="yes"]) # Run Docker tests? AC_ARG_ENABLE([docker-tests], @@ -288,20 +316,11 @@ AM_CONDITIONAL([USE_OSSFUZZ_STATIC], [test -f "$LIB_FUZZING_ENGINE"]) # Checks for header files. -AC_CHECK_HEADERS([errno.h fcntl.h stdio.h unistd.h sys/param.h sys/uio.h]) +AC_CHECK_HEADERS([errno.h fcntl.h stdio.h unistd.h sys/uio.h]) AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/ioctl.h sys/time.h]) AC_CHECK_HEADERS([arpa/inet.h netinet/in.h]) AC_CHECK_HEADERS([sys/un.h]) -case $host in - *-*-cygwin* | *-*-cegcc*) - # These are POSIX-like systems using BSD-like sockets API. - ;; - *) - AC_CHECK_HEADERS([windows.h], [have_windows_h=yes], [have_windows_h=no]) - ;; -esac - case $host in *darwin*|*interix*) dnl poll() does not work on these platforms @@ -365,14 +384,15 @@ if test "$found_crypto" = "none"; then fi if test $missing_required_deps = 1; then - AC_MSG_ERROR([Required dependencies are missing!]) + AC_MSG_ERROR([Required dependencies are missing.]) fi AM_CONDITIONAL([HAVE_WINDRES], [test "x$have_windows_h" = "xyes" && test "x${enable_shared}" = "xyes" && test -n "${RC}"]) +AM_CONDITIONAL([HAVE_LIB_STATIC], [test "x$enable_static" != "xno"]) + # Configure parameters -LIBSSH2_CHECK_OPTION_WERROR # Append crypto lib if test "$found_crypto" = "openssl"; then @@ -387,6 +407,22 @@ elif test "$found_crypto" = "mbedtls"; then LIBS="${LIBS} ${LTLIBMBEDCRYPTO}" fi +LIBS="${LIBS} ${LTLIBZ}" + +LIBSSH2_PC_LIBS_PRIVATE=$LIBS +AC_SUBST(LIBSSH2_PC_LIBS_PRIVATE) + +dnl merge the pkg-config private fields into public ones when static-only +if test "x$enable_shared" = "xyes"; then + LIBSSH2_PC_REQUIRES= + LIBSSH2_PC_LIBS= +else + LIBSSH2_PC_REQUIRES=$LIBSSH2_PC_REQUIRES_PRIVATE + LIBSSH2_PC_LIBS=$LIBSSH2_PC_LIBS_PRIVATE +fi +AC_SUBST(LIBSSH2_PC_REQUIRES) +AC_SUBST(LIBSSH2_PC_LIBS) + AC_CONFIG_FILES([Makefile src/Makefile libssh2.pc]) @@ -394,15 +430,17 @@ AC_OUTPUT AC_MSG_NOTICE([summary of build options: - version: ${LIBSSH2VER} + version: ${LIBSSH2_VERSION} Host type: ${host} Install prefix: ${prefix} Compiler: ${CC} Compiler flags: ${CFLAGS} Library types: Shared=${enable_shared}, Static=${enable_static} Crypto library: ${found_crypto_str} + WinCNG ECDSA: $wincng_ecdsa zlib compression: ${found_libz} Clear memory: $enable_clear_memory + Deprecated APIs: $with_deprecated Debug build: $enable_debug Build examples: $build_examples Run Docker tests: $run_docker_tests diff --git a/libssh2/get_ver.awk b/libssh2/get_ver.awk index 8253168e6..2377ae856 100755 --- a/libssh2/get_ver.awk +++ b/libssh2/get_ver.awk @@ -1,4 +1,7 @@ # fetch libssh2 version number from input file and write them to STDOUT +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause + BEGIN { while ((getline < ARGV[1]) > 0) { if (match ($0, /^#define LIBSSH2_COPYRIGHT "[^"]+"$/)) { diff --git a/libssh2/git2news.pl b/libssh2/git2news.pl index 63dd38267..3e3683408 100755 --- a/libssh2/git2news.pl +++ b/libssh2/git2news.pl @@ -1,4 +1,6 @@ #!/usr/bin/env perl +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause # git log --pretty=fuller --no-color --date=short --decorate=full diff --git a/libssh2/include/libssh2.h b/libssh2/include/libssh2.h index 97ac5898f..f47858aed 100644 --- a/libssh2/include/libssh2.h +++ b/libssh2/include/libssh2.h @@ -1,6 +1,6 @@ -/* Copyright (c) 2004-2009, Sara Golemon - * Copyright (c) 2009-2021 Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,24 +35,26 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIBSSH2_H #define LIBSSH2_H 1 -#define LIBSSH2_COPYRIGHT "2004-2023 The libssh2 project and its contributors." +#define LIBSSH2_COPYRIGHT "The libssh2 project and its contributors." /* We use underscore instead of dash when appending DEV in dev versions just to make the BANNER define (used by src/session.c) be a valid SSH banner. Release versions have no appended strings and may of course not have dashes either. */ -#define LIBSSH2_VERSION "1.11.0" +#define LIBSSH2_VERSION "1.11.1" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBSSH2_VERSION_MAJOR 1 #define LIBSSH2_VERSION_MINOR 11 -#define LIBSSH2_VERSION_PATCH 0 +#define LIBSSH2_VERSION_PATCH 1 /* This is the numeric version of the libssh2 version number, meant for easier parsing and comparisons by programs. The LIBSSH2_VERSION_NUM define will @@ -69,7 +71,7 @@ and it is always a greater number in a more recent release. It makes comparisons with greater than and less than work. */ -#define LIBSSH2_VERSION_NUM 0x010b00 +#define LIBSSH2_VERSION_NUM 0x010b01 /* * This is the date and time when the full source package was created. The @@ -80,7 +82,7 @@ * * "Mon Feb 12 11:35:33 UTC 2007" */ -#define LIBSSH2_TIMESTAMP "Tue May 30 03:58:58 PM UTC 2023" +#define LIBSSH2_TIMESTAMP "Wed Oct 16 08:03:21 UTC 2024" #ifndef RC_INVOKED @@ -88,11 +90,7 @@ extern "C" { #endif -#if defined(_WIN32) || defined(WIN32) -#define LIBSSH2_WIN32 -#endif - -#ifdef LIBSSH2_WIN32 +#ifdef _WIN32 # include # include #endif @@ -104,8 +102,8 @@ extern "C" { /* Allow alternate API prefix from CFLAGS or calling app */ #ifndef LIBSSH2_API -# ifdef LIBSSH2_WIN32 -# if defined(LIBSSH2_EXPORTS) || defined(DLL_EXPORT) || defined(_WINDLL) +# ifdef _WIN32 +# if defined(LIBSSH2_EXPORTS) || defined(_WINDLL) # ifdef LIBSSH2_LIBRARY # define LIBSSH2_API __declspec(dllexport) # else @@ -114,9 +112,9 @@ extern "C" { # else # define LIBSSH2_API # endif -# else /* !LIBSSH2_WIN32 */ +# else /* !_WIN32 */ # define LIBSSH2_API -# endif /* LIBSSH2_WIN32 */ +# endif /* _WIN32 */ #endif /* LIBSSH2_API */ #ifdef HAVE_SYS_UIO_H @@ -142,13 +140,44 @@ typedef unsigned long long libssh2_uint64_t; typedef long long libssh2_int64_t; #endif -#ifdef LIBSSH2_WIN32 +#ifdef _WIN32 typedef SOCKET libssh2_socket_t; #define LIBSSH2_INVALID_SOCKET INVALID_SOCKET -#else /* !LIBSSH2_WIN32 */ +#define LIBSSH2_SOCKET_CLOSE(s) closesocket(s) +#else /* !_WIN32 */ typedef int libssh2_socket_t; #define LIBSSH2_INVALID_SOCKET -1 -#endif /* LIBSSH2_WIN32 */ +#define LIBSSH2_SOCKET_CLOSE(s) close(s) +#endif /* _WIN32 */ + +/* Compile-time deprecation macros */ +#if !defined(LIBSSH2_DISABLE_DEPRECATION) && !defined(LIBSSH2_LIBRARY) +# if defined(_MSC_VER) +# if _MSC_VER >= 1400 +# define LIBSSH2_DEPRECATED(version, message) \ + __declspec(deprecated("since libssh2 " # version ". " message)) +# elif _MSC_VER >= 1310 +# define LIBSSH2_DEPRECATED(version, message) \ + __declspec(deprecated) +# endif +# elif defined(__GNUC__) && !defined(__INTEL_COMPILER) +# if (defined(__clang__) && __clang_major__ >= 3) || \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +# define LIBSSH2_DEPRECATED(version, message) \ + __attribute__((deprecated("since libssh2 " # version ". " message))) +# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) +# define LIBSSH2_DEPRECATED(version, message) \ + __attribute__((deprecated)) +# endif +# elif defined(__SUNPRO_C) && __SUNPRO_C >= 0x5130 +# define LIBSSH2_DEPRECATED(version, message) \ + __attribute__((deprecated)) +# endif +#endif + +#ifndef LIBSSH2_DEPRECATED +#define LIBSSH2_DEPRECATED(version, message) +#endif /* * Determine whether there is small or large file support on windows. @@ -174,7 +203,7 @@ typedef int libssh2_socket_t; # undef LIBSSH2_USE_WIN32_LARGE_FILES #endif -#if defined(LIBSSH2_WIN32) && !defined(LIBSSH2_USE_WIN32_LARGE_FILES) && \ +#if defined(_WIN32) && !defined(LIBSSH2_USE_WIN32_LARGE_FILES) && \ !defined(LIBSSH2_USE_WIN32_SMALL_FILES) # define LIBSSH2_USE_WIN32_SMALL_FILES #endif @@ -263,7 +292,7 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE { char *text; - unsigned int length; + unsigned int length; /* FIXME: change type to size_t */ } LIBSSH2_USERAUTH_KBDINT_RESPONSE; typedef struct _LIBSSH2_SK_SIG_INFO { @@ -281,6 +310,7 @@ typedef struct _LIBSSH2_SK_SIG_INFO { const unsigned char *data, size_t data_len, void **abstract) /* 'keyboard-interactive' authentication callback */ +/* FIXME: name_len, instruction_len -> size_t, num_prompts -> unsigned int? */ #define LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(name_) \ void name_(const char *name, int name_len, const char *instruction, \ int instruction_len, int num_prompts, \ @@ -300,6 +330,8 @@ typedef struct _LIBSSH2_SK_SIG_INFO { #define LIBSSH2_SK_PRESENCE_REQUIRED 0x01 #define LIBSSH2_SK_VERIFICATION_REQUIRED 0x04 +/* FIXME: update lengths to size_t (or ssize_t): */ + /* Callbacks for special SSH packets */ #define LIBSSH2_IGNORE_FUNC(name) \ void name(LIBSSH2_SESSION *session, const char *message, int message_len, \ @@ -470,7 +502,7 @@ typedef struct _LIBSSH2_POLLFD { /* Hostkey Types */ #define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0 #define LIBSSH2_HOSTKEY_TYPE_RSA 1 -#define LIBSSH2_HOSTKEY_TYPE_DSS 2 +#define LIBSSH2_HOSTKEY_TYPE_DSS 2 /* deprecated */ #define LIBSSH2_HOSTKEY_TYPE_ECDSA_256 3 #define LIBSSH2_HOSTKEY_TYPE_ECDSA_384 4 #define LIBSSH2_HOSTKEY_TYPE_ECDSA_521 5 @@ -555,6 +587,9 @@ typedef struct _LIBSSH2_POLLFD { #define LIBSSH2_ERROR_RANDGEN -49 #define LIBSSH2_ERROR_MISSING_USERAUTH_BANNER -50 #define LIBSSH2_ERROR_ALGO_UNSUPPORTED -51 +#define LIBSSH2_ERROR_MAC_FAILURE -52 +#define LIBSSH2_ERROR_HASH_INIT -53 +#define LIBSSH2_ERROR_HASH_CALC -54 /* this is a define to provide the old (<= 1.2.7) name */ #define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV @@ -615,14 +650,25 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session); +typedef void (libssh2_cb_generic)(void); + +LIBSSH2_API libssh2_cb_generic * +libssh2_session_callback_set2(LIBSSH2_SESSION *session, int cbtype, + libssh2_cb_generic *callback); + +LIBSSH2_DEPRECATED(1.11.1, "Use libssh2_session_callback_set2()") LIBSSH2_API void *libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback); LIBSSH2_API int libssh2_session_banner_set(LIBSSH2_SESSION *session, const char *banner); +#ifndef LIBSSH2_NO_DEPRECATED +LIBSSH2_DEPRECATED(1.4.0, "Use libssh2_session_banner_set()") LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, const char *banner); +LIBSSH2_DEPRECATED(1.2.8, "Use libssh2_session_handshake()") LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int sock); +#endif LIBSSH2_API int libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock); LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, @@ -909,12 +955,13 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, #define libssh2_channel_window_read(channel) \ libssh2_channel_window_read_ex((channel), NULL, NULL) -/* libssh2_channel_receive_window_adjust() is DEPRECATED, do not use! */ +#ifndef LIBSSH2_NO_DEPRECATED +LIBSSH2_DEPRECATED(1.1.0, "Use libssh2_channel_receive_window_adjust2()") LIBSSH2_API unsigned long libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, unsigned long adjustment, unsigned char force); - +#endif LIBSSH2_API int libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel, unsigned long adjustment, @@ -953,12 +1000,15 @@ LIBSSH2_API void libssh2_session_set_read_timeout(LIBSSH2_SESSION* session, long timeout); LIBSSH2_API long libssh2_session_get_read_timeout(LIBSSH2_SESSION* session); -/* libssh2_channel_handle_extended_data() is DEPRECATED, do not use! */ +#ifndef LIBSSH2_NO_DEPRECATED +LIBSSH2_DEPRECATED(1.1.0, "libssh2_channel_handle_extended_data2()") LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode); +#endif LIBSSH2_API int libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, int ignore_mode); +#ifndef LIBSSH2_NO_DEPRECATED /* libssh2_channel_ignore_extended_data() is defined below for BC with version * 0.1 * @@ -966,11 +1016,12 @@ LIBSSH2_API int libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, * LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE is passed, extended data will be read * (FIFO) from the standard data channel */ -/* DEPRECATED */ +/* DEPRECATED since 0.3.0. Use libssh2_channel_handle_extended_data2(). */ #define libssh2_channel_ignore_extended_data(channel, ignore) \ libssh2_channel_handle_extended_data((channel), (ignore) ? \ LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE : \ LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL) +#endif #define LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA -1 #define LIBSSH2_CHANNEL_FLUSH_ALL -2 @@ -995,10 +1046,12 @@ LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel); -/* libssh2_scp_recv is DEPRECATED, do not use! */ +#ifndef LIBSSH2_NO_DEPRECATED +LIBSSH2_DEPRECATED(1.7.0, "Use libssh2_scp_recv2()") LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat *sb); +#endif /* Use libssh2_scp_recv2() for large (> 2GB) file support on windows */ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv2(LIBSSH2_SESSION *session, const char *path, @@ -1094,7 +1147,7 @@ libssh2_knownhost_init(LIBSSH2_SESSION *session); #define LIBSSH2_KNOWNHOST_KEY_SHIFT 18 #define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18) #define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18) -#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18) +#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18) /* deprecated */ #define LIBSSH2_KNOWNHOST_KEY_ECDSA_256 (4<<18) #define LIBSSH2_KNOWNHOST_KEY_ECDSA_384 (5<<18) #define LIBSSH2_KNOWNHOST_KEY_ECDSA_521 (6<<18) @@ -1418,7 +1471,7 @@ libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent); */ LIBSSH2_API void libssh2_keepalive_config(LIBSSH2_SESSION *session, int want_reply, - unsigned interval); + unsigned int interval); /* * libssh2_keepalive_send() diff --git a/libssh2/include/libssh2_publickey.h b/libssh2/include/libssh2_publickey.h index 00ea5ffdc..566acd653 100644 --- a/libssh2/include/libssh2_publickey.h +++ b/libssh2/include/libssh2_publickey.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2004-2006, Sara Golemon +/* Copyright (C) Sara Golemon * All rights reserved. * * Redistribution and use in source and binary forms, @@ -41,6 +41,8 @@ * * For more information on the publickey subsystem, * refer to IETF draft: secsh-publickey + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIBSSH2_PUBLICKEY_H diff --git a/libssh2/include/libssh2_sftp.h b/libssh2/include/libssh2_sftp.h index 74f619fcc..ab7b0af4d 100644 --- a/libssh2/include/libssh2_sftp.h +++ b/libssh2/include/libssh2_sftp.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2004-2008, Sara Golemon +/* Copyright (C) Sara Golemon * All rights reserved. * * Redistribution and use in source and binary forms, @@ -33,6 +33,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIBSSH2_SFTP_H @@ -40,7 +42,7 @@ #include "libssh2.h" -#ifndef LIBSSH2_WIN32 +#ifndef _WIN32 #include #endif @@ -301,11 +303,20 @@ LIBSSH2_API int libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, LIBSSH2_SFTP_RENAME_ATOMIC | \ LIBSSH2_SFTP_RENAME_NATIVE) +LIBSSH2_API int libssh2_sftp_posix_rename_ex(LIBSSH2_SFTP *sftp, + const char *source_filename, + size_t srouce_filename_len, + const char *dest_filename, + size_t dest_filename_len); +#define libssh2_sftp_posix_rename(sftp, sourcefile, destfile) \ + libssh2_sftp_posix_rename_ex((sftp), (sourcefile), strlen(sourcefile), \ + (destfile), strlen(destfile)) + LIBSSH2_API int libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, const char *filename, unsigned int filename_len); #define libssh2_sftp_unlink(sftp, filename) \ - libssh2_sftp_unlink_ex((sftp), (filename), strlen(filename)) + libssh2_sftp_unlink_ex((sftp), (filename), (unsigned int)strlen(filename)) LIBSSH2_API int libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st); diff --git a/libssh2/libssh2-style.el b/libssh2/libssh2-style.el index 4437f88ac..3001010fc 100644 --- a/libssh2/libssh2-style.el +++ b/libssh2/libssh2-style.el @@ -1,4 +1,6 @@ ;;;; Emacs Lisp help for writing libssh2 code. ;;;; +;;; Copyright (C) The libssh2 project and its contributors. +;;; SPDX-License-Identifier: BSD-3-Clause ;;; The libssh2 hacker's C conventions. ;;; See the sample.emacs file on how this file can be made to take diff --git a/libssh2/libssh2.pc.in b/libssh2/libssh2.pc.in index 966381674..9dde3e85c 100644 --- a/libssh2/libssh2.pc.in +++ b/libssh2/libssh2.pc.in @@ -1,5 +1,8 @@ ########################################################################### # libssh2 installation details +# +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause ########################################################################### prefix=@prefix@ @@ -8,10 +11,11 @@ libdir=@libdir@ includedir=@includedir@ Name: libssh2 -URL: https://www.libssh2.org/ +URL: https://libssh2.org/ Description: Library for SSH-based communication -Version: @LIBSSH2VER@ -Requires.private: @LIBSREQUIRED@ -Libs: -L${libdir} -lssh2 @LIBS@ -Libs.private: @LIBS@ +Version: @LIBSSH2_VERSION@ +Requires: @LIBSSH2_PC_REQUIRES@ +Requires.private: @LIBSSH2_PC_REQUIRES_PRIVATE@ +Libs: -L${libdir} -lssh2 @LIBSSH2_PC_LIBS@ +Libs.private: @LIBSSH2_PC_LIBS_PRIVATE@ Cflags: -I${includedir} diff --git a/libssh2/m4/lib-ld.m4 b/libssh2/m4/lib-ld.m4 index db76f6bcf..ea53c41d3 100644 --- a/libssh2/m4/lib-ld.m4 +++ b/libssh2/m4/lib-ld.m4 @@ -3,6 +3,8 @@ dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. +dnl +dnl SPDX-License-Identifier: FSFULLR dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision diff --git a/libssh2/m4/lib-link.m4 b/libssh2/m4/lib-link.m4 index 7a41234bf..ee06a613b 100644 --- a/libssh2/m4/lib-link.m4 +++ b/libssh2/m4/lib-link.m4 @@ -3,6 +3,8 @@ dnl Copyright (C) 2001-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. +dnl +dnl SPDX-License-Identifier: FSFULLR dnl From Bruno Haible. diff --git a/libssh2/m4/lib-prefix.m4 b/libssh2/m4/lib-prefix.m4 index a8684e17e..9695f8875 100644 --- a/libssh2/m4/lib-prefix.m4 +++ b/libssh2/m4/lib-prefix.m4 @@ -3,6 +3,8 @@ dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. +dnl +dnl SPDX-License-Identifier: FSFULLR dnl From Bruno Haible. diff --git a/libssh2/maketgz b/libssh2/maketgz index 3f5a1932f..80f557cdb 100755 --- a/libssh2/maketgz +++ b/libssh2/maketgz @@ -1,25 +1,35 @@ #!/bin/sh +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause +# # Script to build release-archives with. Note that this requires a checkout # from git and you should first run 'autoreconf -fi' and './configure'. # -version="$1" +set -eu + +export LC_ALL=C +export TZ=UTC + +version="${1:-}" if [ -z "$version" ]; then echo "Specify a version number!" exit fi -if [ "only" = "$2" ]; then +if [ "only" = "${2:-}" ]; then echo "Setup version number only!" only=1 +else + only= fi libversion="$version" -major="$(echo "$libversion" | cut -d. -f1 | sed -e "s/[^0-9]//g")" -minor="$(echo "$libversion" | cut -d. -f2 | sed -e "s/[^0-9]//g")" -patch="$(echo "$libversion" | cut -d. -f3 | cut -d- -f1 | sed -e "s/[^0-9]//g")" +major=$(echo "$libversion" | cut -d. -f1 | sed -e "s/[^0-9]//g") +minor=$(echo "$libversion" | cut -d. -f2 | sed -e "s/[^0-9]//g") +patch=$(echo "$libversion" | cut -d. -f3 | cut -d- -f1 | sed -e "s/[^0-9]//g") numeric="$(printf "%02x%02x%02x\n" "$major" "$minor" "$patch")" @@ -34,10 +44,12 @@ if test -z "$only"; then HEADER="$HEADER$ext" fi -# requires a date command that knows -u for UTC time zone -datestamp="$(LC_TIME=C date -u)" +# requires a date command that knows + for format and -d for date input +timestamp=${SOURCE_DATE_EPOCH:-$(date +"%s")} +datestamp=$(date -d "@$timestamp") +filestamp=$(date -d "@$timestamp" +"%Y%m%d%H%M.%S") -# Replace in-place version number in header file: +# Replace version number in header file: sed -i.bak \ -e "s/^#define LIBSSH2_VERSION .*/#define LIBSSH2_VERSION \"$libversion\"/g" \ -e "s/^#define LIBSSH2_VERSION_NUM .*/#define LIBSSH2_VERSION_NUM 0x$numeric/g" \ @@ -46,18 +58,17 @@ sed -i.bak \ -e "s/^#define LIBSSH2_VERSION_PATCH .*/#define LIBSSH2_VERSION_PATCH $patch/g" \ -e "s/^#define LIBSSH2_TIMESTAMP .*/#define LIBSSH2_TIMESTAMP \"$datestamp\"/g" \ "$HEADER" - rm -f "$HEADER.bak" -echo "libssh2 version $libversion" -echo "libssh2 numerical $numeric" -echo "datestamp $datestamp" - if test -n "$only"; then # done! exit fi +echo "libssh2 version $libversion" +echo "libssh2 numerical $numeric" +echo "datestamp $datestamp" + findprog() { file="$1" for part in $(echo "$PATH" | tr ':' ' '); do @@ -85,7 +96,7 @@ else automake --include-deps Makefile >/dev/null fi -####################################################################### +############################################################################ # # Generate the changelog # @@ -107,6 +118,23 @@ if test "$res" != 0; then exit 2 fi +retar() { + tempdir=$1 + rm -rf "$tempdir" + mkdir "$tempdir" + cd "$tempdir" + gzip -dc "../$targz" | tar -xf - + find libssh2-* -depth -exec touch -c -t "$filestamp" '{}' + + tar --create --format=ustar --owner=0 --group=0 --numeric-owner --sort=name libssh2-* | gzip --best --no-name > out.tar.gz + mv out.tar.gz ../ + cd .. + rm -rf "$tempdir" +} + +retar ".tarbuild" +echo "replace $targz with out.tar.gz" +mv out.tar.gz "$targz" + ############################################################################ # # Now make a bz2 archive from the tar.gz original @@ -132,11 +160,11 @@ gzip -dc "$targz" | xz -6e - > "$xz" makezip() { rm -rf "$tempdir" mkdir "$tempdir" - cd "$tempdir" || exit 1 + cd "$tempdir" gzip -dc "../$targz" | tar -xf - - find . | zip "$zip" -@ >/dev/null + find . | sort | zip -9 -X "$zip" -@ >/dev/null mv "$zip" ../ - cd .. || exit 1 + cd .. rm -rf "$tempdir" } @@ -145,7 +173,14 @@ echo "Generating $zip" tempdir=".builddir" makezip +# Set deterministic timestamp +touch -c -t "$filestamp" "$targz" "$bzip2" "$xz" "$zip" + echo "------------------" echo "maketgz report:" echo "" -ls -l "$targz" "$bzip2" "$zip" "$xz" +ls -l "$targz" "$bzip2" "$xz" "$zip" +sha256sum "$targz" "$bzip2" "$xz" "$zip" + +echo "Run this:" +echo "gpg -b -a '$targz' && gpg -b -a '$bzip2' && gpg -b -a '$xz' && gpg -b -a '$zip'" diff --git a/libssh2/os400/README400 b/libssh2/os400/README400 index e14bcf364..025cec79c 100644 --- a/libssh2/os400/README400 +++ b/libssh2/os400/README400 @@ -18,7 +18,8 @@ additional procedures are provided for string transcoding (see below). No wrappers to standard procedures are provided: however, nested calls to transcoding procedures may be used. -Crypto API is provided by the IBM QC3 API library. It supports RSA, but not DSA. +Crypto API is provided by the IBM QC3 API library. It supports RSA and EC, +but not DSA. Standard compilation environment does support neither autotools nor make; @@ -36,23 +37,31 @@ Compiling on OS/400: archive extraction. Do not ask questions about these subjects if you're not familiar with. -_ As a prerequisite, QADRT development environment must be installed. -_ Install the libssh2 sources directory in IFS. +_ As a prerequisite, QADRT development environment >= 20211112 must be + installed. + For more information on downloading and installing the QADRT development kit, + please see https://www.ibm.com/support/pages/node/6258183 +_ If data compression has to be supported, ZLIB development environment must + be installed. +_ Install the libssh2 sources directory in IFS. Do NOT install it in the + installation target directory (which defaults to /libssh2). _ Enter shell (QSH). You may need to change the LANG environment variable to be in phase with the libssh2 source files CCSID. _ Change current directory to the libssh2 sources installation directory _ Change current directory to os400 -_ Edit file iniscript.sh. You may want to change tunable configuration - parameters, like debug info generation, optimisation level, listing option, - target library, zlib availability and location, etc. +- If you want to change the default configuration parameters like debug info + generation, optimization level, listing option, target library, zlib + availability and location, etc., copy file config400.default to + config400.override and edit the latter. Do not edit the original default file + as it might be overwritten by a subsequent source installation. _ Copy any file in the current directory to makelog (i.e.: cp initscript.sh makelog): this is intended to create the makelog file with an ASCII CCSID! _ Enter the command "sh make.sh > makelog 2>&1' _ Examine the makelog file to check for compilation errors. - Leaving file initscript.sh unchanged, this will produce the following OS/400 -objects: + Without configuration parameters override, this will produce the following +OS/400 objects: _ Library LIBSSH2. All other objects will be stored in this library. _ Modules for all libssh2 units. _ Binding directory LIBSSH2_A, to be used at calling program link time for @@ -123,7 +132,8 @@ char * libssh2_to_ccsid(LIBSSH2_SESSION *session, size_t *outlen); where: - session is a libssh2 session used for memory allocation. + session is a libssh2 session used for memory allocation or NULL for + global allocation scheme. cache is the address of a string cache. ccsid is the external (i.e.: non libssh2) coded character set id. 65535 means no conversion and 0 means the current job's CCSID. @@ -145,6 +155,8 @@ or NULL if an error occurred. In addition, the variable pointed by outlen receives the effective byte length of the (cached) translated string, or -1 in case of error. + Please take care to never mix different sessions into the same cache. + ILE/RPG support: diff --git a/libssh2/os400/ccsid.c b/libssh2/os400/ccsid.c index fdad8a652..0eb9da244 100644 --- a/libssh2/os400/ccsid.c +++ b/libssh2/os400/ccsid.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ /* Character encoding wrappers. */ @@ -46,6 +48,7 @@ #include #include #include +#include @@ -56,6 +59,11 @@ #define OFFSET_OF(t, f) ((size_t) ((char *) &((t *) 0)->f - (char *) 0)) +#define ALLOC(s, sz) ((s)? LIBSSH2_ALLOC((s), (sz)): malloc(sz)) +#define REALLOC(s, p, sz) ((s)? LIBSSH2_REALLOC((s), (p), (sz)): \ + realloc((p), (sz))) +#define FREE(s, p) ((s)? LIBSSH2_FREE((s), (p)): free(p)) + struct _libssh2_string_cache { libssh2_string_cache * next; @@ -80,7 +88,7 @@ terminator_size(unsigned short ccsid) /* Return the null-terminator size for the given CCSID. */ /* Fast check usual CCSIDs. */ - switch (ccsid) { + switch(ccsid) { case CCSID_UTF8: case 0: /* Job CCSID is SBCS EBCDIC. */ return 1; @@ -90,19 +98,19 @@ terminator_size(unsigned short ccsid) /* Convert an UTF-8 NUL to the target CCSID: use the converted size as result. */ - memset((void *) &outcode, 0, sizeof outcode); + memset((void *) &outcode, 0, sizeof(outcode)); outcode.CCSID = ccsid; cd = QtqIconvOpen(&outcode, (QtqCode_T *) &utf8code); - if (cd.return_value == -1) + if(cd.return_value == -1) return -1; inp = ""; ilen = 1; outp = buf; - olen = sizeof buf; + olen = sizeof(buf); iconv(cd, &inp, &ilen, &outp, &olen); iconv_close(cd); - olen = sizeof buf - olen; - return olen? olen: -1; + olen = sizeof(buf - olen); + return olen ? olen : -1; } static char * @@ -124,66 +132,66 @@ convert_ccsid(LIBSSH2_SESSION *session, libssh2_string_cache **cache, QtqCode_T outcode; iconv_t cd; - if (!instring) { - if (outlen) + if(!instring) { + if(outlen) *outlen = 0; return NULL; } - if (outlen) + if(outlen) *outlen = -1; - if (!session || !cache) + if(!cache) return NULL; /* Get terminator size. */ termsize = terminator_size(outccsid); - if (termsize < 0) + if(termsize < 0) return NULL; /* Prepare conversion parameters. */ - memset((void *) &incode, 0, sizeof incode); - memset((void *) &outcode, 0, sizeof outcode); + memset((void *) &incode, 0, sizeof(incode)); + memset((void *) &outcode, 0, sizeof(outcode)); incode.CCSID = inccsid; outcode.CCSID = outccsid; curlen = OFFSET_OF(libssh2_string_cache, string); inp = (char *) instring; ilen = inlen; buflen = inlen + curlen; - if (inlen < 0) { + if(inlen < 0) { incode.length_option = 1; buflen = STRING_GRANULE; ilen = 0; } /* Allocate output string buffer and open conversion descriptor. */ - dst = LIBSSH2_ALLOC(session, buflen + termsize); - if (!dst) + dst = ALLOC(session, buflen + termsize); + if(!dst) return NULL; cd = QtqIconvOpen(&outcode, &incode); - if (cd.return_value == -1) { - LIBSSH2_FREE(session, (char *) dst); + if(cd.return_value == -1) { + FREE(session, dst); return NULL; } /* Convert string. */ - for (;;) { + for(;;) { outp = dst + curlen; olen = buflen - curlen; i = iconv(cd, &inp, &ilen, &outp, &olen); - if (inlen < 0 && olen == buflen - curlen) { + if(inlen < 0 && olen == buflen - curlen) { /* Special case: converted 0-length (sub)strings do not store the terminator. */ - if (termsize) { + if(termsize) { memset(outp, 0, termsize); olen -= termsize; } } curlen = buflen - olen; - if (i >= 0 || errno != E2BIG) + if(i >= 0 || errno != E2BIG) break; /* Must expand buffer. */ buflen += STRING_GRANULE; - outp = LIBSSH2_REALLOC(session, dst, buflen + termsize); - if (!outp) + outp = REALLOC(session, dst, buflen + termsize); + if(!outp) break; dst = outp; } @@ -191,20 +199,20 @@ convert_ccsid(LIBSSH2_SESSION *session, libssh2_string_cache **cache, iconv_close(cd); /* Check for error. */ - if (i < 0 || !outp) { - LIBSSH2_FREE(session, dst); + if(i < 0 || !outp) { + FREE(session, dst); return NULL; } /* Process terminator. */ - if (inlen < 0) + if(inlen < 0) curlen -= termsize; - else if (termsize) + else if(termsize) memset(dst + curlen, 0, termsize); /* Shorten buffer if possible. */ - if (curlen < buflen) - dst = LIBSSH2_REALLOC(session, dst, curlen + termsize); + if(curlen < buflen) + dst = REALLOC(session, dst, curlen + termsize); /* Link to cache. */ outstring = (libssh2_string_cache *) dst; @@ -212,7 +220,7 @@ convert_ccsid(LIBSSH2_SESSION *session, libssh2_string_cache **cache, *cache = outstring; /* Return length if required. */ - if (outlen) + if(outlen) *outlen = curlen - OFFSET_OF(libssh2_string_cache, string); return outstring->string; @@ -242,10 +250,10 @@ libssh2_release_string_cache(LIBSSH2_SESSION *session, { libssh2_string_cache *p; - if (session && cache) - while ((p = *cache)) { + if(cache) + while((p = *cache)) { *cache = p->next; - LIBSSH2_FREE(session, (char *) p); + FREE(session, (char *) p); } } diff --git a/libssh2/os400/config400.default b/libssh2/os400/config400.default new file mode 100644 index 000000000..5147cb208 --- /dev/null +++ b/libssh2/os400/config400.default @@ -0,0 +1,28 @@ +#!/bin/sh +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause + +################################################################################ + +# Tunable configuration parameters. + +setenv TARGETLIB 'LIBSSH2' # Target OS/400 program library. +setenv STATBNDDIR 'LIBSSH2_A' # Static binding directory. +setenv DYNBNDDIR 'LIBSSH2' # Dynamic binding directory. +setenv SRVPGM "LIBSSH2.${SONAME}" # Service program. +setenv TGTCCSID '500' # Target CCSID of objects. +setenv DEBUG '*ALL' # Debug level. +setenv OPTIMIZE '10' # Optimisation level +setenv OUTPUT '*NONE' # Compilation output option. +setenv TGTRLS '*CURRENT' # Target OS release. +setenv IFSDIR '/libssh2' # Installation IFS directory. +setenv QADRTDIR '/QIBM/ProdData/qadrt' # QADRT IFS directory. + +setenv WITH_MD5 'yes' # enable MD5 support. + +# Define ZLIB availability and locations. + +setenv WITH_ZLIB 0 # Define to 1 to enable. +setenv ZLIB_INCLUDE '/zlib/include' # ZLIB include IFS directory. +setenv ZLIB_LIB 'ZLIB' # ZLIB library. +setenv ZLIB_BNDDIR 'ZLIB_A' # ZLIB binding directory. diff --git a/libssh2/os400/include/alloca.h b/libssh2/os400/include/alloca.h index ff0cee4e2..050f44229 100644 --- a/libssh2/os400/include/alloca.h +++ b/libssh2/os400/include/alloca.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIBSSH2_ALLOCA_H diff --git a/libssh2/os400/include/assert.h b/libssh2/os400/include/assert.h index 33ea34776..b6197c659 100644 --- a/libssh2/os400/include/assert.h +++ b/libssh2/os400/include/assert.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Patrick Monnerat + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIBSSH2_ASSERT_H diff --git a/libssh2/os400/include/sys/socket.h b/libssh2/os400/include/sys/socket.h index 4c7712186..7d5adea93 100644 --- a/libssh2/os400/include/sys/socket.h +++ b/libssh2/os400/include/sys/socket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIBSSH2_SYS_SOCKET_H @@ -64,7 +66,7 @@ #endif extern int _libssh2_os400_connect(int sd, - struct sockaddr * destaddr, int addrlen); + struct sockaddr *destaddr, int addrlen); #ifndef LIBSSH2_DISABLE_QADRT_EXT #define connect(sd, addr, len) _libssh2_os400_connect((sd), (addr), (len)) diff --git a/libssh2/os400/initscript.sh b/libssh2/os400/initscript.sh old mode 100644 new mode 100755 index 931c8cd88..bbe78c070 --- a/libssh2/os400/initscript.sh +++ b/libssh2/os400/initscript.sh @@ -1,19 +1,20 @@ #!/bin/sh - +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause setenv() { # Define and export. - eval ${1}="${2}" - export ${1} + eval "${1}=${2}" + export "${1?}" } case "${SCRIPTDIR}" in /*) ;; -*) SCRIPTDIR="`pwd`/${SCRIPTDIR}" +*) SCRIPTDIR="$(pwd)/${SCRIPTDIR}" esac while true @@ -25,64 +26,43 @@ done # The script directory is supposed to be in $TOPDIR/os400. -TOPDIR=`dirname "${SCRIPTDIR}"` +TOPDIR=$(dirname "${SCRIPTDIR}") export SCRIPTDIR TOPDIR # Extract the SONAME from the library makefile. -SONAME=`sed -e '/^VERSION=/!d' -e 's/^.* \([0-9]*\):.*$/\1/' -e 'q' \ - < "${TOPDIR}/src/Makefile.am"` +SONAME=$(sed -e '/^VERSION=/!d' \ + -e 's/^.* \([0-9]*\):.*$/\1/' -e 'q' \ + < "${TOPDIR}/src/Makefile.am") export SONAME +# Get OS/400 configuration parameters. -################################################################################ -# -# Tunable configuration parameters. -# -################################################################################ - -setenv TARGETLIB 'LIBSSH2' # Target OS/400 program library. -setenv STATBNDDIR 'LIBSSH2_A' # Static binding directory. -setenv DYNBNDDIR 'LIBSSH2' # Dynamic binding directory. -setenv SRVPGM "LIBSSH2.${SONAME}" # Service program. -setenv TGTCCSID '500' # Target CCSID of objects. -setenv DEBUG '*ALL' # Debug level. -setenv OPTIMIZE '10' # Optimisation level -setenv OUTPUT '*NONE' # Compilation output option. -setenv TGTRLS 'V7R3M0' # Target OS release. -setenv IFSDIR '/libssh2' # Installation IFS directory. -setenv QADRTDIR '/QIBM/ProdData/qadrt' # QADRT IFS directory. - -# Define ZLIB availability and locations. - -setenv WITH_ZLIB 0 # Define to 1 to enable. -setenv ZLIB_INCLUDE '/zlib/include' # ZLIB include IFS directory. -setenv ZLIB_LIB 'ZLIB' # ZLIB library. -setenv ZLIB_BNDDIR 'ZLIB_A' # ZLIB binding directory. - - -################################################################################ +. "${SCRIPTDIR}/config400.default" +if [ -f "${SCRIPTDIR}/config400.override" ] +then . "${SCRIPTDIR}/config400.override" +fi # Need to get the version definitions. -LIBSSH2_VERSION=`grep '^#define *LIBSSH2_VERSION ' \ +LIBSSH2_VERSION=$(grep '^#define *LIBSSH2_VERSION ' \ "${TOPDIR}/include/libssh2.h" | - sed 's/.*"\(.*\)".*/\1/'` -LIBSSH2_VERSION_MAJOR=`grep '^#define *LIBSSH2_VERSION_MAJOR ' \ + sed 's/.*"\(.*\)".*/\1/') +LIBSSH2_VERSION_MAJOR=$(grep '^#define *LIBSSH2_VERSION_MAJOR ' \ "${TOPDIR}/include/libssh2.h" | - sed 's/^#define *LIBSSH2_VERSION_MAJOR *\([^ ]*\).*/\1/'` -LIBSSH2_VERSION_MINOR=`grep '^#define *LIBSSH2_VERSION_MINOR ' \ + sed 's/^#define *LIBSSH2_VERSION_MAJOR *\([^ ]*\).*/\1/') +LIBSSH2_VERSION_MINOR=$(grep '^#define *LIBSSH2_VERSION_MINOR ' \ "${TOPDIR}/include/libssh2.h" | - sed 's/^#define *LIBSSH2_VERSION_MINOR *\([^ ]*\).*/\1/'` -LIBSSH2_VERSION_PATCH=`grep '^#define *LIBSSH2_VERSION_PATCH ' \ + sed 's/^#define *LIBSSH2_VERSION_MINOR *\([^ ]*\).*/\1/') +LIBSSH2_VERSION_PATCH=$(grep '^#define *LIBSSH2_VERSION_PATCH ' \ "${TOPDIR}/include/libssh2.h" | - sed 's/^#define *LIBSSH2_VERSION_PATCH *\([^ ]*\).*/\1/'` -LIBSSH2_VERSION_NUM=`grep '^#define *LIBSSH2_VERSION_NUM ' \ + sed 's/^#define *LIBSSH2_VERSION_PATCH *\([^ ]*\).*/\1/') +LIBSSH2_VERSION_NUM=$(grep '^#define *LIBSSH2_VERSION_NUM ' \ "${TOPDIR}/include/libssh2.h" | - sed 's/^#define *LIBSSH2_VERSION_NUM *0x\([^ ]*\).*/\1/'` -LIBSSH2_TIMESTAMP=`grep '^#define *LIBSSH2_TIMESTAMP ' \ + sed 's/^#define *LIBSSH2_VERSION_NUM *0x\([^ ]*\).*/\1/') +LIBSSH2_TIMESTAMP=$(grep '^#define *LIBSSH2_TIMESTAMP ' \ "${TOPDIR}/include/libssh2.h" | - sed 's/.*"\(.*\)".*/\1/'` + sed 's/.*"\(.*\)".*/\1/') export LIBSSH2_VERSION export LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH export LIBSSH2_VERSION_NUM LIBSSH2_TIMESTAMP @@ -113,7 +93,8 @@ action_needed() { [ ! -e "${1}" ] && return 0 - [ "${2}" ] || return 1 + [ -n "${2}" ] || return 1 + # shellcheck disable=SC3013 [ "${1}" -ot "${2}" ] && return 0 return 1 } @@ -130,7 +111,7 @@ canonicalize_path() { if expr "${1}" : '^/' > /dev/null then P="${1}" - else P="`pwd`/${1}" + else P="$(pwd)/${1}" fi R= @@ -141,7 +122,7 @@ canonicalize_path() do IFS="${IFSSAVE}" case "${C}" in .) ;; - ..) R=`expr "${R}" : '^\(.*/\)..*'` + ..) R="$(expr "${R}" : '^\(.*/\)..*')" ;; ?*) R="${R}${C}/" ;; @@ -150,7 +131,7 @@ canonicalize_path() done IFS="${IFSSAVE}" - echo "/`expr "${R}" : '^\(.*\)/'`" + echo "/$(expr "${R}" : '^\(.*\)/')" } @@ -166,7 +147,7 @@ make_module() MODULES="${MODULES} ${1}" MODIFSNAME="${LIBIFSNAME}/${1}.MODULE" action_needed "${MODIFSNAME}" "${2}" || return 0; - SRCDIR=`dirname \`canonicalize_path "${2}"\`` + SRCDIR="$(dirname "$(canonicalize_path "${2}")")" # #pragma convert has to be in the source file itself, i.e. # putting it in an include file makes it only active @@ -174,10 +155,12 @@ make_module() # Thus we build a temporary file with the pragma prepended to # the source file and we compile that temporary file. - echo "#line 1 \"${2}\"" > __tmpsrcf.c - echo "#pragma convert(819)" >> __tmpsrcf.c - echo "#line 1" >> __tmpsrcf.c - cat "${2}" >> __tmpsrcf.c + { + echo "#line 1 \"${2}\"" + echo "#pragma convert(819)" + echo "#line 1" + cat "${2}" + } > __tmpsrcf.c CMD="CRTCMOD MODULE(${TARGETLIB}/${1}) SRCSTMF('__tmpsrcf.c')" # CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST *SHOWINC *SHOWSYS)" CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST)" @@ -202,12 +185,17 @@ make_module() then DEFINES="${DEFINES} LIBSSH2_HAVE_ZLIB" fi - if [ "${DEFINES}" ] + if [ "${WITH_MD5}" != 'yes' ] + then DEFINES="${DEFINES} LIBSSH2_NO_MD5" + fi + + if [ -n "${DEFINES}" ] then CMD="${CMD} DEFINE(${DEFINES})" fi system "${CMD}" rm -f __tmpsrcf.c + # shellcheck disable=SC2034 LINK=YES } diff --git a/libssh2/os400/libssh2_ccsid.h b/libssh2/os400/libssh2_ccsid.h index 632effa38..7bd080c24 100644 --- a/libssh2/os400/libssh2_ccsid.h +++ b/libssh2/os400/libssh2_ccsid.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ /* CCSID conversion support. */ diff --git a/libssh2/os400/libssh2_config.h b/libssh2/os400/libssh2_config.h index d137b41a9..594a23c19 100644 --- a/libssh2/os400/libssh2_config.h +++ b/libssh2/os400/libssh2_config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIBSSH2_CONFIG_H @@ -89,9 +91,6 @@ /* use SO_NONBLOCK for non-blocking sockets */ #undef HAVE_SO_NONBLOCK -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - /* Define to 1 if you have the header file. */ #define HAVE_STDIO_H 1 diff --git a/libssh2/os400/libssh2rpg/libssh2.rpgle.in b/libssh2/os400/libssh2rpg/libssh2.rpgle.in index ea1db892d..e19848ebf 100644 --- a/libssh2/os400/libssh2rpg/libssh2.rpgle.in +++ b/libssh2/os400/libssh2rpg/libssh2.rpgle.in @@ -1,4 +1,4 @@ - * Copyright (c) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -33,12 +33,14 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause /if not defined(LIBSSH2_H_) /define LIBSSH2_H_ d LIBSSH2_COPYRIGHT... - d c '2004-2015 The libssh2 project and + + d c 'The libssh2 project and + d its contributors.' * We use underscore instead of dash when appending DEV in dev versions @@ -110,8 +112,12 @@ d libssh2_uint8_t... d s 3u 0 based(######typedef######) + d libssh2_uint16_t... + d s 5u 0 based(######typedef######) d libssh2_uint32_t... d s 10u 0 based(######typedef######) + d libssh2_int32_t... + d s 10i 0 based(######typedef######) d libssh2_uint64_t... d s 20u 0 based(######typedef######) d libssh2_int64_t... @@ -121,6 +127,10 @@ d s 10i 0 based(######typedef######) d LIBSSH2_INVALID_SOCKET... d c -1 + d LIBSSH2_SOCKET_CLOSE... + d pr extproc('close') + d like(libssh2_Cint) + d s value like(libssh2_socket_t) d libssh2_mode_t s 10u 0 based(######typedef######) d libssh2_ino_t s 10u 0 based(######typedef######) @@ -163,9 +173,9 @@ * Part of every banner, user specified or not. d LIBSSH2_SSH_BANNER... - d c 'SSH-2.0-libssh2_1.6.1_DEV' + d c 'SSH-2.0-libssh2_@LIBSSH2_VERSION@' d LIBSSH2_SSH_DEFAULT_BANNER... - d c 'SSH-2.0-libssh2_1.6.1_DEV' + d c 'SSH-2.0-libssh2_@LIBSSH2_VERSION@' * Default generate and safe prime sizes for * diffie-hellman-group-exchange-sha1. @@ -211,8 +221,8 @@ d LIBSSH2_USERAUTH_KBDINT_PROMPT... d ds based(######typedef######) d align qualified - d text * char * - d length like(libssh2_Cuint) + d text * unsigned char * + d length like(libssh2_Csize_t) d echo like(libssh2_Cuchar) d LIBSSH2_USERAUTH_KBDINT_RESPONSE... @@ -221,6 +231,22 @@ d text * char * d length like(libssh2_Cuint) + d LIBSSH2_SK_SIG_INFO... + d ds based(######typedef######) + d align qualified + d flags like(libssh2_uint8_t) + d counter like(libssh2_uint32_t) + d sig_r * unsigned char * + d sig_r_len like(libssh2_Csize_t) + d sig_s * unsigned char * + d sig_s_len like(libssh2_Csize_t) + + * Flags for SK authentication + d LIBSSH2_SK_PRESENCE_REQUIRED... + d c X'01' + d LIBSSH2_SK_VERIFICATION_REQUIRED... + d c X'04' + * libssh2_session_callback_set() constants. d LIBSSH2_CALLBACK_IGNORE... d c 0 @@ -236,6 +262,12 @@ d c 5 d LIBSSH2_CALLBACK_RECV... d c 6 + d LIBSSH2_CALLBACK_AUTHAGENT... + d c 7 + d LIBSSH2_CALLBACK_AUTHAGENT_IDENTITIES... + d c 8 + d LIBSSH2_CALLBACK_AUTHAGENT_SIGN... + d c 9 * libssh2_session_method_pref() constants. d LIBSSH2_METHOD_KEX... @@ -258,12 +290,38 @@ d c 8 d LIBSSH2_METHOD_LANG_SC... d c 9 + d LIBSSH2_METHOD_SIGN_ALGO... + d c 10 * flags. d LIBSSH2_FLAG_SIGPIPE... d c X'0001' d LIBSSH2_FLAG_COMPRESS... d c X'0002' + d LIBSSH2_FLAG_QUOTE_PATHS... + d c X'0003' + + * SK signature callback + d LIBSSH2_PRIVKEY_SK... + d ds based(######typedef######) + d align qualified + d algorithm like(libssh2_Cint) + d flags like(libssh2_uint8_t) + d application * const char * + d key_handle * const uchar * + d handle_len like(libssh2_Csize_t) + d sign_callback * procptr + d orig_abstract * void ** + + d libssh2_sign_sk... + d pr extproc('libssh2_sign_sk') + d like(libssh2_Cint) + d session * value LIBSSH2_SESSION * + d sig * unsigned char *[] + d sig_len value like(libssh2_Csize_t) + d data * value const uchar * + d data_len value like(libssh2_Csize_t) + d abstract * void * d LIBSSH2_POLLFD ds based(######typedef######) d align qualified @@ -321,6 +379,8 @@ d c 1 d LIBSSH2_HOSTKEY_HASH_SHA1... d c 2 + d LIBSSH2_HOSTKEY_HASH_SHA256... + d c 3 * Hostkey Types. d LIBSSH2_HOSTKEY_TYPE_UNKNOWN... @@ -329,6 +389,14 @@ d c 1 d LIBSSH2_HOSTKEY_TYPE_DSS... d c 2 + d LIBSSH2_HOSTKEY_TYPE_ECDSA_256... + d c 3 + d LIBSSH2_HOSTKEY_TYPE_ECDSA_384... + d c 4 + d LIBSSH2_HOSTKEY_TYPE_ECDSA_521... + d c 5 + d LIBSSH2_HOSTKEY_TYPE_ED25519... + d c 6 * Disconnect Codes (defined by SSH protocol). d SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT... @@ -466,6 +534,20 @@ d c -45 d LIBSSH2_ERROR_KNOWN_HOSTS... d c -46 + d LIBSSH2_ERROR_CHANNEL_WINDOW_FULL... + d c -47 + d LIBSSH2_ERROR_KEYFILE_AUTH_FAILED... + d c -48 + d LIBSSH2_ERROR_RANDGEN... + d c -49 + d LIBSSH2_ERROR_MISSING_USERAUTH_BANNER... + d c -50 + d LIBSSH2_ERROR_ALGO_UNSUPPORTED... + d c -51 + d LIBSSH2_ERROR_MAC_FAILURE... + d c -52 + d LIBSSH2_ERROR_HASH_INIT... + d c -53 * this is a define to provide the old (<= 1.2.7) name. d LIBSSH2_ERROR_BANNER_NONE... @@ -540,6 +622,17 @@ d pr * extproc('libssh2_session_abstract') void * * d session * value LIBSSH2_SESSION * + d libssh2_cb_generic_ptr... + d s * based(######typedef######) procptr + + d libssh2_session_callback_set2... + d pr extproc( + d 'libssh2_session_callback_set2') + d like(libssh2_cb_generic_ptr) + d session * value LIBSSH2_SESSION * + d cbtype value like(libssh2_Cint) + d callback value like(libssh2_cb_generic_ptr) + d libssh2_session_callback_set... d pr * extproc( void * d 'libssh2_session_callback_set') @@ -553,6 +646,7 @@ d session * value LIBSSH2_SESSION * d banner * value options(*string) const char * + /if not defined(LIBSSH2_NO_DEPRECATED) d libssh2_banner_set... d pr extproc('libssh2_banner_set') d like(libssh2_Cint) @@ -564,6 +658,7 @@ d like(libssh2_Cint) d session * value LIBSSH2_SESSION * d sock value like(libssh2_Cint) + /endif d libssh2_session_handshake... d pr extproc('libssh2_session_handshake') @@ -662,6 +757,12 @@ d username * value options(*string) const char * d username_len value like(libssh2_Cuint) + d libssh2_userauth_banner... + d pr extproc('libssh2_userauth_banner') + d like(libssh2_Cint) + d session * value LIBSSH2_SESSION * + d banner * char * + d libssh2_userauth_authenticated... d pr extproc( d 'libssh2_userauth_authenticated') @@ -794,6 +895,24 @@ d response_callback... d * value procptr + d libssh2_userauth_publickey_sk... + d pr extproc( + d 'libssh2_userauth_publickey_sk') + d like(libssh2_Cint) + d session * value LIBSSH2_SESSION * + d username * value options(*string) const char * + d username_len value like(libssh2_Csize_t) + d pubkeydata * value const uchar * + d pubkeydata_len... + d value like(libssh2_Csize_t) + d privatekeydata... + d * value options(*string) const char * + d privatekeydata_len... + d value like(libssh2_Csize_t) + d passphrase * value options(*string) const char * + d sign_callback * value procptr + d abstract * void * + d libssh2_poll pr extproc('libssh2_poll') d like(libssh2_Cint) d fds * value LIBSSH2_POLLFD * @@ -858,6 +977,14 @@ d host * value options(*string) const char * d port value like(libssh2_Cint) + d libssh2_channel_direct_streamlocal_ex... + d pr * extproc('libssh2_channel_direct- LIBSSH2_CHANNEL * + d _streamlocal_ex') + d session * value LIBSSH2_SESSION * + d socket_path * value options(*string) const char * + d shost * value options(*string) const char * + d sport value like(libssh2_Cint) + d libssh2_channel_forward_listen_ex... d pr * extproc( LIBSSH2_LISTENER * d 'libssh2_channel_forward_listen_ex') @@ -902,6 +1029,12 @@ d varname * value options(*string) const char * d value * value options(*string) const char * + d libssh2_channel_request_auth_agent... + d pr extproc( + d 'libssh2_channel_request_auth_agent') + d like(libssh2_Cint) + d channel * value LIBSSH2_CHANNEL * + d libssh2_channel_request_pty_ex... d pr extproc( d 'libssh2_channel_request_pty_ex') @@ -961,6 +1094,20 @@ d channel * value LIBSSH2_CHANNEL * d screen_number value like(libssh2_Cint) + d libssh2_channel_signal_ex... + d pr extproc('libssh2_channel_signal_ex') + d like(libssh2_Cint) + d channel * value LIBSSH2_CHANNEL * + d signame * value options(*string) const char * + d signame_len value like(libssh2_Csize_t) + + * C macro implementation + d libssh2_channel_signal... + d pr extproc('libssh2_channel_signal_ex') + d like(libssh2_Cint) + d channel * value LIBSSH2_CHANNEL * + d signame * value options(*string) const char * + d libssh2_channel_process_startup... d pr extproc( d 'libssh2_channel_process_startup') @@ -1038,6 +1185,16 @@ d like(libssh2_Culong) d channel * value LIBSSH2_CHANNEL * + /if not defined(LIBSSH2_NO_DEPRECATED) + d libssh2_channel_receive_window_adjust... + d pr extproc('libssh2_channel_receive_win- + d dow_adjust') + d like(libssh2_Culong) + d channel * value LIBSSH2_CHANNEL * + d adjustment value like(libssh2_Culong) + d force value like(libssh2_Cuchar) + /endif + d libssh2_channel_receive_window_adjust2... d pr extproc('libssh2_channel_receive_win- d dow_adjust2') @@ -1117,6 +1274,26 @@ d like(libssh2_Clong) d session * value LIBSSH2_SESSION * + d libssh2_session_set_read_timeout... + d pr extproc( + d 'libssh2_session_set_read_timeout') + d session * value LIBSSH2_SESSION * + d timeout value like(libssh2_Clong) + + d libssh2_session_get_read_timeout... + d pr extproc( + d 'libssh2_session_get_read_timeout') + d like(libssh2_Clong) + d session * value LIBSSH2_SESSION * + + /if not defined(LIBSSH2_NO_DEPRECATED) + d libssh2_channel_handle_extended_data... + d pr extproc('libssh2_channel_handle_exte- + d nded_data') + d channel * value LIBSSH2_CHANNEL * + d ignore_mode value like(libssh2_Cint) + /endif + d libssh2_channel_handle_extended_data2... d pr extproc('libssh2_channel_handle_exte- d nded_data2') @@ -1124,8 +1301,16 @@ d channel * value LIBSSH2_CHANNEL * d ignore_mode value like(libssh2_Cint) + /if not defined(LIBSSH2_NO_DEPRECATED) * libssh2_channel_ignore_extended_data() is defined below for BC with * version 0.1. + * C macro implementation. + d libssh2_channel_ignore_extended_data... + d pr extproc('libssh2_channel- + d _ignore_extended_data') + d channel * value LIBSSH2_CHANNEL * + d ignore value like(libssh2_Cint) + /endif d LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA... d c -1 @@ -1201,6 +1386,14 @@ d like(libssh2_Cint) d channel * value LIBSSH2_CHANNEL * + /if not defined(LIBSSH2_NO_DEPRECATED) + d libssh2_scp_recv... + d pr * extproc('libssh2_scp_recv') LIBSSH2_CHANNEL * + d session * value LIBSSH2_SESSION * + d path * value options(*string) const char * + d sb * value struct stat * + /endif + * Use libssh2_scp_recv2 for large (> 2GB) file support. d libssh2_scp_recv2... d pr * extproc('libssh2_scp_recv2') LIBSSH2_CHANNEL * @@ -1234,6 +1427,7 @@ d mode value like(libssh2_Cint) d size value like(libssh2_int64_t) + * DEPRECATED d libssh2_base64_decode... d pr extproc('libssh2_base64_decode') d like(libssh2_Cint) @@ -1249,6 +1443,26 @@ d req_version_num... d value like(libssh2_Cint) + d libssh2_crypto_engine_t... + d s based(######typedef######) + d like(libssh2_Cenum) + d libssh2_no_crypto... + d c 0 + d libssh2_openssl... + d c 1 + d libssh2_gcrypt... + d c 2 + d libssh2_mbedtls... + d c 3 + d libssh2_wincng... + d c 4 + d libssh2_os400qc3... + d c 5 + + d libssh2_crypto_engine... + d pr extproc('libssh2_crypto_engine') + d like(libssh2_crypto_engine_t) + d HAVE_LIBSSH2_KNOWNHOST_API... since 1.1.1 d c X'010101' d HAVE_LIBSSH2_VERSION_API... since 1.1 @@ -1311,9 +1525,9 @@ d LIBSSH2_KNOWNHOST_KEYENC_BASE64... d c X'00020000' - * type of key (3 bits). + * type of key (4 bits). d LIBSSH2_KNOWNHOST_KEY_MASK... - d c X'001C0000' + d c X'003C0000' d LIBSSH2_KNOWNHOST_KEY_SHIFT... d c 18 d LIBSSH2_KNOWNHOST_KEY_RSA1... @@ -1322,8 +1536,16 @@ d c X'00080000' d LIBSSH2_KNOWNHOST_KEY_SSHDSS... d c X'000C0000' - d LIBSSH2_KNOWNHOST_KEY_UNKNOWN... + d LIBSSH2_KNOWNHOST_KEY_ECDSA_256... + d c X'00100000' + d LIBSSH2_KNOWNHOST_KEY_ECDSA_384... + d c X'00140000' + d LIBSSH2_KNOWNHOST_KEY_ECDSA_521... + d c X'00180000' + d LIBSSH2_KNOWNHOST_KEY_ED25519... d c X'001C0000' + d LIBSSH2_KNOWNHOST_KEY_UNKNOWN... + d c X'003C0000' d libssh2_knownhost_add... d pr extproc('libssh2_knownhost_add') @@ -1609,6 +1831,24 @@ d username * value options(*string) const char * d identity likeds(libssh2_agent_publickey) + * libssh2_agent_sign() + * + * Sign a payload using a system-installed ssh-agent. + * + * Returns 0 if succeeded, or a negative value for error. + + d libssh2_agent_sign... + d pr extproc('libssh2_agent_sign') + d like(libssh2_Cint) + d agent * value LIBSSH2_AGENT * + d identity likeds(libssh2_agent_publickey) + d sig * unsigned char * + d s_len like(libssh2_Csize_t) + d data * value const uchar * + d d_len value like(libssh2_Csize_t) + d method * value options(*string) const char * + d method_len value like(libssh2_Cuint) + * libssh2_agent_disconnect() * * Close a connection to an ssh-agent. @@ -1629,6 +1869,24 @@ d pr extproc('libssh2_agent_free') d agent * value LIBSSH2_AGENT * + * libssh2_agent_set_identity_path() + * + * Allows a custom agent identity socket path beyond SSH_AUTH_SOCK env + + d libssh2_agent_set_identity_path... + d pr extproc( + d 'libssh2_agent_set_identity_path') + d agent * value LIBSSH2_AGENT * + d path * value options(*string) const char * + + * libssh2_agent_get_identity_path() + * + * Returns the custom agent identity socket path if set + + d libssh2_agent_get_identity_path... + d pr * extproc( const char * + d 'libssh2_agent_get_identity_path') + d agent * value LIBSSH2_AGENT * * libssh2_keepalive_config() * diff --git a/libssh2/os400/libssh2rpg/libssh2_ccsid.rpgle.in b/libssh2/os400/libssh2rpg/libssh2_ccsid.rpgle.in index 345fa6303..11364a7dd 100644 --- a/libssh2/os400/libssh2rpg/libssh2_ccsid.rpgle.in +++ b/libssh2/os400/libssh2rpg/libssh2_ccsid.rpgle.in @@ -1,4 +1,4 @@ - * Copyright (c) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -33,6 +33,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause /if not defined(LIBSSH2_CCSID_H_) /define LIBSSH2_CCSID_H_ diff --git a/libssh2/os400/libssh2rpg/libssh2_publickey.rpgle b/libssh2/os400/libssh2rpg/libssh2_publickey.rpgle index 4387b0d3a..4aabfbaba 100644 --- a/libssh2/os400/libssh2rpg/libssh2_publickey.rpgle +++ b/libssh2/os400/libssh2rpg/libssh2_publickey.rpgle @@ -1,4 +1,4 @@ - * Copyright (c) 2015, Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -40,6 +40,8 @@ * * For more information on the publickey subsystem, * refer to IETF draft: secsh-publickey + * + * SPDX-License-Identifier: BSD-3-Clause /if not defined(LIBSSH2_PUBLICKEY_H_) /define LIBSSH2_PUBLICKEY_H_ diff --git a/libssh2/os400/libssh2rpg/libssh2_sftp.rpgle b/libssh2/os400/libssh2rpg/libssh2_sftp.rpgle index f4068fc8f..4ccb81b57 100644 --- a/libssh2/os400/libssh2rpg/libssh2_sftp.rpgle +++ b/libssh2/os400/libssh2rpg/libssh2_sftp.rpgle @@ -1,4 +1,4 @@ - * Copyright (c) 2015, Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -33,6 +33,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause /if not defined(LIBSSH2_SFTP_H_) /define LIBSSH2_SFTP_H_ @@ -77,6 +79,10 @@ d LIBSSH2_SFTP_REALPATH... d c 2 + * Flags for sftp_mkdir() + d LIBSSH2_SFTP_DEFAULT_MODE... + d c -1 + * SFTP attribute flag bits. d LIBSSH2_SFTP_ATTR_SIZE... d c X'00000001' @@ -95,7 +101,7 @@ d LIBSSH2_SFTP_ST_NOSUID... d c X'00000002' - d #LIBSSH2_SFTP_ATTRIBUTES... + d LIBSSH2_SFTP_ATTRIBUTES... d ds based(######typedef######) d align qualified * If flags & ATTR_* bit is set, then the value in this struct will be @@ -334,8 +340,7 @@ * C macro implementation. d libssh2_sftp_open... - d pr * extproc('libssh2_sftp_open') LIBSSH2_SFTP_HANDLE - d * + d pr * extproc('libssh2_sftp_open') LIBSSH2_SFTP_HANDLE* d sftp * value LIBSSH2_SFTP * d filename * value options(*string) const char * d flags value like(libssh2_Culong) @@ -344,16 +349,34 @@ * C macro libssh2_sftp_opendir implementation. * Renamed to avoid upper/lower case name clash. d libssh2_sftp_open_dir... - d pr * extproc('libssh2_sftp_opendir') LIBSSH2_SFTP_HANDLE - d * + d pr * extproc('libssh2_sftp_opendir') LIBSSH2_SFTP_HANDLE* d sftp * value LIBSSH2_SFTP * d path * value options(*string) const char * + d libssh2_sftp_open_ex_r... + d pr * extproc('libssh2_sftp_open_ex_r') LIBSSH2_SFTP_HANDLE* + d sftp * value LIBSSH2_SFTP * + d filename * value options(*string) const char * + d filename_len value like(libssh2_Csize_t) + d flags value like(libssh2_Culong) + d mode value like(libssh2_Clong) + d open_type value like(libssh2_Cint) + d attrs likeds(LIBSSH2_SFTP_ATTRIBUTES) + + * C macro implementation. + d libssh2_sftp_open_r... + d pr * extproc('libssh2_sftp_open_r') LIBSSH2_SFTP_HANDLE* + d sftp * value LIBSSH2_SFTP * + d filename * value options(*string) const char * + d flags value like(libssh2_Culong) + d mode value like(libssh2_Clong) + d attrs likeds(LIBSSH2_SFTP_ATTRIBUTES) + d libssh2_sftp_read... d pr extproc('libssh2_sftp_read') d like(libssh2_Cssize_t) d handle * value LIBSSH2_SFTP_HANDLE* - d buffer * value options(*string) char * + d buffer * value char * d buffer_maxlen value like(libssh2_Csize_t) d libssh2_sftp_readdir_ex... diff --git a/libssh2/os400/macros.h b/libssh2/os400/macros.h index 1e809e17c..fa2b22ee1 100644 --- a/libssh2/os400/macros.h +++ b/libssh2/os400/macros.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * +* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIBSSH2_MACROS_H_ @@ -90,6 +92,8 @@ libssh2_channel_request_pty_size(LIBSSH2_CHANNEL *channel, LIBSSH2_API int libssh2_channel_x11_req(LIBSSH2_CHANNEL *channel, int screen_number); LIBSSH2_API int +libssh2_channel_signal(LIBSSH2_CHANNEL *channel, const char *signame); +LIBSSH2_API int libssh2_channel_shell(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_exec(LIBSSH2_CHANNEL *channel, const char *command); @@ -98,16 +102,20 @@ libssh2_channel_subsystem(LIBSSH2_CHANNEL *channel, const char *subsystem); LIBSSH2_API ssize_t libssh2_channel_read(LIBSSH2_CHANNEL *channel, char *buf, size_t buflen); LIBSSH2_API ssize_t -libssh2_channel_read_stderr(LIBSSH2_CHANNEL *channel, char *buf, size_t buflen); +libssh2_channel_read_stderr(LIBSSH2_CHANNEL *channel, + char *buf, size_t buflen); LIBSSH2_API unsigned long libssh2_channel_window_read(LIBSSH2_CHANNEL *channel); LIBSSH2_API ssize_t -libssh2_channel_write(LIBSSH2_CHANNEL *channel, const char *buf, size_t buflen); +libssh2_channel_write(LIBSSH2_CHANNEL *channel, + const char *buf, size_t buflen); LIBSSH2_API ssize_t libssh2_channel_write_stderr(LIBSSH2_CHANNEL *channel, const char *buf, size_t buflen); LIBSSH2_API unsigned long libssh2_channel_window_write(LIBSSH2_CHANNEL *channel); +LIBSSH2_API void +libssh2_channel_ignore_extended_data(LIBSSH2_CHANNEL *channel, int ignore); LIBSSH2_API int libssh2_channel_flush(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_flush_stderr(LIBSSH2_CHANNEL *channel); LIBSSH2_API LIBSSH2_CHANNEL * @@ -135,6 +143,10 @@ libssh2_sftp_open(LIBSSH2_SFTP *sftp, const char *filename, unsigned long flags, long mode); LIBSSH2_API LIBSSH2_SFTP_HANDLE * libssh2_sftp_opendir(LIBSSH2_SFTP *sftp, const char *path); +LIBSSH2_API LIBSSH2_SFTP_HANDLE * +libssh2_sftp_open_r(LIBSSH2_SFTP *sftp, const char *filename, + unsigned long flags, long mode, + LIBSSH2_SFTP_ATTRIBUTES *attrs); LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs); diff --git a/libssh2/os400/make-include.sh b/libssh2/os400/make-include.sh old mode 100644 new mode 100755 index 2cb7b7260..5fa911afd --- a/libssh2/os400/make-include.sh +++ b/libssh2/os400/make-include.sh @@ -1,11 +1,13 @@ #!/bin/sh +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause # # Installation of the header files in the OS/400 library. # -SCRIPTDIR=`dirname "${0}"` +SCRIPTDIR=$(dirname "${0}") . "${SCRIPTDIR}/initscript.sh" -cd "${TOPDIR}/include" +cd "${TOPDIR}/include" || exit 1 # Create the OS/400 source program file for the header files. @@ -45,11 +47,11 @@ copy_hfile() # Copy the header files. for HFILE in *.h "${TOPDIR}/os400/libssh2_ccsid.h" -do DEST="${SRCPF}/`db2_name \"${HFILE}\"`.MBR" +do DEST="${SRCPF}/$(db2_name "${HFILE}").MBR" if action_needed "${DEST}" "${HFILE}" then copy_hfile "${DEST}" "${HFILE}" - IFSDEST="${IFSINCLUDE}/`basename \"${HFILE}\"`" + IFSDEST="${IFSINCLUDE}/$(basename "${HFILE}")" rm -f "${IFSDEST}" ln -s "${DEST}" "${IFSDEST}" fi diff --git a/libssh2/os400/make-rpg.sh b/libssh2/os400/make-rpg.sh old mode 100644 new mode 100755 index c8a264724..68b500091 --- a/libssh2/os400/make-rpg.sh +++ b/libssh2/os400/make-rpg.sh @@ -1,11 +1,13 @@ #!/bin/sh +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause # # Installation of the ILE/RPG header files in the OS/400 library. # -SCRIPTDIR=`dirname "${0}"` +SCRIPTDIR=$(dirname "${0}") . "${SCRIPTDIR}/initscript.sh" -cd "${TOPDIR}/os400/libssh2rpg" +cd "${TOPDIR}/os400/libssh2rpg" || exit 1 # Create the OS/400 source program file for the ILE/RPG header files. @@ -22,9 +24,9 @@ fi # Map file names to DB2 name syntax. for HFILE in *.rpgle *.rpgle.in -do NAME="`basename \"${HFILE}\" .in`" - VAR="`basename \"${NAME}\" .rpgle`" - VAL="`db2_name \"${NAME}\"`" +do NAME="$(basename "${HFILE}" .in)" + VAR="$(basename "${NAME}" .rpgle)" + VAL="$(db2_name "${NAME}")" eval "VAR_${VAR}=\"${VAL}\"" echo "${VAR} s/${VAR}/${VAL}/g" @@ -62,7 +64,7 @@ fi for HFILE in *.rpgle *.rpgle.in do IFSCMD="cat \"${HFILE}\"" DB2CMD="change_include < \"${HFILE}\"" - IFSFILE="`basename \"${HFILE}\" .in`" + IFSFILE="$(basename "${HFILE}" .in)" case "${HFILE}" in @@ -77,7 +79,7 @@ do IFSCMD="cat \"${HFILE}\"" then eval "${IFSCMD}" > "${IFSDEST}" fi - eval DB2MBR="\"\${VAR_`basename \"${IFSDEST}\" .rpgle`}\"" + eval DB2MBR="\"\${VAR_$(basename "${IFSDEST}" .rpgle)}\"" DB2DEST="${SRCPF}/${DB2MBR}.MBR" if action_needed "${DB2DEST}" "${HFILE}" @@ -85,7 +87,7 @@ do IFSCMD="cat \"${HFILE}\"" # Need to translate to target CCSID. - CMD="CPY OBJ('`pwd`/tmphdrfile') TOOBJ('${DB2DEST}')" + CMD="CPY OBJ('$(pwd)/tmphdrfile') TOOBJ('${DB2DEST}')" CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" system "${CMD}" fi diff --git a/libssh2/os400/make-src.sh b/libssh2/os400/make-src.sh old mode 100644 new mode 100755 index 3d352cbe9..4c399da8c --- a/libssh2/os400/make-src.sh +++ b/libssh2/os400/make-src.sh @@ -1,11 +1,13 @@ #!/bin/sh +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause # # libssh2 compilation script for the OS/400. # -SCRIPTDIR=`dirname "${0}"` +SCRIPTDIR=$(dirname "${0}") . "${SCRIPTDIR}/initscript.sh" -cd "${TOPDIR}/src" +cd "${TOPDIR}/src" || exit 1 # Function to extract external prototypes from header files. @@ -46,10 +48,12 @@ fi # Create and compile the identification source file. -echo '#pragma comment(user, "libssh2 version '"${LIBSSH2_VERSION}"'")' > os400.c -echo '#pragma comment(user, __DATE__)' >> os400.c -echo '#pragma comment(user, __TIME__)' >> os400.c -echo '#pragma comment(copyright, "See COPYING file. OS/400 version by P. Monnerat")' >> os400.c +{ + echo '#pragma comment(user, "libssh2 version '"${LIBSSH2_VERSION}"'")' + echo '#pragma comment(user, __DATE__)' + echo '#pragma comment(user, __TIME__)' + echo '#pragma comment(copyright, "See COPYING file. OS/400 version by P. Monnerat")' +} > os400.c make_module OS400 os400.c LINK= # No need to rebuild service program yet. MODULES= @@ -78,28 +82,28 @@ fi # Get source list. -cat Makefile.inc | - sed -e ':begin' \ - -e '/\\$/{' \ - -e 's/\\$/ /' \ - -e 'N' \ - -e 'bbegin' \ - -e '}' \ - -e 's/\n//g' \ - -e 's/[[:space:]]*$//' \ - -e 's/^\([A-Za-z][A-Za-z0-9_]*\)[[:space:]]*=[[:space:]]*\(.*\)/\1="\2"/' \ - -e 's/\$(\([A-Za-z][A-Za-z0-9_]*\))/${\1}/g' \ - > tmpscript.sh +sed -e ':begin' \ + -e '/\\$/{' \ + -e 's/\\$/ /' \ + -e 'N' \ + -e 'bbegin' \ + -e '}' \ + -e 's/\n//g' \ + -e 's/[[:space:]]*$//' \ + -e 's/^\([A-Za-z][A-Za-z0-9_]*\)[[:space:]]*=[[:space:]]*\(.*\)/\1="\2"/' \ + -e 's/\$(\([A-Za-z][A-Za-z0-9_]*\))/${\1}/g' \ + < Makefile.inc > tmpscript.sh . ./tmpscript.sh # Compile the sources into modules. -INCLUDES="'`pwd`'" +# shellcheck disable=SC2034 +INCLUDES="'$(pwd)'" for SRC in "${TOPDIR}/os400/os400sys.c" "${TOPDIR}/os400/ccsid.c" \ ${CSOURCES} macros.c -do MODULE=`db2_name "${SRC}"` +do MODULE=$(db2_name "${SRC}") make_module "${MODULE}" "${SRC}" done @@ -110,7 +114,7 @@ if action_needed "${LIBIFSNAME}/${STATBNDDIR}.BNDDIR" then LINK=YES fi -if [ "${LINK}" ] +if [ -n "${LINK}" ] then rm -rf "${LIBIFSNAME}/${STATBNDDIR}.BNDDIR" CMD="CRTBNDDIR BNDDIR(${TARGETLIB}/${STATBNDDIR})" CMD="${CMD} TEXT('libssh2 API static binding directory')" @@ -143,10 +147,10 @@ fi # Gather the list of symbols to export. -EXPORTS=`cat "${TOPDIR}"/include/*.h "${TOPDIR}/os400/macros.h" \ +EXPORTS=$(cat "${TOPDIR}"/include/*.h "${TOPDIR}/os400/macros.h" \ "${TOPDIR}/os400/libssh2_ccsid.h" | extproto | - sed -e 's/(.*//;s/[^A-Za-z0-9_]/ /g;s/ *$//;s/^.* //'` + sed -e 's/(.*//;s/[^A-Za-z0-9_]/ /g;s/ *$//;s/^.* //') # Create the service program exportation file in DB2 member if needed. @@ -156,7 +160,7 @@ if action_needed "${BSF}" Makefile.am then LINK=YES fi -if [ "${LINK}" ] +if [ -n "${LINK}" ] then echo " STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('LIBSSH2_${SONAME}')" \ > "${BSF}" for EXPORT in ${EXPORTS} @@ -173,7 +177,7 @@ if action_needed "${LIBIFSNAME}/${SRVPGM}.SRVPGM" then LINK=YES fi -if [ "${LINK}" ] +if [ -n "${LINK}" ] then CMD="CRTSRVPGM SRVPGM(${TARGETLIB}/${SRVPGM})" CMD="${CMD} SRCFILE(${TARGETLIB}/TOOLS) SRCMBR(BNDSRC)" CMD="${CMD} MODULE(${TARGETLIB}/OS400)" @@ -197,7 +201,7 @@ if action_needed "${LIBIFSNAME}/${DYNBNDDIR}.BNDDIR" then LINK=YES fi -if [ "${LINK}" ] +if [ -n "${LINK}" ] then rm -rf "${LIBIFSNAME}/${DYNBNDDIR}.BNDDIR" CMD="CRTBNDDIR BNDDIR(${TARGETLIB}/${DYNBNDDIR})" CMD="${CMD} TEXT('libssh2 API dynamic binding directory')" diff --git a/libssh2/os400/make.sh b/libssh2/os400/make.sh old mode 100644 new mode 100755 index 0cfa7ec61..84640db7b --- a/libssh2/os400/make.sh +++ b/libssh2/os400/make.sh @@ -1,13 +1,15 @@ #!/bin/sh +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause # # libssh2 compilation script for the OS/400. # # # This is a shell script since make is not a standard component of OS/400. -SCRIPTDIR=`dirname "${0}"` +SCRIPTDIR=$(dirname "${0}") . "${SCRIPTDIR}/initscript.sh" -cd "${TOPDIR}" +cd "${TOPDIR}" || exit 1 # Create the OS/400 library if it does not exist. @@ -32,7 +34,7 @@ fi for TEXT in "${TOPDIR}/COPYING" "${SCRIPTDIR}/README400" \ "${TOPDIR}/NEWS" "${TOPDIR}/README" "${TOPDIR}/docs/AUTHORS" \ "${TOPDIR}/docs/BINDINGS.md" -do MEMBER="${LIBIFSNAME}/DOCS.FILE/`db2_name \"${TEXT}\"`.MBR" +do MEMBER="${LIBIFSNAME}/DOCS.FILE/$(db2_name "${TEXT}").MBR" if action_needed "${MEMBER}" "${TEXT}" then CMD="CPY OBJ('${TEXT}') TOOBJ('${MEMBER}') TOCCSID(${TGTCCSID})" @@ -42,6 +44,36 @@ do MEMBER="${LIBIFSNAME}/DOCS.FILE/`db2_name \"${TEXT}\"`.MBR" done +# Create the RPGXAMPLES source file if it does not exist. + +if action_needed "${LIBIFSNAME}/RPGXAMPLES.FILE" +then CMD="CRTSRCPF FILE(${TARGETLIB}/RPGXAMPLES) RCDLEN(240)" + CMD="${CMD} CCSID(${TGTCCSID}) TEXT('ILE/RPG examples')" + system "${CMD}" +fi + + +# Copy RPG examples if needed. + +for EXAMPLE in "${SCRIPTDIR}/rpg-examples"/* +do MEMBER="$(basename "${EXAMPLE}")" + IFSMEMBER="${LIBIFSNAME}/RPGXAMPLES.FILE/$(db2_name "${MEMBER}").MBR" + + [ -e "${EXAMPLE}" ] || continue + + if action_needed "${IFSMEMBER}" "${EXAMPLE}" + then CMD="CPY OBJ('${EXAMPLE}') TOOBJ('${IFSMEMBER}')" + CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" + system "${CMD}" + MBRTEXT=$(sed -e '1!d;/^ \*/!d;s/^ *\* *//' \ + -e 's/ *$//;s/'"'"'/&&/g' < "${EXAMPLE}") + CMD="CHGPFM FILE(${TARGETLIB}/RPGXAMPLES) MBR(${MEMBER})" + CMD="${CMD} SRCTYPE(RPGLE) TEXT('${MBRTEXT}')" + system "${CMD}" + fi +done + + # Build in each directory. for SUBDIR in include rpg src diff --git a/libssh2/os400/os400sys.c b/libssh2/os400/os400sys.c index db67876be..081a26ef8 100644 --- a/libssh2/os400/os400sys.c +++ b/libssh2/os400/os400sys.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Patrick Monnerat, D+H + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ /* OS/400 additional support. */ @@ -75,106 +77,54 @@ static int -convert_sockaddr(struct sockaddr_storage * dstaddr, - const struct sockaddr * srcaddr, int srclen) - +convert_sockaddr(struct sockaddr_storage *dstaddr, + const struct sockaddr *srcaddr, int srclen) { - const struct sockaddr_un * srcu; - struct sockaddr_un * dstu; - unsigned int i; - unsigned int dstsize; + const struct sockaddr_un *srcu; + struct sockaddr_un *dstu; + unsigned int i; + unsigned int dstsize; - /* Convert a socket address into job CCSID, if needed. */ + /* Convert a socket address into job CCSID, if needed. */ - if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) + - sizeof srcaddr->sa_family || srclen > sizeof *dstaddr) { - errno = EINVAL; - return -1; - } - - memcpy((char *) dstaddr, (char *) srcaddr, srclen); - - switch (srcaddr->sa_family) { - - case AF_UNIX: - srcu = (const struct sockaddr_un *) srcaddr; - dstu = (struct sockaddr_un *) dstaddr; - dstsize = sizeof *dstaddr - offsetof(struct sockaddr_un, sun_path); - srclen -= offsetof(struct sockaddr_un, sun_path); - i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen); - dstu->sun_path[i] = '\0'; - i += offsetof(struct sockaddr_un, sun_path); - srclen = i; - } - - return srclen; -} - - -int -_libssh2_os400_connect(int sd, struct sockaddr * destaddr, int addrlen) - -{ - int i; - struct sockaddr_storage laddr; - - i = convert_sockaddr(&laddr, destaddr, addrlen); - - if(i < 0) - return -1; - - return connect(sd, (struct sockaddr *) &laddr, i); -} - - -int -_libssh2_os400_vsnprintf(char *dst, size_t len, const char *fmt, va_list args) -{ - size_t l = 4096; - int i; - char *buf; - - if (!dst || !len) { + if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) + + sizeof(srcaddr->sa_family) || srclen > sizeof(*dstaddr)) { errno = EINVAL; return -1; } - if (l < len) - l = len; + memcpy((char *) dstaddr, (char *) srcaddr, srclen); - buf = alloca(l); + switch(srcaddr->sa_family) { - if (!buf) { - errno = ENOMEM; - return -1; + case AF_UNIX: + srcu = (const struct sockaddr_un *) srcaddr; + dstu = (struct sockaddr_un *) dstaddr; + dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path); + srclen -= offsetof(struct sockaddr_un, sun_path); + i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, + dstsize - 1, srclen); + dstu->sun_path[i] = '\0'; + i += offsetof(struct sockaddr_un, sun_path); + srclen = i; } - i = vsprintf(buf, fmt, args); - - if (i < 0) - return i; - - if (--len > i) - len = i; - - if (len) - memcpy(dst, buf, len); - - dst[len] = '\0'; - return len; + return srclen; } -/* VARARGS3 */ -int -_libssh2_os400_snprintf(char *dst, size_t len, const char *fmt, ...) -{ - va_list args; - int ret; - va_start(args, fmt); - ret = _libssh2_os400_vsnprintf(dst, len, fmt, args); - va_end(args); - return ret; +int +_libssh2_os400_connect(int sd, struct sockaddr *destaddr, int addrlen) +{ + int i; + struct sockaddr_storage laddr; + + i = convert_sockaddr(&laddr, destaddr, addrlen); + + if(i < 0) + return -1; + + return connect(sd, (struct sockaddr *) &laddr, i); } @@ -186,11 +136,11 @@ _libssh2_os400_inflateInit_(z_streamp strm, char *ebcversion; int i; - if (!version) + if(!version) return Z_VERSION_ERROR; i = strlen(version); ebcversion = alloca(i + 1); - if (!ebcversion) + if(!ebcversion) return Z_VERSION_ERROR; i = QadrtConvertA2E(ebcversion, version, i, i - 1); ebcversion[i] = '\0'; @@ -204,11 +154,11 @@ _libssh2_os400_deflateInit_(z_streamp strm, int level, char *ebcversion; int i; - if (!version) + if(!version) return Z_VERSION_ERROR; i = strlen(version); ebcversion = alloca(i + 1); - if (!ebcversion) + if(!ebcversion) return Z_VERSION_ERROR; i = QadrtConvertA2E(ebcversion, version, i, i - 1); ebcversion[i] = '\0'; diff --git a/libssh2/src/CMakeLists.txt b/libssh2/src/CMakeLists.txt index 5bbed5e51..512c64ed3 100644 --- a/libssh2/src/CMakeLists.txt +++ b/libssh2/src/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright (c) 2014 Alexander Lamaison -# Copyright (c) 2023 Viktor Szakats +# Copyright (C) Alexander Lamaison +# Copyright (C) Viktor Szakats # # Redistribution and use in source and binary forms, # with or without modification, are permitted provided @@ -33,40 +33,44 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. +# +# SPDX-License-Identifier: BSD-3-Clause + +set(_libssh2_soversion 1) +set(_libssh2_libversion 1.0.1) if(CRYPTO_BACKEND) list(APPEND PRIVATE_COMPILE_DEFINITIONS ${CRYPTO_BACKEND_DEFINE}) list(APPEND PRIVATE_INCLUDE_DIRECTORIES ${CRYPTO_BACKEND_INCLUDE_DIR}) + add_feature_info("Crypto backend" ON "${CRYPTO_BACKEND}") else() message(FATAL_ERROR "No suitable cryptography backend found.") endif() ## Options +unset(_libssh2_definitions) + option(CLEAR_MEMORY "Enable clearing of memory before being freed" ON) if(NOT CLEAR_MEMORY) - list(APPEND libssh2_DEFINITIONS LIBSSH2_NO_CLEAR_MEMORY) + list(APPEND _libssh2_definitions "LIBSSH2_NO_CLEAR_MEMORY") endif() -option(ENABLE_ZLIB_COMPRESSION "Use zlib for compression") +option(ENABLE_ZLIB_COMPRESSION "Use zlib for compression" OFF) add_feature_info(Compression ENABLE_ZLIB_COMPRESSION "using zlib for compression") if(ENABLE_ZLIB_COMPRESSION) find_package(ZLIB REQUIRED) list(APPEND libssh2_INCLUDE_DIRS ${ZLIB_INCLUDE_DIRS}) - list(APPEND LIBRARIES ${ZLIB_LIBRARIES}) - list(APPEND PC_REQUIRES_PRIVATE zlib) + list(APPEND LIBSSH2_LIBS ${ZLIB_LIBRARIES}) + list(APPEND LIBSSH2_PC_REQUIRES_PRIVATE "zlib") if(ZLIB_FOUND) - list(APPEND libssh2_DEFINITIONS LIBSSH2_HAVE_ZLIB) + list(APPEND _libssh2_definitions "LIBSSH2_HAVE_ZLIB") endif() endif() -list(APPEND LIBRARIES ${SOCKET_LIBRARIES}) - -if(WIN32) - list(APPEND PC_LIBS -lws2_32) -endif() +list(APPEND LIBSSH2_LIBS ${LIBSSH2_LIBS_SOCKET}) # to find generated header list(APPEND libssh2_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) @@ -81,8 +85,8 @@ endif() include(GNUInstallDirs) transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") # Get 'CSOURCES' and 'HHEADERS' variables -include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake) -set(SOURCES ${CSOURCES} ${HHEADERS}) +include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") +set(_sources ${CSOURCES} ${HHEADERS}) ## Library definition @@ -96,59 +100,74 @@ if(WIN32 AND BUILD_STATIC_LIBS AND BUILD_SHARED_LIBS AND set(STATIC_LIB_SUFFIX "_static") endif() +unset(_libssh2_export) + # we want it to be called libssh2 on all platforms if(BUILD_STATIC_LIBS) - list(APPEND libssh2_export ${LIB_STATIC}) - add_library(${LIB_STATIC} STATIC ${SOURCES}) - target_compile_definitions(${LIB_STATIC} PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} ${libssh2_DEFINITIONS}) - target_link_libraries(${LIB_STATIC} PRIVATE ${LIBRARIES}) - set_target_properties(${LIB_STATIC} PROPERTIES PREFIX "" OUTPUT_NAME "libssh2") - set_target_properties(${LIB_STATIC} PROPERTIES SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") + list(APPEND _libssh2_export ${LIB_STATIC}) + add_library(${LIB_STATIC} STATIC ${_sources}) + add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC}) + target_compile_definitions(${LIB_STATIC} PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} ${_libssh2_definitions}) + target_link_libraries(${LIB_STATIC} PRIVATE ${LIBSSH2_LIBS}) + set_target_properties(${LIB_STATIC} PROPERTIES + PREFIX "" OUTPUT_NAME "libssh2" SOVERSION "${_libssh2_soversion}" VERSION "${_libssh2_libversion}" + SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}") target_include_directories(${LIB_STATIC} - PRIVATE "${PROJECT_SOURCE_DIR}/include/" ${libssh2_INCLUDE_DIRS} ${PRIVATE_INCLUDE_DIRECTORIES} + PRIVATE + "${PROJECT_SOURCE_DIR}/include" + ${libssh2_INCLUDE_DIRS} + ${PRIVATE_INCLUDE_DIRECTORIES} PUBLIC - $ - $/${CMAKE_INSTALL_INCLUDEDIR}>) + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}>") endif() if(BUILD_SHARED_LIBS) - list(APPEND libssh2_export ${LIB_SHARED}) - add_library(${LIB_SHARED} SHARED ${SOURCES}) + list(APPEND _libssh2_export ${LIB_SHARED}) + add_library(${LIB_SHARED} SHARED ${_sources}) + add_library(${PROJECT_NAME}::${LIB_SHARED} ALIAS ${LIB_SHARED}) if(WIN32) - set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libssh2.rc) + set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "libssh2.rc") endif() - target_compile_definitions(${LIB_SHARED} PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} ${libssh2_DEFINITIONS} ${LIB_SHARED_DEFINITIONS}) + target_compile_definitions(${LIB_SHARED} PRIVATE ${PRIVATE_COMPILE_DEFINITIONS} ${_libssh2_definitions} ${LIB_SHARED_DEFINITIONS}) target_compile_options(${LIB_SHARED} PRIVATE ${LIB_SHARED_C_FLAGS}) - target_link_libraries(${LIB_SHARED} PRIVATE ${LIBRARIES}) - set_target_properties(${LIB_SHARED} PROPERTIES PREFIX "" IMPORT_PREFIX "" OUTPUT_NAME "libssh2") - set_target_properties(${LIB_SHARED} PROPERTIES IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}") - set_target_properties(${LIB_SHARED} PROPERTIES POSITION_INDEPENDENT_CODE ON) + target_link_libraries(${LIB_SHARED} PRIVATE ${LIBSSH2_LIBS}) + set_target_properties(${LIB_SHARED} PROPERTIES + PREFIX "" OUTPUT_NAME "libssh2" SOVERSION "${_libssh2_soversion}" VERSION "${_libssh2_libversion}" + IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}" + POSITION_INDEPENDENT_CODE ON) target_include_directories(${LIB_SHARED} - PRIVATE "${PROJECT_SOURCE_DIR}/include/" ${libssh2_INCLUDE_DIRS} ${PRIVATE_INCLUDE_DIRECTORIES} + PRIVATE + "${PROJECT_SOURCE_DIR}/include" + ${libssh2_INCLUDE_DIRS} + ${PRIVATE_INCLUDE_DIRECTORIES} PUBLIC - $ - $/${CMAKE_INSTALL_INCLUDEDIR}>) + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}>") endif() +add_library(${PROJECT_NAME}::${LIB_NAME} ALIAS ${LIB_SELECTED}) +add_library(${LIB_NAME} ALIAS ${LIB_SELECTED}) + ## Installation install(FILES - ${PROJECT_SOURCE_DIR}/include/libssh2.h - ${PROJECT_SOURCE_DIR}/include/libssh2_publickey.h - ${PROJECT_SOURCE_DIR}/include/libssh2_sftp.h + "${PROJECT_SOURCE_DIR}/include/libssh2.h" + "${PROJECT_SOURCE_DIR}/include/libssh2_publickey.h" + "${PROJECT_SOURCE_DIR}/include/libssh2_sftp.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) if(BUILD_STATIC_LIBS) install(TARGETS ${LIB_STATIC} - EXPORT Libssh2Config + EXPORT "${PROJECT_NAME}-targets" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() if(BUILD_SHARED_LIBS) install(TARGETS ${LIB_SHARED} - EXPORT Libssh2Config + EXPORT "${PROJECT_NAME}-targets" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) @@ -157,59 +176,166 @@ if(BUILD_SHARED_LIBS) endif() set(RUNTIME_DEPENDENCIES ${_RUNTIME_DEPENDENCIES} CACHE INTERNAL - "Files that must be in the same directory as the executables at runtime.") + "Files that must be in the same directory as the executables at runtime.") # Package config -## During package installation, install Libssh2Config.cmake -install(EXPORT Libssh2Config - NAMESPACE Libssh2:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libssh2) +## During package installation, install libssh2-targets.cmake +install(EXPORT "${PROJECT_NAME}-targets" + NAMESPACE "${PROJECT_NAME}::" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") ## During build, register directly from build tree -# create Libssh2Config.cmake -export(TARGETS ${libssh2_export} NAMESPACE Libssh2:: FILE Libssh2Config.cmake) -export(PACKAGE Libssh2) # register it +# create libssh2-targets.cmake +export(TARGETS ${_libssh2_export} NAMESPACE "${PROJECT_NAME}::" FILE "${PROJECT_NAME}-targets.cmake") +export(PACKAGE ${PROJECT_NAME}) # register it -## Export a .pc file for client projects not using CMaek -if(PC_REQUIRES_PRIVATE) - string(REPLACE ";" "," PC_REQUIRES_PRIVATE "${PC_REQUIRES_PRIVATE}") -endif() -if(PC_LIBS) - string(REPLACE ";" " " PC_LIBS "${PC_LIBS}") -endif() -set(LIBSSH2VER ${LIBSSH2_VERSION}) -set(LIBSREQUIRED ${PC_REQUIRES_PRIVATE}) -set(LIBS ${PC_LIBS}) -set(prefix ${CMAKE_INSTALL_PREFIX}) -set(exec_prefix "\${prefix}") -set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}") -set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") -configure_file(${CMAKE_SOURCE_DIR}/libssh2.pc.in libssh2.pc @ONLY) +# Generate libssh2-config.cmake into build tree and install it with dependencies +configure_file("${PROJECT_SOURCE_DIR}/cmake/libssh2-config.cmake.in" "${PROJECT_NAME}-config.cmake" @ONLY) install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/libssh2.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" + "${PROJECT_SOURCE_DIR}/cmake/FindLibgcrypt.cmake" + "${PROJECT_SOURCE_DIR}/cmake/FindMbedTLS.cmake" + "${PROJECT_SOURCE_DIR}/cmake/FindWolfSSL.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") -## Versioning +# Calculate variables for pkg-config +set(LIBSSH2_PC_LIBS_PRIVATE "") -set(LIBSSH2_SOVERSION 1) -set(LIBSSH2_VERSION 1.0.1) -if(BUILD_STATIC_LIBS) - set_target_properties(${LIB_STATIC} PROPERTIES - SOVERSION ${LIBSSH2_SOVERSION} - VERSION ${LIBSSH2_VERSION}) +if(WIN32) + list(APPEND LIBSSH2_PC_LIBS_PRIVATE "-lws2_32") endif() + +set(_ldflags "") + +# Avoid getting unnecessary -L options for known system directories. +unset(_sys_libdirs) +foreach(_libdir IN LISTS CMAKE_SYSTEM_PREFIX_PATH) + if(_libdir MATCHES "/$") + set(_libdir "${_libdir}lib") + else() + set(_libdir "${_libdir}/lib") + endif() + if(IS_DIRECTORY "${_libdir}") + list(APPEND _sys_libdirs "${_libdir}") + endif() + if(DEFINED CMAKE_LIBRARY_ARCHITECTURE) + set(_libdir "${_libdir}/${CMAKE_LIBRARY_ARCHITECTURE}") + if(IS_DIRECTORY "${_libdir}") + list(APPEND _sys_libdirs "${_libdir}") + endif() + endif() +endforeach() + +foreach(_libdir IN LISTS LIBSSH2_LIBDIRS) + list(FIND _sys_libdirs "${_libdir}" _libdir_index) + if(_libdir_index LESS 0) + list(APPEND _ldflags "-L${_libdir}") + endif() +endforeach() + +unset(_implicit_libs) +if(NOT MINGW AND NOT UNIX) + set(_implicit_libs ${CMAKE_C_IMPLICIT_LINK_LIBRARIES}) +endif() + +foreach(_lib IN LISTS _implicit_libs LIBSSH2_LIBS) + if(TARGET "${_lib}") + set(_libname "${_lib}") + get_target_property(_imported "${_libname}" IMPORTED) + if(NOT _imported) + # Reading the LOCATION property on non-imported target will error out. + # Assume the user will not need this information in the .pc file. + continue() + endif() + get_target_property(_lib "${_libname}" LOCATION) + if(NOT _lib) + message(WARNING "Bad lib in library list: ${_libname}") + continue() + endif() + endif() + if(_lib MATCHES "^-") + list(APPEND _ldflags "${_lib}") + elseif(_lib MATCHES ".*/.*") + # This gets a bit more complex, because we want to specify the + # directory separately, and only once per directory + get_filename_component(_libdir ${_lib} DIRECTORY) + get_filename_component(_libname ${_lib} NAME_WE) + if(_libname MATCHES "^lib") + list(FIND _sys_libdirs "${_libdir}" _libdir_index) + if(_libdir_index LESS 0) + list(APPEND _ldflags "-L${_libdir}") + endif() + string(REGEX REPLACE "^lib" "" _libname "${_libname}") + list(APPEND LIBSSH2_PC_LIBS_PRIVATE "-l${_libname}") + else() + list(APPEND LIBSSH2_PC_LIBS_PRIVATE "${_lib}") + endif() + else() + list(APPEND LIBSSH2_PC_LIBS_PRIVATE "-l${_lib}") + endif() +endforeach() + +if(LIBSSH2_PC_REQUIRES_PRIVATE) + string(REPLACE ";" "," LIBSSH2_PC_REQUIRES_PRIVATE "${LIBSSH2_PC_REQUIRES_PRIVATE}") +endif() +if(LIBSSH2_PC_LIBS_PRIVATE) + list(REMOVE_DUPLICATES LIBSSH2_PC_LIBS_PRIVATE) + string(REPLACE ";" " " LIBSSH2_PC_LIBS_PRIVATE "${LIBSSH2_PC_LIBS_PRIVATE}") +endif() +if(_ldflags) + list(REMOVE_DUPLICATES _ldflags) + string(REPLACE ";" " " _ldflags "${_ldflags}") + set(LIBSSH2_PC_LIBS_PRIVATE "${_ldflags} ${LIBSSH2_PC_LIBS_PRIVATE}") + string(STRIP "${LIBSSH2_PC_LIBS_PRIVATE}" LIBSSH2_PC_LIBS_PRIVATE) +endif() + +# Merge pkg-config private fields into public ones when static-only if(BUILD_SHARED_LIBS) - set_target_properties(${LIB_SHARED} PROPERTIES - SOVERSION ${LIBSSH2_SOVERSION} - VERSION ${LIBSSH2_VERSION}) + set(LIBSSH2_PC_REQUIRES "") + set(LIBSSH2_PC_LIBS "") +else() + set(LIBSSH2_PC_REQUIRES "${LIBSSH2_PC_REQUIRES_PRIVATE}") + set(LIBSSH2_PC_LIBS "${LIBSSH2_PC_LIBS_PRIVATE}") endif() +set(prefix "${CMAKE_INSTALL_PREFIX}") +set(exec_prefix "\${prefix}") +if(IS_ABSOLUTE ${CMAKE_INSTALL_INCLUDEDIR}) + set(includedir "${CMAKE_INSTALL_INCLUDEDIR}") +else() + set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") +endif() +if(IS_ABSOLUTE ${CMAKE_INSTALL_LIBDIR}) + set(libdir "${CMAKE_INSTALL_LIBDIR}") +else() + set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") +endif() + +# Generate a pkg-config file for client projects not using CMake. +# Consumed variables: +# exec_prefix +# includedir +# LIBSSH2_PC_LIBS +# LIBSSH2_PC_LIBS_PRIVATE +# LIBSSH2_PC_REQUIRES +# LIBSSH2_PC_REQUIRES_PRIVATE +# LIBSSH2_VERSION +# libdir +# prefix +configure_file("${PROJECT_SOURCE_DIR}/libssh2.pc.in" "libssh2.pc" @ONLY) +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/libssh2.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + +# + include(CMakePackageConfigHelpers) write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/Libssh2ConfigVersion.cmake + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}" COMPATIBILITY SameMajorVersion) install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/Libssh2ConfigVersion.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libssh2) + FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") diff --git a/libssh2/src/Makefile.am b/libssh2/src/Makefile.am index 91222d54c..9f148823d 100644 --- a/libssh2/src/Makefile.am +++ b/libssh2/src/Makefile.am @@ -1,3 +1,5 @@ +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause AUTOMAKE_OPTIONS = foreign nostdinc # Get the CSOURCES, HHEADERS and EXTRA_DIST defines @@ -17,6 +19,9 @@ lib_LTLIBRARIES = libssh2.la # tree AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/include +# This might hold -Werror +AM_CFLAGS = @LIBSSH2_CFLAG_EXTRAS@ + VERSION=-version-info 1:1:0 # This flag accepts an argument of the form current[:revision[:age]]. So, @@ -48,8 +53,7 @@ VERSION=-version-info 1:1:0 # libssh2_la_LDFLAGS = $(VERSION) -no-undefined \ - -export-symbols-regex '^libssh2_.*' \ - $(LTLIBZ) + -export-symbols-regex '^libssh2_.*' if HAVE_WINDRES .rc.lo: diff --git a/libssh2/src/Makefile.in b/libssh2/src/Makefile.in index 4e4917c7b..cdc882757 100644 --- a/libssh2/src/Makefile.in +++ b/libssh2/src/Makefile.in @@ -91,12 +91,12 @@ host_triplet = @host@ @HAVE_WINDRES_TRUE@am__append_1 = libssh2.rc subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) @@ -135,18 +135,20 @@ am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libssh2_la_LIBADD = am__libssh2_la_SOURCES_DIST = agent.c bcrypt_pbkdf.c channel.c comp.c \ - crypt.c crypto.c global.c hostkey.c keepalive.c kex.c \ - knownhost.c mac.c misc.c packet.c pem.c publickey.c scp.c \ - session.c sftp.c transport.c userauth.c userauth_kbd_packet.c \ - version.c channel.h comp.h crypto.h libgcrypt.h libssh2_priv.h \ - libssh2_setup.h mac.h mbedtls.h misc.h openssl.h os400qc3.h \ - packet.h session.h sftp.h transport.h userauth.h \ + chacha.c cipher-chachapoly.c crypt.c crypto.c global.c \ + hostkey.c keepalive.c kex.c knownhost.c mac.c misc.c packet.c \ + pem.c poly1305.c publickey.c scp.c session.c sftp.c \ + transport.c userauth.c userauth_kbd_packet.c version.c \ + chacha.h channel.h cipher-chachapoly.h comp.h crypto.h \ + crypto_config.h libgcrypt.h libssh2_priv.h libssh2_setup.h \ + mac.h mbedtls.h misc.h openssl.h os400qc3.h packet.h \ + poly1305.h session.h sftp.h transport.h userauth.h \ userauth_kbd_packet.h wincng.h libssh2.rc -am__objects_1 = agent.lo bcrypt_pbkdf.lo channel.lo comp.lo crypt.lo \ - crypto.lo global.lo hostkey.lo keepalive.lo kex.lo \ - knownhost.lo mac.lo misc.lo packet.lo pem.lo publickey.lo \ - scp.lo session.lo sftp.lo transport.lo userauth.lo \ - userauth_kbd_packet.lo version.lo +am__objects_1 = agent.lo bcrypt_pbkdf.lo channel.lo comp.lo chacha.lo \ + cipher-chachapoly.lo crypt.lo crypto.lo global.lo hostkey.lo \ + keepalive.lo kex.lo knownhost.lo mac.lo misc.lo packet.lo \ + pem.lo poly1305.lo publickey.lo scp.lo session.lo sftp.lo \ + transport.lo userauth.lo userauth_kbd_packet.lo version.lo am__objects_2 = @HAVE_WINDRES_TRUE@am__objects_3 = libssh2.lo am_libssh2_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ @@ -175,17 +177,19 @@ DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/agent.Plo \ - ./$(DEPDIR)/bcrypt_pbkdf.Plo ./$(DEPDIR)/channel.Plo \ + ./$(DEPDIR)/bcrypt_pbkdf.Plo ./$(DEPDIR)/chacha.Plo \ + ./$(DEPDIR)/channel.Plo ./$(DEPDIR)/cipher-chachapoly.Plo \ ./$(DEPDIR)/comp.Plo ./$(DEPDIR)/crypt.Plo \ ./$(DEPDIR)/crypto.Plo ./$(DEPDIR)/global.Plo \ ./$(DEPDIR)/hostkey.Plo ./$(DEPDIR)/keepalive.Plo \ ./$(DEPDIR)/kex.Plo ./$(DEPDIR)/knownhost.Plo \ ./$(DEPDIR)/mac.Plo ./$(DEPDIR)/misc.Plo \ ./$(DEPDIR)/packet.Plo ./$(DEPDIR)/pem.Plo \ - ./$(DEPDIR)/publickey.Plo ./$(DEPDIR)/scp.Plo \ - ./$(DEPDIR)/session.Plo ./$(DEPDIR)/sftp.Plo \ - ./$(DEPDIR)/transport.Plo ./$(DEPDIR)/userauth.Plo \ - ./$(DEPDIR)/userauth_kbd_packet.Plo ./$(DEPDIR)/version.Plo + ./$(DEPDIR)/poly1305.Plo ./$(DEPDIR)/publickey.Plo \ + ./$(DEPDIR)/scp.Plo ./$(DEPDIR)/session.Plo \ + ./$(DEPDIR)/sftp.Plo ./$(DEPDIR)/transport.Plo \ + ./$(DEPDIR)/userauth.Plo ./$(DEPDIR)/userauth_kbd_packet.Plo \ + ./$(DEPDIR)/version.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -290,8 +294,12 @@ LIBMBEDCRYPTO = @LIBMBEDCRYPTO@ LIBMBEDCRYPTO_PREFIX = @LIBMBEDCRYPTO_PREFIX@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ -LIBSREQUIRED = @LIBSREQUIRED@ -LIBSSH2VER = @LIBSSH2VER@ +LIBSSH2_CFLAG_EXTRAS = @LIBSSH2_CFLAG_EXTRAS@ +LIBSSH2_PC_LIBS = @LIBSSH2_PC_LIBS@ +LIBSSH2_PC_LIBS_PRIVATE = @LIBSSH2_PC_LIBS_PRIVATE@ +LIBSSH2_PC_REQUIRES = @LIBSSH2_PC_REQUIRES@ +LIBSSH2_PC_REQUIRES_PRIVATE = @LIBSSH2_PC_REQUIRES_PRIVATE@ +LIBSSH2_VERSION = @LIBSSH2_VERSION@ LIBSSL = @LIBSSL@ LIBSSL_PREFIX = @LIBSSL_PREFIX@ LIBTOOL = @LIBTOOL@ @@ -390,12 +398,20 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ + +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause AUTOMAKE_OPTIONS = foreign nostdinc + +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause CSOURCES = \ agent.c \ bcrypt_pbkdf.c \ channel.c \ comp.c \ + chacha.c \ + cipher-chachapoly.c \ crypt.c \ crypto.c \ global.c \ @@ -407,6 +423,7 @@ CSOURCES = \ misc.c \ packet.c \ pem.c \ + poly1305.c \ publickey.c \ scp.c \ session.c \ @@ -417,9 +434,12 @@ CSOURCES = \ version.c HHEADERS = \ + chacha.h \ channel.h \ + cipher-chachapoly.h \ comp.h \ crypto.h \ + crypto_config.h \ libgcrypt.h \ libssh2_priv.h \ libssh2_setup.h \ @@ -429,6 +449,7 @@ HHEADERS = \ openssl.h \ os400qc3.h \ packet.h \ + poly1305.h \ session.h \ sftp.h \ transport.h \ @@ -449,6 +470,9 @@ lib_LTLIBRARIES = libssh2.la # tree AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/include +# This might hold -Werror +AM_CFLAGS = @LIBSSH2_CFLAG_EXTRAS@ + # This flag accepts an argument of the form current[:revision[:age]]. So, # passing -version-info 3:12:1 sets current to 3, revision to 12, and age to # 1. @@ -477,8 +501,7 @@ AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/include # set age to 0. (c:r:a=0) # libssh2_la_LDFLAGS = $(VERSION) -no-undefined \ - -export-symbols-regex '^libssh2_.*' \ - $(LTLIBZ) + -export-symbols-regex '^libssh2_.*' all: libssh2_config.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -577,7 +600,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/agent.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bcrypt_pbkdf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chacha.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-chachapoly.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypt.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto.Plo@am__quote@ # am--include-marker @@ -590,6 +615,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pem.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poly1305.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/publickey.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Plo@am__quote@ # am--include-marker @@ -761,7 +787,9 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ distclean: distclean-am -rm -f ./$(DEPDIR)/agent.Plo -rm -f ./$(DEPDIR)/bcrypt_pbkdf.Plo + -rm -f ./$(DEPDIR)/chacha.Plo -rm -f ./$(DEPDIR)/channel.Plo + -rm -f ./$(DEPDIR)/cipher-chachapoly.Plo -rm -f ./$(DEPDIR)/comp.Plo -rm -f ./$(DEPDIR)/crypt.Plo -rm -f ./$(DEPDIR)/crypto.Plo @@ -774,6 +802,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/misc.Plo -rm -f ./$(DEPDIR)/packet.Plo -rm -f ./$(DEPDIR)/pem.Plo + -rm -f ./$(DEPDIR)/poly1305.Plo -rm -f ./$(DEPDIR)/publickey.Plo -rm -f ./$(DEPDIR)/scp.Plo -rm -f ./$(DEPDIR)/session.Plo @@ -829,7 +858,9 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/agent.Plo -rm -f ./$(DEPDIR)/bcrypt_pbkdf.Plo + -rm -f ./$(DEPDIR)/chacha.Plo -rm -f ./$(DEPDIR)/channel.Plo + -rm -f ./$(DEPDIR)/cipher-chachapoly.Plo -rm -f ./$(DEPDIR)/comp.Plo -rm -f ./$(DEPDIR)/crypt.Plo -rm -f ./$(DEPDIR)/crypto.Plo @@ -842,6 +873,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/misc.Plo -rm -f ./$(DEPDIR)/packet.Plo -rm -f ./$(DEPDIR)/pem.Plo + -rm -f ./$(DEPDIR)/poly1305.Plo -rm -f ./$(DEPDIR)/publickey.Plo -rm -f ./$(DEPDIR)/scp.Plo -rm -f ./$(DEPDIR)/session.Plo diff --git a/libssh2/src/Makefile.inc b/libssh2/src/Makefile.inc index 2928ba2b2..5cf070cc8 100644 --- a/libssh2/src/Makefile.inc +++ b/libssh2/src/Makefile.inc @@ -1,8 +1,12 @@ +# Copyright (C) The libssh2 project and its contributors. +# SPDX-License-Identifier: BSD-3-Clause CSOURCES = \ agent.c \ bcrypt_pbkdf.c \ channel.c \ comp.c \ + chacha.c \ + cipher-chachapoly.c \ crypt.c \ crypto.c \ global.c \ @@ -14,6 +18,7 @@ CSOURCES = \ misc.c \ packet.c \ pem.c \ + poly1305.c \ publickey.c \ scp.c \ session.c \ @@ -24,9 +29,12 @@ CSOURCES = \ version.c HHEADERS = \ + chacha.h \ channel.h \ + cipher-chachapoly.h \ comp.h \ crypto.h \ + crypto_config.h \ libgcrypt.h \ libssh2_priv.h \ libssh2_setup.h \ @@ -36,6 +44,7 @@ HHEADERS = \ openssl.h \ os400qc3.h \ packet.h \ + poly1305.h \ session.h \ sftp.h \ transport.h \ diff --git a/libssh2/src/agent.c b/libssh2/src/agent.c index 450581ce5..dd709eb1f 100644 --- a/libssh2/src/agent.c +++ b/libssh2/src/agent.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2009 by Daiki Ueno - * Copyright (C) 2010-2021 by Daniel Stenberg + * Copyright (C) Daiki Ueno + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,6 +35,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -51,13 +53,14 @@ #undef PF_UNIX #endif -#if defined(WIN32) && !defined(LIBSSH2_WINDOWS_UWP) +#if defined(_WIN32) && !defined(LIBSSH2_WINDOWS_UWP) #define HAVE_WIN32_AGENTS #endif #include "userauth.h" #include "session.h" +#if 0 /* Requests from client to agent for protocol 1 key operations */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENTC_RSA_CHALLENGE 3 @@ -65,10 +68,12 @@ #define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 #define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 #define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 +#endif /* Requests from client to agent for protocol 2 key operations */ #define SSH2_AGENTC_REQUEST_IDENTITIES 11 #define SSH2_AGENTC_SIGN_REQUEST 13 +#if 0 #define SSH2_AGENTC_ADD_IDENTITY 17 #define SSH2_AGENTC_REMOVE_IDENTITY 18 #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 @@ -89,13 +94,14 @@ #define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 #define SSH_AGENT_RSA_RESPONSE 4 -/* Replies from agent to client for protocol 2 key operations */ -#define SSH2_AGENT_IDENTITIES_ANSWER 12 -#define SSH2_AGENT_SIGN_RESPONSE 14 - /* Key constraint identifiers */ #define SSH_AGENT_CONSTRAIN_LIFETIME 1 #define SSH_AGENT_CONSTRAIN_CONFIRM 2 +#endif + +/* Replies from agent to client for protocol 2 key operations */ +#define SSH2_AGENT_IDENTITIES_ANSWER 12 +#define SSH2_AGENT_SIGN_RESPONSE 14 /* Signature request methods */ #define SSH_AGENT_RSA_SHA2_256 2 @@ -557,7 +563,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Agent sign method %.*s", - method_len, method_name)); + (int)method_len, method_name)); rc = LIBSSH2_ERROR_ALGO_UNSUPPORTED; goto error; diff --git a/libssh2/src/agent_win.c b/libssh2/src/agent_win.c index 723dc0e13..3764fe433 100644 --- a/libssh2/src/agent_win.c +++ b/libssh2/src/agent_win.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2009 by Daiki Ueno - * Copyright (C) 2010-2014 by Daniel Stenberg + * Copyright (C) Daiki Ueno + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,6 +35,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause */ #ifdef HAVE_WIN32_AGENTS /* Compile this via agent.c */ @@ -59,7 +61,7 @@ * - fileio_close replacing close * * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland + * Copyright (C) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for connecting the local authentication agent. * @@ -70,7 +72,7 @@ * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation, - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (C) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -92,7 +94,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Copyright (c) 2015 Microsoft Corp. + * Copyright (C) 2015 Microsoft Corp. * All rights reserved * * Microsoft openssh win32 port diff --git a/libssh2/src/bcrypt_pbkdf.c b/libssh2/src/bcrypt_pbkdf.c index 91be901cd..73cda4357 100644 --- a/libssh2/src/bcrypt_pbkdf.c +++ b/libssh2/src/bcrypt_pbkdf.c @@ -1,6 +1,6 @@ /* $OpenBSD: bcrypt_pbkdf.c,v 1.4 2013/07/29 00:55:53 tedu Exp $ */ /* - * Copyright (c) 2013 Ted Unangst + * Copyright (C) Ted Unangst * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -13,6 +13,8 @@ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * SPDX-License-Identifier: MIT */ #include "libssh2_priv.h" @@ -114,7 +116,7 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, if(rounds < 1) return -1; if(passlen == 0 || saltlen == 0 || keylen == 0 || - keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20) + keylen > sizeof(out) * sizeof(out) || saltlen > 1 << 20) return -1; countsalt = calloc(1, saltlen + 4); if(!countsalt) @@ -125,9 +127,12 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, memcpy(countsalt, salt, saltlen); /* collapse password */ - (void)libssh2_sha512_init(&ctx); - libssh2_sha512_update(ctx, pass, passlen); - libssh2_sha512_final(ctx, sha2pass); + if(!libssh2_sha512_init(&ctx) || + !libssh2_sha512_update(ctx, pass, passlen) || + !libssh2_sha512_final(ctx, sha2pass)) { + free(countsalt); + return -1; + } /* generate key, sizeof(out) at a time */ for(count = 1; keylen > 0; count++) { @@ -137,18 +142,26 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, countsalt[saltlen + 3] = count & 0xff; /* first round, salt is salt */ - (void)libssh2_sha512_init(&ctx); - libssh2_sha512_update(ctx, countsalt, saltlen + 4); - libssh2_sha512_final(ctx, sha2salt); + if(!libssh2_sha512_init(&ctx) || + !libssh2_sha512_update(ctx, countsalt, saltlen + 4) || + !libssh2_sha512_final(ctx, sha2salt)) { + _libssh2_explicit_zero(out, sizeof(out)); + free(countsalt); + return -1; + } bcrypt_hash(sha2pass, sha2salt, tmpout); memcpy(out, tmpout, sizeof(out)); for(i = 1; i < rounds; i++) { /* subsequent rounds, salt is previous output */ - (void)libssh2_sha512_init(&ctx); - libssh2_sha512_update(ctx, tmpout, sizeof(tmpout)); - libssh2_sha512_final(ctx, sha2salt); + if(!libssh2_sha512_init(&ctx) || + !libssh2_sha512_update(ctx, tmpout, sizeof(tmpout)) || + !libssh2_sha512_final(ctx, sha2salt)) { + _libssh2_explicit_zero(out, sizeof(out)); + free(countsalt); + return -1; + } bcrypt_hash(sha2pass, sha2salt, tmpout); for(j = 0; j < sizeof(out); j++) diff --git a/libssh2/src/blowfish.c b/libssh2/src/blowfish.c index b580b7171..5de54f596 100644 --- a/libssh2/src/blowfish.c +++ b/libssh2/src/blowfish.c @@ -2,7 +2,7 @@ /* * Blowfish for OpenBSD - a fast block cipher designed by Bruce Schneier * - * Copyright 1997 Niels Provos + * Copyright (C) Niels Provos * All rights reserved. * * Implementation advice by David Mazieres . @@ -28,6 +28,8 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ /* diff --git a/libssh2/src/chacha.c b/libssh2/src/chacha.c new file mode 100644 index 000000000..72560f861 --- /dev/null +++ b/libssh2/src/chacha.c @@ -0,0 +1,224 @@ +/* + * chacha-merged.c version 20080118 + * D. J. Bernstein + * Public domain. + * Copyright not intended 2024. + * + * SPDX-License-Identifier: SAX-PD-2.0 + */ + +#include "libssh2_priv.h" + +#include "chacha.h" + +/* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */ + +typedef unsigned char u8; +typedef unsigned int u32; + +typedef struct chacha_ctx chacha_ctx; + +#define U8C(v) (v##U) +#define U32C(v) (v##U) + +#define U8V(v) ((u8)(v) & U8C(0xFF)) +#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) + +#define ROTL32(v, n) \ + (U32V((v) << (n)) | ((v) >> (32 - (n)))) + +#define U8TO32_LITTLE(p) \ + (((u32)((p)[0]) ) | \ + ((u32)((p)[1]) << 8) | \ + ((u32)((p)[2]) << 16) | \ + ((u32)((p)[3]) << 24)) + +#define U32TO8_LITTLE(p, v) \ + do { \ + (p)[0] = U8V((v) ); \ + (p)[1] = U8V((v) >> 8); \ + (p)[2] = U8V((v) >> 16); \ + (p)[3] = U8V((v) >> 24); \ + } while (0) + +#define ROTATE(v,c) (ROTL32(v,c)) +#define XOR(v,w) ((v) ^ (w)) +#define PLUS(v,w) (U32V((v) + (w))) +#define PLUSONE(v) (PLUS((v),1)) + +#define QUARTERROUND(a,b,c,d) \ + a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ + c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ + a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ + c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); + +static const char sigma[17] = "expand 32-byte k"; +static const char tau[17] = "expand 16-byte k"; + +void +chacha_keysetup(chacha_ctx *x, const u8 *k, u32 kbits) +{ + const char *constants; + + x->input[4] = U8TO32_LITTLE(k + 0); + x->input[5] = U8TO32_LITTLE(k + 4); + x->input[6] = U8TO32_LITTLE(k + 8); + x->input[7] = U8TO32_LITTLE(k + 12); + if(kbits == 256) { /* recommended */ + k += 16; + constants = sigma; + } + else { /* kbits == 128 */ + constants = tau; + } + x->input[8] = U8TO32_LITTLE(k + 0); + x->input[9] = U8TO32_LITTLE(k + 4); + x->input[10] = U8TO32_LITTLE(k + 8); + x->input[11] = U8TO32_LITTLE(k + 12); + x->input[0] = U8TO32_LITTLE(constants + 0); + x->input[1] = U8TO32_LITTLE(constants + 4); + x->input[2] = U8TO32_LITTLE(constants + 8); + x->input[3] = U8TO32_LITTLE(constants + 12); +} + +void +chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) +{ + x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); + x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); + x->input[14] = U8TO32_LITTLE(iv + 0); + x->input[15] = U8TO32_LITTLE(iv + 4); +} + +void +chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes) +{ + u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; + u8 *ctarget = NULL; + u8 tmp[64]; + u_int i; + + if(!bytes) + return; + + j0 = x->input[0]; + j1 = x->input[1]; + j2 = x->input[2]; + j3 = x->input[3]; + j4 = x->input[4]; + j5 = x->input[5]; + j6 = x->input[6]; + j7 = x->input[7]; + j8 = x->input[8]; + j9 = x->input[9]; + j10 = x->input[10]; + j11 = x->input[11]; + j12 = x->input[12]; + j13 = x->input[13]; + j14 = x->input[14]; + j15 = x->input[15]; + + for(;;) { + if(bytes < 64) { + for(i = 0; i < bytes;++i) tmp[i] = m[i]; + m = tmp; + ctarget = c; + c = tmp; + } + x0 = j0; + x1 = j1; + x2 = j2; + x3 = j3; + x4 = j4; + x5 = j5; + x6 = j6; + x7 = j7; + x8 = j8; + x9 = j9; + x10 = j10; + x11 = j11; + x12 = j12; + x13 = j13; + x14 = j14; + x15 = j15; + for(i = 20; i > 0; i -= 2) { + QUARTERROUND(x0, x4, x8, x12) + QUARTERROUND(x1, x5, x9, x13) + QUARTERROUND(x2, x6, x10, x14) + QUARTERROUND(x3, x7, x11, x15) + QUARTERROUND(x0, x5, x10, x15) + QUARTERROUND(x1, x6, x11, x12) + QUARTERROUND(x2, x7, x8, x13) + QUARTERROUND(x3, x4, x9, x14) + } + x0 = PLUS(x0, j0); + x1 = PLUS(x1, j1); + x2 = PLUS(x2, j2); + x3 = PLUS(x3, j3); + x4 = PLUS(x4, j4); + x5 = PLUS(x5, j5); + x6 = PLUS(x6, j6); + x7 = PLUS(x7, j7); + x8 = PLUS(x8, j8); + x9 = PLUS(x9, j9); + x10 = PLUS(x10, j10); + x11 = PLUS(x11, j11); + x12 = PLUS(x12, j12); + x13 = PLUS(x13, j13); + x14 = PLUS(x14, j14); + x15 = PLUS(x15, j15); + + x0 = XOR(x0, U8TO32_LITTLE(m + 0)); + x1 = XOR(x1, U8TO32_LITTLE(m + 4)); + x2 = XOR(x2, U8TO32_LITTLE(m + 8)); + x3 = XOR(x3, U8TO32_LITTLE(m + 12)); + x4 = XOR(x4, U8TO32_LITTLE(m + 16)); + x5 = XOR(x5, U8TO32_LITTLE(m + 20)); + x6 = XOR(x6, U8TO32_LITTLE(m + 24)); + x7 = XOR(x7, U8TO32_LITTLE(m + 28)); + x8 = XOR(x8, U8TO32_LITTLE(m + 32)); + x9 = XOR(x9, U8TO32_LITTLE(m + 36)); + x10 = XOR(x10, U8TO32_LITTLE(m + 40)); + x11 = XOR(x11, U8TO32_LITTLE(m + 44)); + x12 = XOR(x12, U8TO32_LITTLE(m + 48)); + x13 = XOR(x13, U8TO32_LITTLE(m + 52)); + x14 = XOR(x14, U8TO32_LITTLE(m + 56)); + x15 = XOR(x15, U8TO32_LITTLE(m + 60)); + + j12 = PLUSONE(j12); + if(!j12) { + j13 = PLUSONE(j13); + /* stopping at 2^70 bytes per nonce is user's responsibility */ + } + + U32TO8_LITTLE(c + 0, x0); + U32TO8_LITTLE(c + 4, x1); + U32TO8_LITTLE(c + 8, x2); + U32TO8_LITTLE(c + 12, x3); + U32TO8_LITTLE(c + 16, x4); + U32TO8_LITTLE(c + 20, x5); + U32TO8_LITTLE(c + 24, x6); + U32TO8_LITTLE(c + 28, x7); + U32TO8_LITTLE(c + 32, x8); + U32TO8_LITTLE(c + 36, x9); + U32TO8_LITTLE(c + 40, x10); + U32TO8_LITTLE(c + 44, x11); + U32TO8_LITTLE(c + 48, x12); + U32TO8_LITTLE(c + 52, x13); + U32TO8_LITTLE(c + 56, x14); + U32TO8_LITTLE(c + 60, x15); + + if(bytes <= 64) { + if(bytes < 64) { + for(i = 0; i < bytes;++i) ctarget[i] = c[i]; + } + x->input[12] = j12; + x->input[13] = j13; + return; + } + bytes -= 64; + c += 64; + m += 64; + } +} diff --git a/libssh2/src/chacha.h b/libssh2/src/chacha.h new file mode 100644 index 000000000..b17ecd5c6 --- /dev/null +++ b/libssh2/src/chacha.h @@ -0,0 +1,33 @@ +/* $OpenBSD: chacha.h,v 1.4 2016/08/27 04:04:56 guenther Exp $ */ + +/* + * chacha-merged.c version 20080118 + * D. J. Bernstein + * Public domain. + * Copyright not intended 2024. + * + * SPDX-License-Identifier: SAX-PD-2.0 + */ + +#ifndef CHACHA_H +#define CHACHA_H + +#include + +struct chacha_ctx { + u_int input[16]; +}; + +#define CHACHA_MINKEYLEN 16 +#define CHACHA_NONCELEN 8 +#define CHACHA_CTRLEN 8 +#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) +#define CHACHA_BLOCKLEN 64 + +void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits); +void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr); +void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m, + u_char *c, u_int bytes); + +#endif /* CHACHA_H */ + diff --git a/libssh2/src/channel.c b/libssh2/src/channel.c index 2091d60d6..529c2ef82 100644 --- a/libssh2/src/channel.c +++ b/libssh2/src/channel.c @@ -1,7 +1,6 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2005 Mikhail Gusarov - * Copyright (c) 2008-2019 by Daniel Stenberg - * +/* Copyright (C) Sara Golemon + * Copyright (C) Mikhail Gusarov + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -36,6 +35,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -83,7 +84,7 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session) */ session->next_channel = id + 1; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Allocated new channel ID#%lu", id)); + "Allocated new channel ID#%u", id)); return id; } @@ -264,8 +265,8 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, session->open_channel->local.packet_size = _libssh2_ntohu32(session->open_data + 13); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Connection Established - ID: %lu/%lu win: %lu/%lu" - " pack: %lu/%lu", + "Connection Established - ID: %u/%u win: %u/%u" + " pack: %u/%u", session->open_channel->local.id, session->open_channel->remote.id, session->open_channel->local.window_size, @@ -901,7 +902,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel, _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Setting remote environment variable: %s=%s on " - "channel %lu/%lu", + "channel %u/%u", varname, value, channel->local.id, channel->remote.id)); s = channel->setenv_packet = @@ -1035,7 +1036,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, sizeof(channel->reqPTY_packet_requirev_state)); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Allocating tty on channel %lu/%lu", channel->local.id, + "Allocating tty on channel %u/%u", channel->local.id, channel->remote.id)); s = channel->reqPTY_packet; @@ -1138,7 +1139,7 @@ static int channel_request_auth_agent(LIBSSH2_CHANNEL *channel, sizeof(channel->req_auth_agent_requirev_state)); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Requesting auth agent on channel %lu/%lu", + "Requesting auth agent on channel %u/%u", channel->local.id, channel->remote.id)); /* @@ -1302,7 +1303,7 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width, sizeof(channel->reqPTY_packet_requirev_state)); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "changing tty size on channel %lu/%lu", + "changing tty size on channel %u/%u", channel->local.id, channel->remote.id)); @@ -1391,7 +1392,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, sizeof(channel->reqX11_packet_requirev_state)); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Requesting x11-req for channel %lu/%lu: single=%d " + "Requesting x11-req for channel %u/%u: single=%d " "proto=%s cookie=%s screen=%d", channel->local.id, channel->remote.id, single_connection, @@ -1549,7 +1550,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, channel->process_packet_len += + 4; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "starting request(%s) on channel %lu/%lu, message=%s", + "starting request(%s) on channel %u/%u, message=%s", request, channel->local.id, channel->remote.id, message ? message : "")); s = channel->process_packet = @@ -1718,9 +1719,9 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid) packet->data_head; _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN, - "Flushing %d bytes of data from stream " - "%lu on channel %lu/%lu", - bytes_to_flush, packet_stream_id, + "Flushing %ld bytes of data from stream " + "%d on channel %u/%u", + (long)bytes_to_flush, packet_stream_id, channel->local.id, channel->remote.id)); /* It's one of the streams we wanted to flush */ @@ -1881,8 +1882,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, && (adjustment + channel->adjust_queue < LIBSSH2_CHANNEL_MINADJUST)) { _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN, - "Queueing %lu bytes for receive window adjustment " - "for channel %lu/%lu", + "Queueing %u bytes for receive window adjustment " + "for channel %u/%u", adjustment, channel->local.id, channel->remote.id)); channel->adjust_queue += adjustment; return 0; @@ -1900,8 +1901,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, _libssh2_htonu32(&channel->adjust_adjust[1], channel->remote.id); _libssh2_htonu32(&channel->adjust_adjust[5], adjustment); _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN, - "Adjusting window %lu bytes for data on " - "channel %lu/%lu", + "Adjusting window %u bytes for data on " + "channel %u/%u", adjustment, channel->local.id, channel->remote.id)); channel->adjust_state = libssh2_NB_state_created; @@ -1929,10 +1930,9 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, return 0; } +#ifndef LIBSSH2_NO_DEPRECATED /* - * libssh2_channel_receive_window_adjust - * - * DEPRECATED + * libssh2_channel_receive_window_adjust (DEPRECATED, DO NOT USE!) * * Adjust the receive window for a channel by adjustment bytes. If the amount * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the @@ -1962,6 +1962,7 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, kept for backwards compatibility */ return rc ? (unsigned long)rc : window; } +#endif /* * libssh2_channel_receive_window_adjust2 @@ -1997,7 +1998,7 @@ _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode) { if(channel->extData2_state == libssh2_NB_state_idle) { _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN, - "Setting channel %lu/%lu handle_extended_data" + "Setting channel %u/%u handle_extended_data" " mode to %d", channel->local.id, channel->remote.id, ignore_mode)); channel->remote.extended_data_ignore_mode = (char)ignore_mode; @@ -2037,10 +2038,9 @@ libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, return rc; } +#ifndef LIBSSH2_NO_DEPRECATED /* - * libssh2_channel_handle_extended_data - * - * DEPRECATED DO NOTE USE! + * libssh2_channel_handle_extended_data (DEPRECATED, DO NOT USE!) * * How should extended data look to the calling app? Keep it in separate * channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the @@ -2053,7 +2053,7 @@ libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, { (void)libssh2_channel_handle_extended_data2(channel, ignore_mode); } - +#endif /* @@ -2080,9 +2080,9 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, LIBSSH2_PACKET *read_next; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "channel_read() wants %d bytes from channel %lu/%lu " + "channel_read() wants %ld bytes from channel %u/%u " "stream #%d", - (int) buflen, channel->local.id, channel->remote.id, + (long)buflen, channel->local.id, channel->remote.id, stream_id)); /* expand the receiving window first if it has become too narrow */ @@ -2177,10 +2177,10 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "channel_read() got %d of data from %lu/%lu/%d%s", - bytes_want, channel->local.id, + "channel_read() got %ld of data from %u/%u/%d%s", + (long)bytes_want, channel->local.id, channel->remote.id, stream_id, - unlink_packet?" [ul]":"")); + unlink_packet ? " [ul]" : "")); /* copy data from this struct to the target buffer */ memcpy(&buf[bytes_read], @@ -2355,8 +2355,8 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, unsigned char *s = channel->write_packet; _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN, - "Writing %d bytes on channel %lu/%lu, stream #%d", - (int) buflen, channel->local.id, channel->remote.id, + "Writing %ld bytes on channel %u/%u, stream #%d", + (long)buflen, channel->local.id, channel->remote.id, stream_id)); if(channel->local.close) @@ -2404,16 +2404,16 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, /* REMEMBER local means local as the SOURCE of the data */ if(channel->write_bufwrite > channel->local.window_size) { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Splitting write block due to %lu byte " - "window_size on %lu/%lu/%d", + "Splitting write block due to %u byte " + "window_size on %u/%u/%d", channel->local.window_size, channel->local.id, channel->remote.id, stream_id)); channel->write_bufwrite = channel->local.window_size; } if(channel->write_bufwrite > channel->local.packet_size) { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Splitting write block due to %lu byte " - "packet_size on %lu/%lu/%d", + "Splitting write block due to %u byte " + "packet_size on %u/%u/%d", channel->local.packet_size, channel->local.id, channel->remote.id, stream_id)); channel->write_bufwrite = channel->local.packet_size; @@ -2424,8 +2424,8 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, channel->write_packet_len = s - channel->write_packet; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Sending %d bytes on channel %lu/%lu, stream_id=%d", - (int) channel->write_bufwrite, channel->local.id, + "Sending %ld bytes on channel %u/%u, stream_id=%d", + (long)channel->write_bufwrite, channel->local.id, channel->remote.id, stream_id)); channel->write_state = libssh2_NB_state_created; @@ -2499,7 +2499,7 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel) int rc; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Sending EOF on channel %lu/%lu", + "Sending EOF on channel %u/%u", channel->local.id, channel->remote.id)); packet[0] = SSH_MSG_CHANNEL_EOF; _libssh2_htonu32(packet + 1, channel->remote.id); @@ -2589,7 +2589,7 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel) if(channel->wait_eof_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Awaiting EOF for channel %lu/%lu", channel->local.id, + "Awaiting EOF for channel %u/%u", channel->local.id, channel->remote.id)); channel->wait_eof_state = libssh2_NB_state_created; @@ -2617,7 +2617,7 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel) else if(rc < 0) { channel->wait_eof_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, - "_libssh2_transport_read() bailed out!"); + "_libssh2_transport_read() bailed out"); } } while(1); @@ -2670,7 +2670,7 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel) late for us to wait for it. Continue closing! */ if(channel->close_state == libssh2_NB_state_idle) { - _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu", + _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Closing channel %u/%u", channel->local.id, channel->remote.id)); channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE; @@ -2761,7 +2761,7 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel) if(channel->wait_closed_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Awaiting close of channel %lu/%lu", channel->local.id, + "Awaiting close of channel %u/%u", channel->local.id, channel->remote.id)); channel->wait_closed_state = libssh2_NB_state_created; @@ -2824,7 +2824,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) if(channel->free_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Freeing channel %lu/%lu resources", channel->local.id, + "Freeing channel %u/%u resources", channel->local.id, channel->remote.id)); channel->free_state = libssh2_NB_state_created; diff --git a/libssh2/src/channel.h b/libssh2/src/channel.h index 4466c4fc7..709ec0615 100644 --- a/libssh2/src/channel.h +++ b/libssh2/src/channel.h @@ -1,6 +1,6 @@ -#ifndef __LIBSSH2_CHANNEL_H -#define __LIBSSH2_CHANNEL_H -/* Copyright (c) 2008-2010 by Daniel Stenberg +#ifndef LIBSSH2_CHANNEL_H +#define LIBSSH2_CHANNEL_H +/* Copyright (C) Daniel Stenberg * * All rights reserved. * @@ -36,6 +36,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ /* @@ -137,4 +139,4 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel); */ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener); -#endif /* __LIBSSH2_CHANNEL_H */ +#endif /* LIBSSH2_CHANNEL_H */ diff --git a/libssh2/src/cipher-chachapoly.c b/libssh2/src/cipher-chachapoly.c new file mode 100644 index 000000000..9e4b11700 --- /dev/null +++ b/libssh2/src/cipher-chachapoly.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2013 Damien Miller + * + * Adapted by Will Cosgrove for libssh2 + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* $OpenBSD: cipher-chachapoly.c,v 1.8 2016/08/03 05:41:57 djm Exp $ */ + +#include "libssh2_priv.h" +#include "misc.h" +#include "cipher-chachapoly.h" + +int +chachapoly_timingsafe_bcmp(const void *b1, const void *b2, size_t n); + +int +chachapoly_init(struct chachapoly_ctx *ctx, const u_char *key, u_int keylen) +{ + if(keylen != (32 + 32)) /* 2 x 256 bit keys */ + return LIBSSH2_ERROR_INVAL; + chacha_keysetup(&ctx->main_ctx, key, 256); + chacha_keysetup(&ctx->header_ctx, key + 32, 256); + return 0; +} + +/* + * chachapoly_crypt() operates as following: + * En/decrypt with header key 'aadlen' bytes from 'src', storing result + * to 'dest'. The ciphertext here is treated as additional authenticated + * data for MAC calculation. + * En/decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. Use + * POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the authentication + * tag. This tag is written on encryption and verified on decryption. + */ +int +chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest, + const u_char *src, u_int len, u_int aadlen, int do_encrypt) +{ + u_char seqbuf[8]; + const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */ + u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; + int r = LIBSSH2_ERROR_INVAL; + unsigned char *ptr = NULL; + + /* + * Run ChaCha20 once to generate the Poly1305 key. The IV is the + * packet sequence number. + */ + memset(poly_key, 0, sizeof(poly_key)); + ptr = &seqbuf[0]; + _libssh2_store_u64(&ptr, seqnr); + chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL); + chacha_encrypt_bytes(&ctx->main_ctx, + poly_key, poly_key, sizeof(poly_key)); + + /* If decrypting, check tag before anything else */ + if(!do_encrypt) { + const u_char *tag = src + aadlen + len; + + poly1305_auth(expected_tag, src, aadlen + len, poly_key); + if(chachapoly_timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) + != 0) { + r = LIBSSH2_ERROR_DECRYPT; + goto out; + } + } + + /* Crypt additional data */ + if(aadlen) { + chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); + chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen); + } + + /* Set Chacha's block counter to 1 */ + chacha_ivsetup(&ctx->main_ctx, seqbuf, one); + chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen, + dest + aadlen, len); + + /* If encrypting, calculate and append tag */ + if(do_encrypt) { + poly1305_auth(dest + aadlen + len, dest, aadlen + len, + poly_key); + } + r = 0; +out: + memset(expected_tag, 0, sizeof(expected_tag)); + memset(seqbuf, 0, sizeof(seqbuf)); + memset(poly_key, 0, sizeof(poly_key)); + return r; +} + +/* Decrypt and extract the encrypted packet length */ +int +chachapoly_get_length(struct chachapoly_ctx *ctx, unsigned int *plenp, + unsigned int seqnr, const unsigned char *cp, + unsigned int len) +{ + u_char buf[4], seqbuf[8]; + unsigned char *ptr = NULL; + + if(len < 4) + return -1; + ptr = &seqbuf[0]; + _libssh2_store_u64(&ptr, seqnr); + chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); + chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4); + *plenp = _libssh2_ntohu32(buf); + return 0; +} + +int +chachapoly_timingsafe_bcmp(const void *b1, const void *b2, size_t n) +{ + const unsigned char *p1 = b1, *p2 = b2; + int ret = 0; + + for(; n > 0; n--) + ret |= *p1++ ^ *p2++; + return (ret != 0); +} diff --git a/libssh2/src/cipher-chachapoly.h b/libssh2/src/cipher-chachapoly.h new file mode 100644 index 000000000..4d0015cb7 --- /dev/null +++ b/libssh2/src/cipher-chachapoly.h @@ -0,0 +1,41 @@ +/* $OpenBSD: cipher-chachapoly.h,v 1.4 2014/06/24 01:13:21 djm Exp $ */ + +/* + * Copyright (c) Damien Miller 2013 + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#ifndef CHACHA_POLY_AEAD_H +#define CHACHA_POLY_AEAD_H + +#include "chacha.h" +#include "poly1305.h" + +#define CHACHA_KEYLEN 32 /* Only 256 bit keys used here */ + +struct chachapoly_ctx { + struct chacha_ctx main_ctx, header_ctx; +}; + +int chachapoly_init(struct chachapoly_ctx *cpctx, + const u_char *key, u_int keylen); +int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr, + u_char *dest, const u_char *src, u_int len, u_int aadlen, + int do_encrypt); +int chachapoly_get_length(struct chachapoly_ctx *cpctx, + u_int *plenp, u_int seqnr, const u_char *cp, + u_int len); + +#endif /* CHACHA_POLY_AEAD_H */ diff --git a/libssh2/src/comp.c b/libssh2/src/comp.c index f35650560..ecfb28a31 100644 --- a/libssh2/src/comp.c +++ b/libssh2/src/comp.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2004-2007, 2019, Sara Golemon - * Copyright (c) 2010-2014, Daniel Stenberg +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -206,7 +208,7 @@ comp_method_zlib_comp(LIBSSH2_SESSION *session, } _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "unhandled zlib compression error %d, avail_out", + "unhandled zlib compression error %d, avail_out %u", status, strm->avail_out)); return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compression failure"); } diff --git a/libssh2/src/comp.h b/libssh2/src/comp.h index 82ac2dc95..6a35d6949 100644 --- a/libssh2/src/comp.h +++ b/libssh2/src/comp.h @@ -1,6 +1,6 @@ -#ifndef __LIBSSH2_COMP_H -#define __LIBSSH2_COMP_H -/* Copyright (C) 2009-2010 by Daniel Stenberg +#ifndef LIBSSH2_COMP_H +#define LIBSSH2_COMP_H +/* Copyright (C) Daniel Stenberg * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -35,10 +35,11 @@ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session); -#endif /* __LIBSSH2_COMP_H */ +#endif /* LIBSSH2_COMP_H */ diff --git a/libssh2/src/crypt.c b/libssh2/src/crypt.c index 9652e6cd4..6c816eb44 100644 --- a/libssh2/src/crypt.c +++ b/libssh2/src/crypt.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2009, 2010 Simon Josefsson - * Copyright (c) 2004-2007, Sara Golemon +/* Copyright (C) Simon Josefsson + * Copyright (C) Sara Golemon * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,9 +34,14 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" +#include "cipher-chachapoly.h" + +#include #if defined(LIBSSH2DEBUG) && defined(LIBSSH2_CRYPT_NONE_INSECURE) /* crypt_none_crypt @@ -53,8 +58,12 @@ * */ static int -crypt_none_crypt(LIBSSH2_SESSION * session, unsigned char *buf, - void **abstract, int firstlast) +crypt_none_crypt(LIBSSH2_SESSION * session, + unsigned int seqno, + unsigned char *buf, + size_t buf_len, + void **abstract, + int firstlast) { /* Do nothing to the data! */ return 0; @@ -78,6 +87,7 @@ struct crypt_ctx int encrypt; _libssh2_cipher_type(algo); _libssh2_cipher_ctx h; + struct chachapoly_ctx chachapoly_ctx; }; static int @@ -105,13 +115,18 @@ crypt_init(LIBSSH2_SESSION * session, } static int -crypt_encrypt(LIBSSH2_SESSION * session, unsigned char *block, - size_t blocksize, void **abstract, int firstlast) +crypt_encrypt(LIBSSH2_SESSION * session, + unsigned int seqno, + unsigned char *buf, + size_t buf_len, + void **abstract, + int firstlast) { struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract; (void) session; - return _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block, - blocksize, firstlast); + (void) seqno; + return _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, buf, + buf_len, firstlast); } static int @@ -133,8 +148,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_gcm = { 16, /* blocksize */ 12, /* initial value length */ 32, /* secret length -- 32*8 == 256bit */ + 16, /* length of the authentication tag */ LIBSSH2_CRYPT_FLAG_INTEGRATED_MAC | LIBSSH2_CRYPT_FLAG_PKTLEN_AAD, &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes256gcm @@ -146,8 +163,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_gcm = { 16, /* blocksize */ 12, /* initial value length */ 16, /* secret length -- 16*8 == 128bit */ + 16, /* length of the authentication tag */ LIBSSH2_CRYPT_FLAG_INTEGRATED_MAC | LIBSSH2_CRYPT_FLAG_PKTLEN_AAD, &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes128gcm @@ -161,8 +180,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = { 16, /* blocksize */ 16, /* initial value length */ 16, /* secret length -- 16*8 == 128bit */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes128ctr @@ -174,8 +195,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = { 16, /* blocksize */ 16, /* initial value length */ 24, /* secret length -- 24*8 == 192bit */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes192ctr @@ -187,8 +210,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = { 16, /* blocksize */ 16, /* initial value length */ 32, /* secret length -- 32*8 == 256bit */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes256ctr @@ -202,8 +227,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = { 16, /* blocksize */ 16, /* initial value length */ 16, /* secret length -- 16*8 == 128bit */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes128 @@ -215,8 +242,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = { 16, /* blocksize */ 16, /* initial value length */ 24, /* secret length -- 24*8 == 192bit */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes192 @@ -228,8 +257,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = { 16, /* blocksize */ 16, /* initial value length */ 32, /* secret length -- 32*8 == 256bit */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes256 @@ -243,8 +274,10 @@ static const LIBSSH2_CRYPT_METHOD 16, /* blocksize */ 16, /* initial value length */ 32, /* secret length -- 32*8 == 256bit */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_aes256 @@ -258,8 +291,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = { 8, /* blocksize */ 8, /* initial value length */ 16, /* secret length */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_blowfish @@ -273,8 +308,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = { 8, /* blocksize */ 8, /* initial value length */ 16, /* secret length */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_arcfour @@ -310,8 +347,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = { 8, /* blocksize */ 8, /* initial value length */ 16, /* secret length */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init_arcfour128, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_arcfour @@ -325,8 +364,10 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = { 8, /* blocksize */ 8, /* initial value length */ 16, /* secret length */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_cast5 @@ -340,17 +381,132 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = { 8, /* blocksize */ 8, /* initial value length */ 24, /* secret length */ + 0, /* length of the authentication tag */ 0, /* flags */ &crypt_init, + NULL, &crypt_encrypt, &crypt_dtor, _libssh2_cipher_3des }; #endif +static int +crypt_init_chacha20_poly(LIBSSH2_SESSION * session, + const LIBSSH2_CRYPT_METHOD * method, + unsigned char *iv, int *free_iv, + unsigned char *secret, int *free_secret, + int encrypt, void **abstract) +{ + struct crypt_ctx *ctx = LIBSSH2_ALLOC(session, + sizeof(struct crypt_ctx)); + + (void)iv; + + if(!ctx) + return LIBSSH2_ERROR_ALLOC; + + ctx->encrypt = encrypt; + ctx->algo = method->algo; + + if(chachapoly_init(&ctx->chachapoly_ctx, secret, method->secret_len)) { + LIBSSH2_FREE(session, ctx); + return -1; + } + + *abstract = ctx; + *free_iv = 1; + *free_secret = 1; + return 0; +} + + +static int +crypt_encrypt_chacha20_poly_buffer(LIBSSH2_SESSION * session, + unsigned int seqno, + unsigned char *buf, + size_t buf_len, + void **abstract, + int firstlast) +{ + int ret = 1; + struct crypt_ctx *ctx = *(struct crypt_ctx **) abstract; + + (void)session; + (void)firstlast; + + if(ctx) { + if(ctx->encrypt) { + /* requires out_buf to be large enough to hold encrypted output + plus auth tag (auth len) + + buf is a full packet so we need to subtract packet length from + length + */ + ret = chachapoly_crypt(&ctx->chachapoly_ctx, seqno, buf, buf, + ((u_int)buf_len) - 4, 4, ctx->encrypt); + } + else { + /* buf is full packet including size and auth tag but buf_len + doesn't include size */ + ret = chachapoly_crypt(&ctx->chachapoly_ctx, seqno, buf, buf, + ((u_int)buf_len), 4, ctx->encrypt); + + /* the api expects the size field to already be removed + from the decrypted packet so we'll help it out */ + if(ret == 0) { + memmove(buf, buf + 4, buf_len - 4); + } + } + } + + return (ret == 0 ? 0 : 1); +} + +static int +crypt_get_length_chacha20_poly(LIBSSH2_SESSION * session, unsigned int seqno, + unsigned char *data, size_t data_size, + unsigned int *len, void **abstract) +{ + struct crypt_ctx *ctx = *(struct crypt_ctx **) abstract; + + (void)session; + + return chachapoly_get_length(&ctx->chachapoly_ctx, len, seqno, data, + (u_int)data_size); +} + +static int +crypt_dtor_chacha20_poly(LIBSSH2_SESSION * session, void **abstract) +{ + struct crypt_ctx **cctx = (struct crypt_ctx **) abstract; + if(cctx && *cctx) { + LIBSSH2_FREE(session, *cctx); + *abstract = NULL; + } + return 0; +} + +static const LIBSSH2_CRYPT_METHOD + libssh2_crypt_method_chacha20_poly1305_openssh = { + "chacha20-poly1305@openssh.com", + "", + 8, /* blocksize */ + 0, /* initial value length */ + 64, /* secret length */ + 16, /* length of the auth_tag */ + LIBSSH2_CRYPT_FLAG_REQUIRES_FULL_PACKET, /* flags */ + &crypt_init_chacha20_poly, + &crypt_get_length_chacha20_poly, + &crypt_encrypt_chacha20_poly_buffer, + &crypt_dtor_chacha20_poly, + _libssh2_cipher_chacha20 /* not actually used */ +}; + /* These are the crypt methods that are available to be negotiated. Methods towards the start are chosen in preference to ones further down the list. */ static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = { + &libssh2_crypt_method_chacha20_poly1305_openssh, #if LIBSSH2_AES_GCM &libssh2_crypt_method_aes256_gcm, &libssh2_crypt_method_aes128_gcm, diff --git a/libssh2/src/crypto.c b/libssh2/src/crypto.c index b91dc37a7..b3b1afcb1 100644 --- a/libssh2/src/crypto.c +++ b/libssh2/src/crypto.c @@ -1,3 +1,8 @@ +/* Copyright (C) Viktor Szakats + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #define LIBSSH2_CRYPTO_C #include "libssh2_priv.h" diff --git a/libssh2/src/crypto.h b/libssh2/src/crypto.h index 4d3d49ccd..487444145 100644 --- a/libssh2/src/crypto.h +++ b/libssh2/src/crypto.h @@ -1,8 +1,9 @@ -#ifndef __LIBSSH2_CRYPTO_H -#define __LIBSSH2_CRYPTO_H -/* Copyright (C) 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2010-2019 Daniel Stenberg +#ifndef LIBSSH2_CRYPTO_H +#define LIBSSH2_CRYPTO_H +/* Copyright (C) Simon Josefsson + * Copyright (C) The Written Word, Inc. + * Copyright (C) Daniel Stenberg + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -36,6 +37,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #if defined(LIBSSH2_OPENSSL) || defined(LIBSSH2_WOLFSSL) @@ -52,70 +55,26 @@ #error "no cryptography backend selected" #endif -#ifdef LIBSSH2_NO_MD5 -#undef LIBSSH2_MD5 -#define LIBSSH2_MD5 0 +/* return: success = 1, error = 0 */ +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx); +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); #endif - -#ifdef LIBSSH2_NO_HMAC_RIPEMD -#undef LIBSSH2_HMAC_RIPEMD -#define LIBSSH2_HMAC_RIPEMD 0 -#endif - -#ifdef LIBSSH2_NO_DSA -#undef LIBSSH2_DSA -#define LIBSSH2_DSA 0 -#endif - -#ifdef LIBSSH2_NO_RSA -#undef LIBSSH2_RSA -#define LIBSSH2_RSA 0 -#endif - -#ifdef LIBSSH2_NO_RSA_SHA1 -#undef LIBSSH2_RSA_SHA1 -#define LIBSSH2_RSA_SHA1 0 -#endif - -#ifdef LIBSSH2_NO_ECDSA -#undef LIBSSH2_ECDSA -#define LIBSSH2_ECDSA 0 -#endif - -#ifdef LIBSSH2_NO_ED25519 -#undef LIBSSH2_ED25519 -#define LIBSSH2_ED25519 0 -#endif - -#ifdef LIBSSH2_NO_AES_CTR -#undef LIBSSH2_AES_CTR -#define LIBSSH2_AES_CTR 0 -#endif - -#ifdef LIBSSH2_NO_AES_CBC -#undef LIBSSH2_AES_CBC -#define LIBSSH2_AES_CBC 0 -#endif - -#ifdef LIBSSH2_NO_BLOWFISH -#undef LIBSSH2_BLOWFISH -#define LIBSSH2_BLOWFISH 0 -#endif - -#ifdef LIBSSH2_NO_RC4 -#undef LIBSSH2_RC4 -#define LIBSSH2_RC4 0 -#endif - -#ifdef LIBSSH2_NO_CAST -#undef LIBSSH2_CAST -#define LIBSSH2_CAST 0 -#endif - -#ifdef LIBSSH2_NO_3DES -#undef LIBSSH2_3DES -#define LIBSSH2_3DES 0 +#if LIBSSH2_HMAC_RIPEMD +int _libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); #endif +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen); +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen); +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *data); +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx); #define LIBSSH2_ED25519_KEY_LEN 32 #define LIBSSH2_ED25519_PRIVATE_KEY_LEN 64 @@ -143,16 +102,16 @@ int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, const char *filename, unsigned const char *passphrase); #if LIBSSH2_RSA_SHA1 -int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, - const unsigned char *sig, - size_t sig_len, - const unsigned char *m, size_t m_len); int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, libssh2_rsa_ctx * rsactx, const unsigned char *hash, size_t hash_len, unsigned char **signature, size_t *signature_len); +int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, + const unsigned char *sig, + size_t sig_len, + const unsigned char *m, size_t m_len); #endif #if LIBSSH2_RSA_SHA2 int _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, @@ -194,7 +153,7 @@ int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, const unsigned char *m, size_t m_len); int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, const unsigned char *hash, - unsigned long hash_len, unsigned char *sig); + size_t hash_len, unsigned char *sig); int _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa, LIBSSH2_SESSION * session, const char *filedata, @@ -245,7 +204,7 @@ _libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key, int _libssh2_ecdsa_sign(LIBSSH2_SESSION *session, libssh2_ecdsa_ctx *ec_ctx, - const unsigned char *hash, unsigned long hash_len, + const unsigned char *hash, size_t hash_len, unsigned char **signature, size_t *signature_len); int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, @@ -395,4 +354,4 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, unsigned char *key_method, size_t key_method_len); -#endif /* __LIBSSH2_CRYPTO_H */ +#endif /* LIBSSH2_CRYPTO_H */ diff --git a/libssh2/src/crypto_config.h b/libssh2/src/crypto_config.h new file mode 100644 index 000000000..885a6a918 --- /dev/null +++ b/libssh2/src/crypto_config.h @@ -0,0 +1,76 @@ +/* Copyright (C) Viktor Szakats + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define LIBSSH2_MD5_PEM LIBSSH2_MD5 + +#ifdef LIBSSH2_NO_MD5 +#undef LIBSSH2_MD5 +#define LIBSSH2_MD5 0 +#endif + +#ifdef LIBSSH2_NO_MD5_PEM +#undef LIBSSH2_MD5_PEM +#define LIBSSH2_MD5_PEM 0 +#endif + +#ifdef LIBSSH2_NO_HMAC_RIPEMD +#undef LIBSSH2_HMAC_RIPEMD +#define LIBSSH2_HMAC_RIPEMD 0 +#endif + +#if !defined(LIBSSH2_DSA_ENABLE) +#undef LIBSSH2_DSA +#define LIBSSH2_DSA 0 +#endif + +#ifdef LIBSSH2_NO_RSA +#undef LIBSSH2_RSA +#define LIBSSH2_RSA 0 +#endif + +#ifdef LIBSSH2_NO_RSA_SHA1 +#undef LIBSSH2_RSA_SHA1 +#define LIBSSH2_RSA_SHA1 0 +#endif + +#ifdef LIBSSH2_NO_ECDSA +#undef LIBSSH2_ECDSA +#define LIBSSH2_ECDSA 0 +#endif + +#ifdef LIBSSH2_NO_ED25519 +#undef LIBSSH2_ED25519 +#define LIBSSH2_ED25519 0 +#endif + +#ifdef LIBSSH2_NO_AES_CTR +#undef LIBSSH2_AES_CTR +#define LIBSSH2_AES_CTR 0 +#endif + +#ifdef LIBSSH2_NO_AES_CBC +#undef LIBSSH2_AES_CBC +#define LIBSSH2_AES_CBC 0 +#endif + +#ifdef LIBSSH2_NO_BLOWFISH +#undef LIBSSH2_BLOWFISH +#define LIBSSH2_BLOWFISH 0 +#endif + +#ifdef LIBSSH2_NO_RC4 +#undef LIBSSH2_RC4 +#define LIBSSH2_RC4 0 +#endif + +#ifdef LIBSSH2_NO_CAST +#undef LIBSSH2_CAST +#define LIBSSH2_CAST 0 +#endif + +#ifdef LIBSSH2_NO_3DES +#undef LIBSSH2_3DES +#define LIBSSH2_3DES 0 +#endif diff --git a/libssh2/src/global.c b/libssh2/src/global.c index c5894364e..a8bc38078 100644 --- a/libssh2/src/global.c +++ b/libssh2/src/global.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2010 Lars Nordin - * Copyright (C) 2010 Simon Josefsson +/* Copyright (C) Lars Nordin + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" diff --git a/libssh2/src/hostkey.c b/libssh2/src/hostkey.c index f38236768..99eaf3e07 100644 --- a/libssh2/src/hostkey.c +++ b/libssh2/src/hostkey.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2004-2006, Sara Golemon - * Copyright (c) 2009-2019 by Daniel Stenberg +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -104,7 +106,7 @@ hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session, #endif { _libssh2_debug((session, LIBSSH2_TRACE_ERROR, - "unexpected rsa type: %.*s", type_len, type)); + "unexpected rsa type: %.*s", (int)type_len, type)); return -1; } @@ -240,11 +242,18 @@ hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session, unsigned char hash[SHA_DIGEST_LENGTH]; libssh2_sha1_ctx ctx; - (void)libssh2_sha1_init(&ctx); - for(i = 0; i < veccount; i++) { - libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len); + if(!libssh2_sha1_init(&ctx)) { + return -1; + } + for(i = 0; i < veccount; i++) { + if(!libssh2_sha1_update(ctx, + datavec[i].iov_base, datavec[i].iov_len)) { + return -1; + } + } + if(!libssh2_sha1_final(ctx, hash)) { + return -1; } - libssh2_sha1_final(ctx, hash); ret = _libssh2_rsa_sha1_sign(session, rsactx, hash, SHA_DIGEST_LENGTH, signature, signature_len); @@ -314,9 +323,14 @@ hostkey_method_ssh_rsa_sha2_256_signv(LIBSSH2_SESSION * session, return -1; } for(i = 0; i < veccount; i++) { - libssh2_sha256_update(ctx, datavec[i].iov_base, datavec[i].iov_len); + if(!libssh2_sha256_update(ctx, + datavec[i].iov_base, datavec[i].iov_len)) { + return -1; + } + } + if(!libssh2_sha256_final(ctx, hash)) { + return -1; } - libssh2_sha256_final(ctx, hash); ret = _libssh2_rsa_sha2_sign(session, rsactx, hash, SHA256_DIGEST_LENGTH, signature, signature_len); @@ -384,9 +398,14 @@ hostkey_method_ssh_rsa_sha2_512_signv(LIBSSH2_SESSION * session, return -1; } for(i = 0; i < veccount; i++) { - libssh2_sha512_update(ctx, datavec[i].iov_base, datavec[i].iov_len); + if(!libssh2_sha512_update(ctx, + datavec[i].iov_base, datavec[i].iov_len)) { + return -1; + } + } + if(!libssh2_sha512_final(ctx, hash)) { + return -1; } - libssh2_sha512_final(ctx, hash); ret = _libssh2_rsa_sha2_sign(session, rsactx, hash, SHA512_DIGEST_LENGTH, signature, signature_len); @@ -479,6 +498,34 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa_cert = { #endif /* LIBSSH2_RSA_SHA1 */ +#if LIBSSH2_RSA_SHA2 + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa_sha2_256_cert = { + "rsa-sha2-256-cert-v01@openssh.com", + SHA256_DIGEST_LENGTH, + NULL, + hostkey_method_ssh_rsa_initPEM, + hostkey_method_ssh_rsa_initPEMFromMemory, + NULL, + hostkey_method_ssh_rsa_sha2_256_signv, + NULL, /* encrypt */ + hostkey_method_ssh_rsa_dtor, +}; + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa_sha2_512_cert = { + "rsa-sha2-512-cert-v01@openssh.com", + SHA512_DIGEST_LENGTH, + NULL, + hostkey_method_ssh_rsa_initPEM, + hostkey_method_ssh_rsa_initPEMFromMemory, + NULL, + hostkey_method_ssh_rsa_sha2_512_signv, + NULL, /* encrypt */ + hostkey_method_ssh_rsa_dtor, +}; + +#endif /* LIBSSH2_RSA_SHA2 */ + #endif /* LIBSSH2_RSA */ #if LIBSSH2_DSA @@ -657,6 +704,12 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, libssh2_sha1_ctx ctx; int i; + if(!libssh2_sha1_init(&ctx)) { + *signature = NULL; + *signature_len = 0; + return -1; + } + *signature = LIBSSH2_CALLOC(session, 2 * SHA_DIGEST_LENGTH); if(!*signature) { return -1; @@ -664,11 +717,15 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, *signature_len = 2 * SHA_DIGEST_LENGTH; - (void)libssh2_sha1_init(&ctx); for(i = 0; i < veccount; i++) { - libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len); + if(!libssh2_sha1_update(ctx, + datavec[i].iov_base, datavec[i].iov_len)) { + return -1; + } + } + if(!libssh2_sha1_final(ctx, hash)) { + return -1; } - libssh2_sha1_final(ctx, hash); if(_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) { LIBSSH2_FREE(session, *signature); @@ -907,20 +964,33 @@ hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session, } -#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type) \ - do { \ - unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ - libssh2_sha##digest_type##_ctx ctx; \ - int i; \ - (void)libssh2_sha##digest_type##_init(&ctx); \ - for(i = 0; i < veccount; i++) { \ - libssh2_sha##digest_type##_update(ctx, datavec[i].iov_base, \ - datavec[i].iov_len); \ - } \ - libssh2_sha##digest_type##_final(ctx, hash); \ - ret = _libssh2_ecdsa_sign(session, ec_ctx, hash, \ - SHA##digest_type##_DIGEST_LENGTH, \ - signature, signature_len); \ +#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type) \ + do { \ + unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ + libssh2_sha##digest_type##_ctx ctx; \ + int i; \ + if(!libssh2_sha##digest_type##_init(&ctx)) { \ + ret = -1; \ + break; \ + } \ + for(i = 0; i < veccount; i++) { \ + if(!libssh2_sha##digest_type##_update(ctx, \ + datavec[i].iov_base, \ + datavec[i].iov_len)) { \ + ret = -1; \ + break; \ + } \ + } \ + if(ret == -1) { \ + break; \ + } \ + if(!libssh2_sha##digest_type##_final(ctx, hash)) { \ + ret = -1; \ + break; \ + } \ + ret = _libssh2_ecdsa_sign(session, ec_ctx, hash, \ + SHA##digest_type##_DIGEST_LENGTH, \ + signature, signature_len); \ } while(0) @@ -1222,7 +1292,8 @@ hostkey_method_ssh_ed25519_signv(LIBSSH2_SESSION * session, } return _libssh2_ed25519_sign(ctx, session, signature, signature_len, - datavec[0].iov_base, datavec[0].iov_len); + (const uint8_t *)datavec[0].iov_base, + datavec[0].iov_len); } @@ -1289,6 +1360,8 @@ static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = { #if LIBSSH2_RSA_SHA2 &hostkey_method_ssh_rsa_sha2_512, &hostkey_method_ssh_rsa_sha2_256, + &hostkey_method_ssh_rsa_sha2_512_cert, + &hostkey_method_ssh_rsa_sha2_256_cert, #endif /* LIBSSH2_RSA_SHA2 */ #if LIBSSH2_RSA_SHA1 &hostkey_method_ssh_rsa, @@ -1324,18 +1397,15 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) return (session->server_hostkey_md5_valid) ? (char *) session->server_hostkey_md5 : NULL; - break; #endif /* LIBSSH2_MD5 */ case LIBSSH2_HOSTKEY_HASH_SHA1: return (session->server_hostkey_sha1_valid) ? (char *) session->server_hostkey_sha1 : NULL; - break; case LIBSSH2_HOSTKEY_HASH_SHA256: return (session->server_hostkey_sha256_valid) ? (char *) session->server_hostkey_sha256 : NULL; - break; default: return NULL; } @@ -1346,9 +1416,11 @@ static int hostkey_type(const unsigned char *hostkey, size_t len) static const unsigned char rsa[] = { 0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a' }; +#if LIBSSH2_DSA static const unsigned char dss[] = { 0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's' }; +#endif static const unsigned char ecdsa_256[] = { 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', 'n', 'i', 's', 't', 'p', '2', '5', '6' @@ -1371,8 +1443,10 @@ static int hostkey_type(const unsigned char *hostkey, size_t len) if(!memcmp(rsa, hostkey, 11)) return LIBSSH2_HOSTKEY_TYPE_RSA; +#if LIBSSH2_DSA if(!memcmp(dss, hostkey, 11)) return LIBSSH2_HOSTKEY_TYPE_DSS; +#endif if(len < 15) return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; diff --git a/libssh2/src/keepalive.c b/libssh2/src/keepalive.c index f34255d76..489a1daaa 100644 --- a/libssh2/src/keepalive.c +++ b/libssh2/src/keepalive.c @@ -1,5 +1,5 @@ -/* Copyright (C) 2010 Simon Josefsson - * Author: Simon Josefsson +/* Copyright (C) Simon Josefsson + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -34,6 +34,7 @@ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -44,7 +45,7 @@ LIBSSH2_API void libssh2_keepalive_config(LIBSSH2_SESSION *session, int want_reply, - unsigned interval) + unsigned int interval) { if(interval == 1) session->keepalive_interval = 2; diff --git a/libssh2/src/kex.c b/libssh2/src/kex.c index d4034a0a9..4ca9c34c7 100644 --- a/libssh2/src/kex.c +++ b/libssh2/src/kex.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010-2019, Daniel Stenberg +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -53,6 +55,7 @@ /* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */ +#if LIBSSH2_ECDSA #define LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(value, reqlen, version) \ do { \ if(type == LIBSSH2_EC_CURVE_NISTP256) { \ @@ -65,6 +68,7 @@ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, value, reqlen, version); \ } \ } while(0) +#endif #define LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(digest_type, value, \ reqlen, version) \ @@ -77,22 +81,40 @@ do { \ } \ if(value) \ while(len < (size_t)reqlen) { \ - (void)libssh2_sha##digest_type##_init(&hash); \ - libssh2_sha##digest_type##_update(hash, \ - exchange_state->k_value, \ - exchange_state->k_value_len); \ - libssh2_sha##digest_type##_update(hash, \ - exchange_state->h_sig_comp, \ - SHA##digest_type##_DIGEST_LENGTH); \ + if(!libssh2_sha##digest_type##_init(&hash) || \ + !libssh2_sha##digest_type##_update(hash, \ + exchange_state->k_value, \ + exchange_state->k_value_len) || \ + !libssh2_sha##digest_type##_update(hash, \ + exchange_state->h_sig_comp, \ + SHA##digest_type##_DIGEST_LENGTH)) { \ + LIBSSH2_FREE(session, value); \ + value = NULL; \ + break; \ + } \ if(len > 0) { \ - libssh2_sha##digest_type##_update(hash, value, len); \ + if(!libssh2_sha##digest_type##_update(hash, value, len)) { \ + LIBSSH2_FREE(session, value); \ + value = NULL; \ + break; \ + } \ } \ else { \ - libssh2_sha##digest_type##_update(hash, (version), 1); \ - libssh2_sha##digest_type##_update(hash, session->session_id,\ - session->session_id_len); \ + if(!libssh2_sha##digest_type##_update(hash, \ + (version), 1) || \ + !libssh2_sha##digest_type##_update(hash, \ + session->session_id, \ + session->session_id_len)) { \ + LIBSSH2_FREE(session, value); \ + value = NULL; \ + break; \ + } \ + } \ + if(!libssh2_sha##digest_type##_final(hash, (value) + len)) { \ + LIBSSH2_FREE(session, value); \ + value = NULL; \ + break; \ } \ - libssh2_sha##digest_type##_final(hash, (value) + len); \ len += SHA##digest_type##_DIGEST_LENGTH; \ } \ } while(0) @@ -104,75 +126,80 @@ do { \ * don't allow it so we have to wrap them up in helper functions */ -static void _libssh2_sha_algo_ctx_init(int sha_algo, void *ctx) +static int _libssh2_sha_algo_ctx_init(int sha_algo, void *ctx) { if(sha_algo == 512) { - (void)libssh2_sha512_init((libssh2_sha512_ctx*)ctx); + return libssh2_sha512_init((libssh2_sha512_ctx*)ctx); } else if(sha_algo == 384) { - (void)libssh2_sha384_init((libssh2_sha384_ctx*)ctx); + return libssh2_sha384_init((libssh2_sha384_ctx*)ctx); } else if(sha_algo == 256) { - (void)libssh2_sha256_init((libssh2_sha256_ctx*)ctx); + return libssh2_sha256_init((libssh2_sha256_ctx*)ctx); } else if(sha_algo == 1) { - (void)libssh2_sha1_init((libssh2_sha1_ctx*)ctx); - } - else { - assert(0); - } -} - -static void _libssh2_sha_algo_ctx_update(int sha_algo, void *ctx, - void *data, size_t len) -{ - if(sha_algo == 512) { - libssh2_sha512_ctx *_ctx = (libssh2_sha512_ctx*)ctx; - libssh2_sha512_update(*_ctx, data, len); - } - else if(sha_algo == 384) { - libssh2_sha384_ctx *_ctx = (libssh2_sha384_ctx*)ctx; - libssh2_sha384_update(*_ctx, data, len); - } - else if(sha_algo == 256) { - libssh2_sha256_ctx *_ctx = (libssh2_sha256_ctx*)ctx; - libssh2_sha256_update(*_ctx, data, len); - } - else if(sha_algo == 1) { - libssh2_sha1_ctx *_ctx = (libssh2_sha1_ctx*)ctx; - libssh2_sha1_update(*_ctx, data, len); + return libssh2_sha1_init((libssh2_sha1_ctx*)ctx); } else { #ifdef LIBSSH2DEBUG assert(0); #endif } + return 0; } -static void _libssh2_sha_algo_ctx_final(int sha_algo, void *ctx, - void *hash) +static int _libssh2_sha_algo_ctx_update(int sha_algo, void *ctx, + void *data, size_t len) { if(sha_algo == 512) { libssh2_sha512_ctx *_ctx = (libssh2_sha512_ctx*)ctx; - libssh2_sha512_final(*_ctx, hash); + return libssh2_sha512_update(*_ctx, data, len); } else if(sha_algo == 384) { libssh2_sha384_ctx *_ctx = (libssh2_sha384_ctx*)ctx; - libssh2_sha384_final(*_ctx, hash); + return libssh2_sha384_update(*_ctx, data, len); } else if(sha_algo == 256) { libssh2_sha256_ctx *_ctx = (libssh2_sha256_ctx*)ctx; - libssh2_sha256_final(*_ctx, hash); + return libssh2_sha256_update(*_ctx, data, len); } else if(sha_algo == 1) { libssh2_sha1_ctx *_ctx = (libssh2_sha1_ctx*)ctx; - libssh2_sha1_final(*_ctx, hash); + return libssh2_sha1_update(*_ctx, data, len); } else { #ifdef LIBSSH2DEBUG assert(0); #endif } + return 0; +} + +static int _libssh2_sha_algo_ctx_final(int sha_algo, void *ctx, + void *hash) +{ + if(sha_algo == 512) { + libssh2_sha512_ctx *_ctx = (libssh2_sha512_ctx*)ctx; + return libssh2_sha512_final(*_ctx, hash); + } + else if(sha_algo == 384) { + libssh2_sha384_ctx *_ctx = (libssh2_sha384_ctx*)ctx; + return libssh2_sha384_final(*_ctx, hash); + } + else if(sha_algo == 256) { + libssh2_sha256_ctx *_ctx = (libssh2_sha256_ctx*)ctx; + return libssh2_sha256_final(*_ctx, hash); + } + else if(sha_algo == 1) { + libssh2_sha1_ctx *_ctx = (libssh2_sha1_ctx*)ctx; + return libssh2_sha1_final(*_ctx, hash); + } + else { +#ifdef LIBSSH2DEBUG + assert(0); +#endif + } + return 0; } static void _libssh2_sha_algo_value_hash(int sha_algo, @@ -201,6 +228,60 @@ static void _libssh2_sha_algo_value_hash(int sha_algo, } +static void +diffie_hellman_state_cleanup(LIBSSH2_SESSION * session, + kmdhgGPshakex_state_t *exchange_state) +{ + libssh2_dh_dtor(&exchange_state->x); + _libssh2_bn_free(exchange_state->e); + exchange_state->e = NULL; + _libssh2_bn_free(exchange_state->f); + exchange_state->f = NULL; + _libssh2_bn_free(exchange_state->k); + exchange_state->k = NULL; + _libssh2_bn_ctx_free(exchange_state->ctx); + exchange_state->ctx = NULL; + + if(exchange_state->e_packet) { + LIBSSH2_FREE(session, exchange_state->e_packet); + exchange_state->e_packet = NULL; + } + + if(exchange_state->s_packet) { + LIBSSH2_FREE(session, exchange_state->s_packet); + exchange_state->s_packet = NULL; + } + + if(exchange_state->k_value) { + LIBSSH2_FREE(session, exchange_state->k_value); + exchange_state->k_value = NULL; + } + + exchange_state->state = libssh2_NB_state_idle; +} + +static void +kex_diffie_hellman_cleanup(LIBSSH2_SESSION * session, + key_exchange_state_low_t * key_state) { + if(key_state->state != libssh2_NB_state_idle) { + _libssh2_bn_free(key_state->p); + key_state->p = NULL; + _libssh2_bn_free(key_state->g); + key_state->g = NULL; + + if(key_state->data) { + LIBSSH2_FREE(session, key_state->data); + key_state->data = NULL; + } + key_state->state = libssh2_NB_state_idle; + } + + if(key_state->exchange_state.state != libssh2_NB_state_idle) { + diffie_hellman_state_cleanup(session, &key_state->exchange_state); + } +} + + /*! * @function diffie_hellman_sha_algo * @abstract Diffie Hellman Key Exchange, Group Agnostic, @@ -289,17 +370,25 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, _libssh2_htonu32(exchange_state->e_packet + 1, (uint32_t)(exchange_state->e_packet_len - 5)); if(_libssh2_bn_bits(exchange_state->e) % 8) { - _libssh2_bn_to_bin(exchange_state->e, - exchange_state->e_packet + 5); + if(_libssh2_bn_to_bin(exchange_state->e, + exchange_state->e_packet + 5)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Can't write exchange_state->e"); + goto clean_exit; + } } else { exchange_state->e_packet[5] = 0; - _libssh2_bn_to_bin(exchange_state->e, - exchange_state->e_packet + 6); + if(_libssh2_bn_to_bin(exchange_state->e, + exchange_state->e_packet + 6)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Can't write exchange_state->e"); + goto clean_exit; + } } - _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Sending KEX packet %d", - (int) packet_type_init)); + _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Sending KEX packet %u", + (unsigned int) packet_type_init)); exchange_state->state = libssh2_NB_state_created; } @@ -353,6 +442,7 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, struct string_buf buf; size_t host_key_len; int err; + int hok; rc = _libssh2_packet_require(session, packet_type_reply, &exchange_state->s_packet, @@ -379,8 +469,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, buf.dataptr = buf.data; buf.dataptr++; /* advance past type */ - if(session->server_hostkey) + if(session->server_hostkey) { LIBSSH2_FREE(session, session->server_hostkey); + session->server_hostkey = NULL; + session->server_hostkey_len = 0; + } if(_libssh2_copy_string(session, &buf, &(session->server_hostkey), &host_key_len)) { @@ -395,11 +488,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, { libssh2_md5_ctx fingerprint_ctx; - if(libssh2_md5_init(&fingerprint_ctx)) { - libssh2_md5_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_md5_final(fingerprint_ctx, - session->server_hostkey_md5); + if(libssh2_md5_init(&fingerprint_ctx) && + libssh2_md5_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_md5_final(fingerprint_ctx, + session->server_hostkey_md5)) { session->server_hostkey_md5_valid = TRUE; } else { @@ -423,11 +516,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, { libssh2_sha1_ctx fingerprint_ctx; - if(libssh2_sha1_init(&fingerprint_ctx)) { - libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_sha1_final(fingerprint_ctx, - session->server_hostkey_sha1); + if(libssh2_sha1_init(&fingerprint_ctx) && + libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_sha1_final(fingerprint_ctx, + session->server_hostkey_sha1)) { session->server_hostkey_sha1_valid = TRUE; } else { @@ -450,11 +543,11 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, { libssh2_sha256_ctx fingerprint_ctx; - if(libssh2_sha256_init(&fingerprint_ctx)) { - libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_sha256_final(fingerprint_ctx, - session->server_hostkey_sha256); + if(libssh2_sha256_init(&fingerprint_ctx) && + libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_sha256_final(fingerprint_ctx, + session->server_hostkey_sha256)) { session->server_hostkey_sha256_valid = TRUE; } else { @@ -494,8 +587,13 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, goto clean_exit; } - _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len, - exchange_state->f_value); + if(_libssh2_bn_from_bin(exchange_state->f, + exchange_state->f_value_len, + exchange_state->f_value)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Invalid DH-SHA f value"); + goto clean_exit; + } if(_libssh2_get_string(&buf, &(exchange_state->h_sig), &(exchange_state->h_sig_len))) { @@ -522,67 +620,84 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, _libssh2_htonu32(exchange_state->k_value, (uint32_t)(exchange_state->k_value_len - 4)); if(_libssh2_bn_bits(exchange_state->k) % 8) { - _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); + if(_libssh2_bn_to_bin(exchange_state->k, + exchange_state->k_value + 4)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Can't write exchange_state->k"); + goto clean_exit; + } } else { exchange_state->k_value[4] = 0; - _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); + if(_libssh2_bn_to_bin(exchange_state->k, + exchange_state->k_value + 5)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Can't write exchange_state->k"); + goto clean_exit; + } } exchange_state->exchange_hash = (void *)&exchange_hash_ctx; - _libssh2_sha_algo_ctx_init(sha_algo_value, exchange_hash_ctx); - + if(!_libssh2_sha_algo_ctx_init(sha_algo_value, exchange_hash_ctx)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HASH_INIT, + "Unable to initialize hash context"); + goto clean_exit; + } + hok = 1; if(session->local.banner) { _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)(strlen((char *) session->local.banner) - 2)); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->local.banner, + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + session->local.banner, strlen((char *) session->local.banner) - 2); } else { _libssh2_htonu32(exchange_state->h_sig_comp, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - (unsigned char *) - LIBSSH2_SSH_DEFAULT_BANNER, + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + (unsigned char *)LIBSSH2_SSH_DEFAULT_BANNER, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); } _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)strlen((char *) session->remote.banner)); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->remote.banner, - strlen((char *) session->remote.banner)); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + session->remote.banner, + strlen((char *)session->remote.banner)); _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)session->local.kexinit_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->local.kexinit, - session->local.kexinit_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + session->local.kexinit, + session->local.kexinit_len); _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)session->remote.kexinit_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->remote.kexinit, - session->remote.kexinit_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + session->remote.kexinit, + session->remote.kexinit_len); _libssh2_htonu32(exchange_state->h_sig_comp, session->server_hostkey_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - session->server_hostkey, - session->server_hostkey_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + session->server_hostkey, + session->server_hostkey_len); if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) { /* diffie-hellman-group-exchange hashes additional fields */ @@ -592,33 +707,41 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, LIBSSH2_DH_GEX_OPTGROUP); _libssh2_htonu32(exchange_state->h_sig_comp + 8, LIBSSH2_DH_GEX_MAXGROUP); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 12); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + exchange_state->h_sig_comp, + 12); } if(midhash) { - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - midhash, midhash_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, + exchange_hash_ctx, + midhash, midhash_len); } - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->e_packet + 1, - exchange_state->e_packet_len - 1); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->e_packet + 1, + exchange_state->e_packet_len - 1); _libssh2_htonu32(exchange_state->h_sig_comp, (uint32_t)exchange_state->f_value_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp, 4); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->f_value, - exchange_state->f_value_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp, 4); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->f_value, + exchange_state->f_value_len); - _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, - exchange_state->k_value, - exchange_state->k_value_len); + hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx, + exchange_state->k_value, + exchange_state->k_value_len); - _libssh2_sha_algo_ctx_final(sha_algo_value, exchange_hash_ctx, - exchange_state->h_sig_comp); + if(!hok || + !_libssh2_sha_algo_ctx_final(sha_algo_value, exchange_hash_ctx, + exchange_state->h_sig_comp)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HASH_CALC, + "kex: failed to calculate hash"); + goto clean_exit; + } err = session->hostkey->sig_verify(session, exchange_state->h_sig, @@ -890,32 +1013,7 @@ static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session, } clean_exit: - libssh2_dh_dtor(&exchange_state->x); - _libssh2_bn_free(exchange_state->e); - exchange_state->e = NULL; - _libssh2_bn_free(exchange_state->f); - exchange_state->f = NULL; - _libssh2_bn_free(exchange_state->k); - exchange_state->k = NULL; - _libssh2_bn_ctx_free(exchange_state->ctx); - exchange_state->ctx = NULL; - - if(exchange_state->e_packet) { - LIBSSH2_FREE(session, exchange_state->e_packet); - exchange_state->e_packet = NULL; - } - - if(exchange_state->s_packet) { - LIBSSH2_FREE(session, exchange_state->s_packet); - exchange_state->s_packet = NULL; - } - - if(exchange_state->k_value) { - LIBSSH2_FREE(session, exchange_state->k_value); - exchange_state->k_value = NULL; - } - - exchange_state->state = libssh2_NB_state_idle; + diffie_hellman_state_cleanup(session, exchange_state); return ret; } @@ -959,8 +1057,16 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session, key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */ /* Initialize P and G */ - _libssh2_bn_set_word(key_state->g, 2); - _libssh2_bn_from_bin(key_state->p, 128, p_value); + if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to allocate key state g."); + goto clean_exit; + } + if(!key_state->p || _libssh2_bn_from_bin(key_state->p, 128, p_value)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to allocate key state p."); + goto clean_exit; + } _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Initiating Diffie-Hellman Group1 Key Exchange")); @@ -976,11 +1082,8 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session, return ret; } - _libssh2_bn_free(key_state->p); - key_state->p = NULL; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; - key_state->state = libssh2_NB_state_idle; +clean_exit: + kex_diffie_hellman_cleanup(session, key_state); return ret; } @@ -1052,8 +1155,17 @@ kex_method_diffie_hellman_group14_key_exchange(LIBSSH2_SESSION *session, /* g == 2 */ /* Initialize P and G */ - _libssh2_bn_set_word(key_state->g, 2); - _libssh2_bn_from_bin(key_state->p, 256, p_value); + if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to allocate key state g."); + goto clean_exit; + } + else if(!key_state->p || + _libssh2_bn_from_bin(key_state->p, 256, p_value)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to allocate key state p."); + goto clean_exit; + } _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Initiating Diffie-Hellman Group14 Key Exchange")); @@ -1067,11 +1179,8 @@ kex_method_diffie_hellman_group14_key_exchange(LIBSSH2_SESSION *session, return ret; } - key_state->state = libssh2_NB_state_idle; - _libssh2_bn_free(key_state->p); - key_state->p = NULL; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; +clean_exit: + kex_diffie_hellman_cleanup(session, key_state); return ret; } @@ -1173,8 +1282,16 @@ kex_method_diffie_hellman_group16_sha512_key_exchange(LIBSSH2_SESSION *session, /* g == 2 */ /* Initialize P and G */ - _libssh2_bn_set_word(key_state->g, 2); - _libssh2_bn_from_bin(key_state->p, 512, p_value); + if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to allocate key state g."); + goto clean_exit; + } + if(!key_state->p || _libssh2_bn_from_bin(key_state->p, 512, p_value)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to allocate key state p."); + goto clean_exit; + } _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Initiating Diffie-Hellman Group16 Key Exchange")); @@ -1190,11 +1307,8 @@ kex_method_diffie_hellman_group16_sha512_key_exchange(LIBSSH2_SESSION *session, return ret; } - key_state->state = libssh2_NB_state_idle; - _libssh2_bn_free(key_state->p); - key_state->p = NULL; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; +clean_exit: + kex_diffie_hellman_cleanup(session, key_state); return ret; } @@ -1305,8 +1419,17 @@ kex_method_diffie_hellman_group18_sha512_key_exchange(LIBSSH2_SESSION *session, /* g == 2 */ /* Initialize P and G */ - _libssh2_bn_set_word(key_state->g, 2); - _libssh2_bn_from_bin(key_state->p, 1024, p_value); + if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to allocate key state g."); + goto clean_exit; + } + else if(!key_state->p || + _libssh2_bn_from_bin(key_state->p, 1024, p_value)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to allocate key state p."); + goto clean_exit; + } _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Initiating Diffie-Hellman Group18 Key Exchange")); @@ -1322,11 +1445,8 @@ kex_method_diffie_hellman_group18_sha512_key_exchange(LIBSSH2_SESSION *session, return ret; } - key_state->state = libssh2_NB_state_idle; - _libssh2_bn_free(key_state->p); - key_state->p = NULL; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; +clean_exit: + kex_diffie_hellman_cleanup(session, key_state); return ret; } @@ -1419,8 +1539,17 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange( goto dh_gex_clean_exit; } - _libssh2_bn_from_bin(key_state->p, p_len, p); - _libssh2_bn_from_bin(key_state->g, g_len, g); + if(_libssh2_bn_from_bin(key_state->p, p_len, p)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Invalid DH-SHA1 p"); + goto dh_gex_clean_exit; + } + + if(_libssh2_bn_from_bin(key_state->g, g_len, g)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Invalid DH-SHA1 g"); + goto dh_gex_clean_exit; + } ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p, (int)p_len, 1, @@ -1433,16 +1562,10 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange( if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } - - LIBSSH2_FREE(session, key_state->data); } dh_gex_clean_exit: - key_state->state = libssh2_NB_state_idle; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; - _libssh2_bn_free(key_state->p); - key_state->p = NULL; + kex_diffie_hellman_cleanup(session, key_state); return ret; } @@ -1538,8 +1661,17 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange( goto dh_gex_clean_exit; } - _libssh2_bn_from_bin(key_state->p, p_len, p); - _libssh2_bn_from_bin(key_state->g, g_len, g); + if(_libssh2_bn_from_bin(key_state->p, p_len, p)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Invalid DH-SHA256 p"); + goto dh_gex_clean_exit; + } + + if(_libssh2_bn_from_bin(key_state->g, g_len, g)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Invalid DH-SHA256 g"); + goto dh_gex_clean_exit; + } ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p, (int)p_len, 256, @@ -1552,20 +1684,15 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange( if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } - - LIBSSH2_FREE(session, key_state->data); } dh_gex_clean_exit: - key_state->state = libssh2_NB_state_idle; - _libssh2_bn_free(key_state->g); - key_state->g = NULL; - _libssh2_bn_free(key_state->p); - key_state->p = NULL; + kex_diffie_hellman_cleanup(session, key_state); return ret; } +#if LIBSSH2_ECDSA /* LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY * @@ -1583,101 +1710,104 @@ dh_gex_clean_exit: * mpint K, shared secret * */ - #define LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(digest_type) \ do { \ libssh2_sha##digest_type##_ctx ctx; \ + int hok; \ + if(!libssh2_sha##digest_type##_init(&ctx)) { \ + rc = -1; \ + break; \ + } \ exchange_state->exchange_hash = (void *)&ctx; \ - (void)libssh2_sha##digest_type##_init(&ctx); \ + hok = 1; \ if(session->local.banner) { \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)(strlen((char *) session->local.banner) - 2)); \ - libssh2_sha##digest_type##_update(ctx, \ - exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - (char *) session->local.banner, \ - strlen((char *) \ - session->local.banner) \ - - 2); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, \ + 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + (char *)session->local.banner, \ + strlen((char *)session->local.banner) \ + - 2); \ } \ else { \ _libssh2_htonu32(exchange_state->h_sig_comp, \ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); \ - libssh2_sha##digest_type##_update(ctx, \ + hok &= libssh2_sha##digest_type##_update(ctx, \ exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - LIBSSH2_SSH_DEFAULT_BANNER, \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + LIBSSH2_SSH_DEFAULT_BANNER, \ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) \ - 1); \ } \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)strlen((char *) session->remote.banner)); \ - libssh2_sha##digest_type##_update(ctx, \ - exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - session->remote.banner, \ - strlen((char *) \ - session->remote.banner)); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, session->remote.banner, \ + strlen((char *)session->remote.banner)); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)session->local.kexinit_len); \ - libssh2_sha##digest_type##_update(ctx, \ - exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - session->local.kexinit, \ - session->local.kexinit_len); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + session->local.kexinit, \ + session->local.kexinit_len); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)session->remote.kexinit_len); \ - libssh2_sha##digest_type##_update(ctx, \ - exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - session->remote.kexinit, \ - session->remote.kexinit_len); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + session->remote.kexinit, \ + session->remote.kexinit_len); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ session->server_hostkey_len); \ - libssh2_sha##digest_type##_update(ctx, \ - exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - session->server_hostkey, \ - session->server_hostkey_len); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + session->server_hostkey, \ + session->server_hostkey_len); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)public_key_len); \ - libssh2_sha##digest_type##_update(ctx, \ - exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - public_key, \ - public_key_len); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + public_key, \ + public_key_len); \ \ _libssh2_htonu32(exchange_state->h_sig_comp, \ (uint32_t)server_public_key_len); \ - libssh2_sha##digest_type##_update(ctx, \ - exchange_state->h_sig_comp, 4); \ - libssh2_sha##digest_type##_update(ctx, \ - server_public_key, \ - server_public_key_len); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + server_public_key, \ + server_public_key_len); \ \ - libssh2_sha##digest_type##_update(ctx, \ - exchange_state->k_value, \ - exchange_state->k_value_len); \ + hok &= libssh2_sha##digest_type##_update(ctx, \ + exchange_state->k_value, \ + exchange_state->k_value_len); \ \ - libssh2_sha##digest_type##_final(ctx, exchange_state->h_sig_comp); \ + if(!hok || \ + !libssh2_sha##digest_type##_final(ctx, exchange_state->h_sig_comp)) { \ + rc = -1; \ + break; \ + } \ \ if(session->hostkey-> \ - sig_verify(session, exchange_state->h_sig, \ - exchange_state->h_sig_len, exchange_state->h_sig_comp, \ - SHA##digest_type##_DIGEST_LENGTH, \ - &session->server_hostkey_abstract)) { \ + sig_verify(session, exchange_state->h_sig, \ + exchange_state->h_sig_len, exchange_state->h_sig_comp, \ + SHA##digest_type##_DIGEST_LENGTH, \ + &session->server_hostkey_abstract)) { \ rc = -1; \ } \ } while(0) - -#if LIBSSH2_ECDSA - /* kex_session_ecdh_curve_type * returns the EC curve type by name used in key exchange */ @@ -1685,7 +1815,6 @@ do { \ static int kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type) { - int ret = 0; libssh2_curve_type type; if(!name) @@ -1698,19 +1827,57 @@ kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type) else if(strcmp(name, "ecdh-sha2-nistp521") == 0) type = LIBSSH2_EC_CURVE_NISTP521; else { -/* silence: - warning C4701: potentially uninitialized local variable 'type' used */ -#if defined(_MSC_VER) - type = (libssh2_curve_type)0; -#endif - ret = -1; + return -1; } - if(ret == 0 && out_type) { + if(out_type) { *out_type = type; } - return ret; + return 0; +} + + +static void +ecdh_exchange_state_cleanup(LIBSSH2_SESSION * session, + kmdhgGPshakex_state_t *exchange_state) +{ + _libssh2_bn_free(exchange_state->k); + exchange_state->k = NULL; + + if(exchange_state->k_value) { + LIBSSH2_FREE(session, exchange_state->k_value); + exchange_state->k_value = NULL; + } + + exchange_state->state = libssh2_NB_state_idle; +} + + +static void +kex_method_ecdh_cleanup +(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) +{ + if(key_state->public_key_oct) { + LIBSSH2_FREE(session, key_state->public_key_oct); + key_state->public_key_oct = NULL; + } + + if(key_state->private_key) { + _libssh2_ecdsa_free(key_state->private_key); + key_state->private_key = NULL; + } + + if(key_state->data) { + LIBSSH2_FREE(session, key_state->data); + key_state->data = NULL; + } + + key_state->state = libssh2_NB_state_idle; + + if(key_state->exchange_state.state != libssh2_NB_state_idle) { + ecdh_exchange_state_cleanup(session, &key_state->exchange_state); + } } @@ -1768,11 +1935,11 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, { libssh2_md5_ctx fingerprint_ctx; - if(libssh2_md5_init(&fingerprint_ctx)) { - libssh2_md5_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_md5_final(fingerprint_ctx, - session->server_hostkey_md5); + if(libssh2_md5_init(&fingerprint_ctx) && + libssh2_md5_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_md5_final(fingerprint_ctx, + session->server_hostkey_md5)) { session->server_hostkey_md5_valid = TRUE; } else { @@ -1796,11 +1963,11 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, { libssh2_sha1_ctx fingerprint_ctx; - if(libssh2_sha1_init(&fingerprint_ctx)) { - libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_sha1_final(fingerprint_ctx, - session->server_hostkey_sha1); + if(libssh2_sha1_init(&fingerprint_ctx) && + libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_sha1_final(fingerprint_ctx, + session->server_hostkey_sha1)) { session->server_hostkey_sha1_valid = TRUE; } else { @@ -1824,11 +1991,11 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, { libssh2_sha256_ctx fingerprint_ctx; - if(libssh2_sha256_init(&fingerprint_ctx)) { - libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_sha256_final(fingerprint_ctx, - session->server_hostkey_sha256); + if(libssh2_sha256_init(&fingerprint_ctx) && + libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_sha256_final(fingerprint_ctx, + session->server_hostkey_sha256)) { session->server_hostkey_sha256_valid = TRUE; } else { @@ -1900,11 +2067,21 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, _libssh2_htonu32(exchange_state->k_value, (uint32_t)(exchange_state->k_value_len - 4)); if(_libssh2_bn_bits(exchange_state->k) % 8) { - _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); + if(_libssh2_bn_to_bin(exchange_state->k, + exchange_state->k_value + 4)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Can't write exchange_state->k"); + goto clean_exit; + } } else { exchange_state->k_value[4] = 0; - _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); + if(_libssh2_bn_to_bin(exchange_state->k, + exchange_state->k_value + 5)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Can't write exchange_state->e"); + goto clean_exit; + } } /* verify hash */ @@ -1913,7 +2090,6 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, case LIBSSH2_EC_CURVE_NISTP256: LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256); break; - case LIBSSH2_EC_CURVE_NISTP384: LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(384); break; @@ -2191,15 +2367,7 @@ static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, } clean_exit: - _libssh2_bn_free(exchange_state->k); - exchange_state->k = NULL; - - if(exchange_state->k_value) { - LIBSSH2_FREE(session, exchange_state->k_value); - exchange_state->k_value = NULL; - } - - exchange_state->state = libssh2_NB_state_idle; + ecdh_exchange_state_cleanup(session, exchange_state); return ret; } @@ -2307,23 +2475,11 @@ kex_method_ecdh_key_exchange if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } - - LIBSSH2_FREE(session, key_state->data); } ecdh_clean_exit: - if(key_state->public_key_oct) { - LIBSSH2_FREE(session, key_state->public_key_oct); - key_state->public_key_oct = NULL; - } - - if(key_state->private_key) { - _libssh2_ecdsa_free(key_state->private_key); - key_state->private_key = NULL; - } - - key_state->state = libssh2_NB_state_idle; + kex_method_ecdh_cleanup(session, key_state); return ret; } @@ -2333,6 +2489,51 @@ ecdh_clean_exit: #if LIBSSH2_ED25519 +static void +curve25519_exchange_state_cleanup(LIBSSH2_SESSION * session, + kmdhgGPshakex_state_t *exchange_state) +{ + _libssh2_bn_free(exchange_state->k); + exchange_state->k = NULL; + + if(exchange_state->k_value) { + LIBSSH2_FREE(session, exchange_state->k_value); + exchange_state->k_value = NULL; + } + + exchange_state->state = libssh2_NB_state_idle; +} + +static void +kex_method_curve25519_cleanup +(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) +{ + if(key_state->curve25519_public_key) { + _libssh2_explicit_zero(key_state->curve25519_public_key, + LIBSSH2_ED25519_KEY_LEN); + LIBSSH2_FREE(session, key_state->curve25519_public_key); + key_state->curve25519_public_key = NULL; + } + + if(key_state->curve25519_private_key) { + _libssh2_explicit_zero(key_state->curve25519_private_key, + LIBSSH2_ED25519_KEY_LEN); + LIBSSH2_FREE(session, key_state->curve25519_private_key); + key_state->curve25519_private_key = NULL; + } + + if(key_state->data) { + LIBSSH2_FREE(session, key_state->data); + key_state->data = NULL; + } + + key_state->state = libssh2_NB_state_idle; + + if(key_state->exchange_state.state != libssh2_NB_state_idle) { + curve25519_exchange_state_cleanup(session, &key_state->exchange_state); + } +} + /* curve25519_sha256 * Elliptic Curve Key Exchange */ @@ -2400,11 +2601,11 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, { libssh2_md5_ctx fingerprint_ctx; - if(libssh2_md5_init(&fingerprint_ctx)) { - libssh2_md5_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_md5_final(fingerprint_ctx, - session->server_hostkey_md5); + if(libssh2_md5_init(&fingerprint_ctx) && + libssh2_md5_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_md5_final(fingerprint_ctx, + session->server_hostkey_md5)) { session->server_hostkey_md5_valid = TRUE; } else { @@ -2428,11 +2629,11 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, { libssh2_sha1_ctx fingerprint_ctx; - if(libssh2_sha1_init(&fingerprint_ctx)) { - libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_sha1_final(fingerprint_ctx, - session->server_hostkey_sha1); + if(libssh2_sha1_init(&fingerprint_ctx) && + libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_sha1_final(fingerprint_ctx, + session->server_hostkey_sha1)) { session->server_hostkey_sha1_valid = TRUE; } else { @@ -2456,11 +2657,11 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, { libssh2_sha256_ctx fingerprint_ctx; - if(libssh2_sha256_init(&fingerprint_ctx)) { - libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, - session->server_hostkey_len); - libssh2_sha256_final(fingerprint_ctx, - session->server_hostkey_sha256); + if(libssh2_sha256_init(&fingerprint_ctx) && + libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len) && + libssh2_sha256_final(fingerprint_ctx, + session->server_hostkey_sha256)) { session->server_hostkey_sha256_valid = TRUE; } else { @@ -2539,11 +2740,21 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, _libssh2_htonu32(exchange_state->k_value, (uint32_t)(exchange_state->k_value_len - 4)); if(_libssh2_bn_bits(exchange_state->k) % 8) { - _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); + if(_libssh2_bn_to_bin(exchange_state->k, + exchange_state->k_value + 4)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Can't write exchange_state->e"); + goto clean_exit; + } } else { exchange_state->k_value[4] = 0; - _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); + if(_libssh2_bn_to_bin(exchange_state->k, + exchange_state->k_value + 5)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Can't write exchange_state->e"); + goto clean_exit; + } } /*/ verify hash */ @@ -2805,15 +3016,7 @@ curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, } clean_exit: - _libssh2_bn_free(exchange_state->k); - exchange_state->k = NULL; - - if(exchange_state->k_value) { - LIBSSH2_FREE(session, exchange_state->k_value); - exchange_state->k_value = NULL; - } - - exchange_state->state = libssh2_NB_state_idle; + curve25519_exchange_state_cleanup(session, exchange_state); return ret; } @@ -2912,27 +3115,11 @@ kex_method_curve25519_key_exchange if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } - - LIBSSH2_FREE(session, key_state->data); } clean_exit: - if(key_state->curve25519_public_key) { - _libssh2_explicit_zero(key_state->curve25519_public_key, - LIBSSH2_ED25519_KEY_LEN); - LIBSSH2_FREE(session, key_state->curve25519_public_key); - key_state->curve25519_public_key = NULL; - } - - if(key_state->curve25519_private_key) { - _libssh2_explicit_zero(key_state->curve25519_private_key, - LIBSSH2_ED25519_KEY_LEN); - LIBSSH2_FREE(session, key_state->curve25519_private_key); - key_state->curve25519_private_key = NULL; - } - - key_state->state = libssh2_NB_state_idle; + kex_method_curve25519_cleanup(session, key_state); return ret; } @@ -2947,30 +3134,35 @@ clean_exit: static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group1_sha1 = { "diffie-hellman-group1-sha1", kex_method_diffie_hellman_group1_sha1_key_exchange, + kex_diffie_hellman_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha1 = { "diffie-hellman-group14-sha1", kex_method_diffie_hellman_group14_sha1_key_exchange, + kex_diffie_hellman_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha256 = { "diffie-hellman-group14-sha256", kex_method_diffie_hellman_group14_sha256_key_exchange, + kex_diffie_hellman_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group16_sha512 = { "diffie-hellman-group16-sha512", kex_method_diffie_hellman_group16_sha512_key_exchange, + kex_diffie_hellman_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group18_sha512 = { "diffie-hellman-group18-sha512", kex_method_diffie_hellman_group18_sha512_key_exchange, + kex_diffie_hellman_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; @@ -2978,6 +3170,7 @@ static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group_exchange_sha1 = { "diffie-hellman-group-exchange-sha1", kex_method_diffie_hellman_group_exchange_sha1_key_exchange, + kex_diffie_hellman_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; @@ -2985,6 +3178,7 @@ static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group_exchange_sha256 = { "diffie-hellman-group-exchange-sha256", kex_method_diffie_hellman_group_exchange_sha256_key_exchange, + kex_diffie_hellman_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; @@ -2993,6 +3187,7 @@ static const LIBSSH2_KEX_METHOD kex_method_ecdh_sha2_nistp256 = { "ecdh-sha2-nistp256", kex_method_ecdh_key_exchange, + kex_method_ecdh_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; @@ -3000,6 +3195,7 @@ static const LIBSSH2_KEX_METHOD kex_method_ecdh_sha2_nistp384 = { "ecdh-sha2-nistp384", kex_method_ecdh_key_exchange, + kex_method_ecdh_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; @@ -3007,6 +3203,7 @@ static const LIBSSH2_KEX_METHOD kex_method_ecdh_sha2_nistp521 = { "ecdh-sha2-nistp521", kex_method_ecdh_key_exchange, + kex_method_ecdh_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; #endif @@ -3016,12 +3213,14 @@ static const LIBSSH2_KEX_METHOD kex_method_ssh_curve25519_sha256_libssh = { "curve25519-sha256@libssh.org", kex_method_curve25519_key_exchange, + kex_method_curve25519_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; static const LIBSSH2_KEX_METHOD kex_method_ssh_curve25519_sha256 = { "curve25519-sha256", kex_method_curve25519_key_exchange, + kex_method_curve25519_cleanup, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; #endif @@ -3034,6 +3233,15 @@ static const LIBSSH2_KEX_METHOD kex_method_extension_negotiation = { "ext-info-c", NULL, + NULL, + 0, +}; + +static const LIBSSH2_KEX_METHOD +kex_method_strict_client_extension = { + "kex-strict-c-v00@openssh.com", + NULL, + NULL, 0, }; @@ -3055,6 +3263,7 @@ static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { &kex_method_diffie_helman_group1_sha1, &kex_method_diffie_helman_group_exchange_sha1, &kex_method_extension_negotiation, + &kex_method_strict_client_extension, NULL }; @@ -3307,13 +3516,13 @@ static int kexinit(LIBSSH2_SESSION * session) return 0; } -/* kex_agree_instr +/* _libssh2_kex_agree_instr * Kex specific variant of strstr() * Needle must be preceded by BOL or ',', and followed by ',' or EOL */ -static unsigned char * -kex_agree_instr(unsigned char *haystack, size_t haystack_len, - const unsigned char *needle, size_t needle_len) +unsigned char * +_libssh2_kex_agree_instr(unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) { unsigned char *s; unsigned char *end_haystack; @@ -3346,6 +3555,7 @@ kex_agree_instr(unsigned char *haystack, size_t haystack_len, left = end_haystack - s; if((left >= 1) && (left <= haystack_len) && (left > needle_len)) { s++; + left--; } else { return NULL; @@ -3398,7 +3608,7 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session, while(s && *s) { unsigned char *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if(kex_agree_instr(hostkey, hostkey_len, s, method_len)) { + if(_libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) { const LIBSSH2_HOSTKEY_METHOD *method = (const LIBSSH2_HOSTKEY_METHOD *) kex_get_method_by_name((char *) s, method_len, @@ -3432,9 +3642,9 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session, } while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) { - s = kex_agree_instr(hostkey, hostkey_len, - (unsigned char *) (*hostkeyp)->name, - strlen((*hostkeyp)->name)); + s = _libssh2_kex_agree_instr(hostkey, hostkey_len, + (unsigned char *) (*hostkeyp)->name, + strlen((*hostkeyp)->name)); if(s) { /* So far so good, but does it suit our purposes? (Encrypting vs Signing) */ @@ -3468,6 +3678,12 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, { const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods; unsigned char *s; + const unsigned char *strict = + (unsigned char *)"kex-strict-s-v00@openssh.com"; + + if(_libssh2_kex_agree_instr(kex, kex_len, strict, 28)) { + session->kex_strict = 1; + } if(session->kex_prefs) { s = (unsigned char *) session->kex_prefs; @@ -3475,7 +3691,7 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, while(s && *s) { unsigned char *q, *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - q = kex_agree_instr(kex, kex_len, s, method_len); + q = _libssh2_kex_agree_instr(kex, kex_len, s, method_len); if(q) { const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *) kex_get_method_by_name((char *) s, method_len, @@ -3509,9 +3725,9 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, } while(*kexp && (*kexp)->name) { - s = kex_agree_instr(kex, kex_len, - (unsigned char *) (*kexp)->name, - strlen((*kexp)->name)); + s = _libssh2_kex_agree_instr(kex, kex_len, + (unsigned char *) (*kexp)->name, + strlen((*kexp)->name)); if(s) { /* We've agreed on a key exchange method, * Can we agree on a hostkey that works with this kex? @@ -3555,7 +3771,7 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session, unsigned char *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if(kex_agree_instr(crypt, crypt_len, s, method_len)) { + if(_libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) { const LIBSSH2_CRYPT_METHOD *method = (const LIBSSH2_CRYPT_METHOD *) kex_get_method_by_name((char *) s, method_len, @@ -3577,9 +3793,9 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session, } while(*cryptp && (*cryptp)->name) { - s = kex_agree_instr(crypt, crypt_len, - (unsigned char *) (*cryptp)->name, - strlen((*cryptp)->name)); + s = _libssh2_kex_agree_instr(crypt, crypt_len, + (unsigned char *) (*cryptp)->name, + strlen((*cryptp)->name)); if(s) { endpoint->crypt = *cryptp; return 0; @@ -3619,7 +3835,7 @@ static int kex_agree_mac(LIBSSH2_SESSION * session, unsigned char *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if(kex_agree_instr(mac, mac_len, s, method_len)) { + if(_libssh2_kex_agree_instr(mac, mac_len, s, method_len)) { const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *) kex_get_method_by_name((char *) s, method_len, (const LIBSSH2_COMMON_METHOD **) @@ -3640,8 +3856,9 @@ static int kex_agree_mac(LIBSSH2_SESSION * session, } while(*macp && (*macp)->name) { - s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name, - strlen((*macp)->name)); + s = _libssh2_kex_agree_instr(mac, mac_len, + (unsigned char *) (*macp)->name, + strlen((*macp)->name)); if(s) { endpoint->mac = *macp; return 0; @@ -3672,7 +3889,7 @@ static int kex_agree_comp(LIBSSH2_SESSION *session, unsigned char *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if(kex_agree_instr(comp, comp_len, s, method_len)) { + if(_libssh2_kex_agree_instr(comp, comp_len, s, method_len)) { const LIBSSH2_COMP_METHOD *method = (const LIBSSH2_COMP_METHOD *) kex_get_method_by_name((char *) s, method_len, @@ -3694,8 +3911,9 @@ static int kex_agree_comp(LIBSSH2_SESSION *session, } while(*compp && (*compp)->name) { - s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name, - strlen((*compp)->name)); + s = _libssh2_kex_agree_instr(comp, comp_len, + (unsigned char *) (*compp)->name, + strlen((*compp)->name)); if(s) { endpoint->comp = *compp; return 0; @@ -3843,6 +4061,10 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, session->state |= LIBSSH2_STATE_EXCHANGING_KEYS; if(reexchange) { + if(session->kex && session->kex->cleanup) { + session->kex->cleanup(session, &key_state->key_state_low); + } + session->kex = NULL; if(session->hostkey && session->hostkey->dtor) { @@ -3876,6 +4098,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, session->local.kexinit = key_state->oldlocal; session->local.kexinit_len = key_state->oldlocal_len; key_state->state = libssh2_NB_state_idle; + session->state &= ~LIBSSH2_STATE_INITIAL_KEX; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; return -1; @@ -3901,6 +4124,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, session->local.kexinit = key_state->oldlocal; session->local.kexinit_len = key_state->oldlocal_len; key_state->state = libssh2_NB_state_idle; + session->state &= ~LIBSSH2_STATE_INITIAL_KEX; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; return -1; @@ -3911,9 +4135,10 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, } session->remote.kexinit = key_state->data; session->remote.kexinit_len = key_state->data_len; + key_state->data = NULL; - if(kex_agree_methods(session, key_state->data, - key_state->data_len)) + if(kex_agree_methods(session, session->remote.kexinit, + session->remote.kexinit_len)) rc = LIBSSH2_ERROR_KEX_FAILURE; key_state->state = libssh2_NB_state_sent2; @@ -3949,6 +4174,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, session->remote.kexinit = NULL; } + session->state &= ~LIBSSH2_STATE_INITIAL_KEX; session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; @@ -3967,13 +4193,26 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type, const char *prefs) { char **prefvar, *s, *newprefs; + char *tmpprefs = NULL; size_t prefs_len = strlen(prefs); const LIBSSH2_COMMON_METHOD **mlist; + const char *kex_extensions = "ext-info-c,kex-strict-c-v00@openssh.com,"; + size_t kex_extensions_len = strlen(kex_extensions); switch(method_type) { case LIBSSH2_METHOD_KEX: prefvar = &session->kex_prefs; mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_kex_methods; + tmpprefs = LIBSSH2_ALLOC(session, kex_extensions_len + prefs_len + 1); + if(!tmpprefs) { + return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Error allocated space for kex method" + " preferences"); + } + memcpy(tmpprefs, kex_extensions, kex_extensions_len); + memcpy(tmpprefs + kex_extensions_len, prefs, prefs_len + 1); + prefs = tmpprefs; + prefs_len = strlen(prefs); break; case LIBSSH2_METHOD_HOSTKEY: @@ -4033,6 +4272,9 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type, s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1); if(!newprefs) { + if(tmpprefs) { + LIBSSH2_FREE(session, tmpprefs); + } return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocated space for method preferences"); } @@ -4061,6 +4303,10 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type, } } + if(tmpprefs) { + LIBSSH2_FREE(session, tmpprefs); + } + if(!*newprefs) { LIBSSH2_FREE(session, newprefs); return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, @@ -4165,7 +4411,7 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Memory allocation failed"); } - /* Past this point *algs must be deallocated in case of an error!! */ + /* Past this point *algs must be deallocated in case of an error! */ /* copy non-NULL pointers only */ for(i = 0, j = 0; mlist[i] && j < ialg; i++) { diff --git a/libssh2/src/knownhost.c b/libssh2/src/knownhost.c index c22311809..79500ec55 100644 --- a/libssh2/src/knownhost.c +++ b/libssh2/src/knownhost.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2019 by Daniel Stenberg + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -419,19 +421,23 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, */ unsigned char hash[SHA_DIGEST_LENGTH]; libssh2_hmac_ctx ctx; - libssh2_hmac_ctx_init(ctx); + if(!_libssh2_hmac_ctx_init(&ctx)) + break; if(SHA_DIGEST_LENGTH != node->name_len) { /* the name hash length must be the sha1 size or we can't match it */ break; } - libssh2_hmac_sha1_init(&ctx, (unsigned char *)node->salt, - node->salt_len); - libssh2_hmac_update(ctx, (unsigned char *)host, - strlen(host)); - libssh2_hmac_final(ctx, hash); - libssh2_hmac_cleanup(&ctx); + if(!_libssh2_hmac_sha1_init(&ctx, + node->salt, node->salt_len)) + break; + if(!_libssh2_hmac_update(&ctx, host, strlen(host)) || + !_libssh2_hmac_final(&ctx, hash)) { + _libssh2_hmac_cleanup(&ctx); + break; + } + _libssh2_hmac_cleanup(&ctx); if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH)) /* this is a node we're interested in */ @@ -773,18 +779,20 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts, } key_type_len = key - key_type_name; - if(!strncmp(key_type_name, "ssh-dss", key_type_len)) - key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS; - else if(!strncmp(key_type_name, "ssh-rsa", key_type_len)) - key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA; + if(!strncmp(key_type_name, "ssh-ed25519", key_type_len)) + key_type = LIBSSH2_KNOWNHOST_KEY_ED25519; else if(!strncmp(key_type_name, "ecdsa-sha2-nistp256", key_type_len)) key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_256; else if(!strncmp(key_type_name, "ecdsa-sha2-nistp384", key_type_len)) key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_384; else if(!strncmp(key_type_name, "ecdsa-sha2-nistp521", key_type_len)) key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_521; - else if(!strncmp(key_type_name, "ssh-ed25519", key_type_len)) - key_type = LIBSSH2_KNOWNHOST_KEY_ED25519; + else if(!strncmp(key_type_name, "ssh-rsa", key_type_len)) + key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA; +#if LIBSSH2_DSA + else if(!strncmp(key_type_name, "ssh-dss", key_type_len)) + key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS; +#endif else key_type = LIBSSH2_KNOWNHOST_KEY_UNKNOWN; @@ -1020,10 +1028,12 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, key_type_name = "ssh-rsa"; key_type_len = 7; break; +#if LIBSSH2_DSA case LIBSSH2_KNOWNHOST_KEY_SSHDSS: key_type_name = "ssh-dss"; key_type_len = 7; break; +#endif case LIBSSH2_KNOWNHOST_KEY_ECDSA_256: key_type_name = "ecdsa-sha2-nistp256"; key_type_len = 19; @@ -1047,7 +1057,7 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, break; } /* otherwise fallback to default and error */ - /* FALL-THROUGH */ + LIBSSH2_FALLTHROUGH(); default: return _libssh2_error(hosts->session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, diff --git a/libssh2/src/libgcrypt.c b/libssh2/src/libgcrypt.c index d1e177621..b92ec7c97 100644 --- a/libssh2/src/libgcrypt.c +++ b/libssh2/src/libgcrypt.c @@ -1,5 +1,5 @@ -/* Copyright (C) 2008, 2009, Simon Josefsson - * Copyright (C) 2006, 2007, The Written Word, Inc. +/* Copyright (C) Simon Josefsson + * Copyright (C) The Written Word, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,10 +34,111 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifdef LIBSSH2_CRYPTO_C /* Compile this via crypto.c */ +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx) +{ + *ctx = NULL; + return 1; +} + +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} +#endif + +#if LIBSSH2_HMAC_RIPEMD +int _libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} +#endif + +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} + +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} + +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + gcry_error_t err; + err = gcry_md_open(ctx, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + err = gcry_md_setkey(*ctx, key, keylen); + if(gcry_err_code(err) != GPG_ERR_NO_ERROR) + return 0; + return 1; +} + +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen) +{ + gcry_md_write(*ctx, data, datalen); + return 1; +} + +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *data) +{ + unsigned char *res = gcry_md_read(*ctx, 0); + + if(!res) + return 0; + + memcpy(data, res, gcry_md_get_algo_dlen(gcry_md_get_algo(*ctx))); + + return 1; +} + +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx) +{ + gcry_md_close(*ctx); +} + #if LIBSSH2_RSA int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, @@ -93,7 +194,9 @@ _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, gcry_sexp_t s_sig, s_hash; int rc = -1; - libssh2_sha1(m, m_len, hash); + if(libssh2_sha1(m, m_len, hash)) { + return -1; + } rc = gcry_sexp_build(&s_hash, NULL, "(data (flags pkcs1) (hash sha1 %b))", @@ -446,7 +549,7 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, const unsigned char *hash, - unsigned long hash_len, unsigned char *sig) + size_t hash_len, unsigned char *sig) { unsigned char zhash[SHA_DIGEST_LENGTH + 1]; gcry_sexp_t sig_sexp; @@ -463,7 +566,7 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, zhash[0] = 0; if(gcry_sexp_build(&data, NULL, "(data (value %b))", - hash_len + 1, zhash)) { + (int)(hash_len + 1), zhash)) { return -1; } @@ -542,7 +645,9 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, gcry_sexp_t s_sig, s_hash; int rc = -1; - libssh2_sha1(m, m_len, hash + 1); + if(libssh2_sha1(m, m_len, hash + 1)) { + return -1; + } hash[0] = 0; if(gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))", diff --git a/libssh2/src/libgcrypt.h b/libssh2/src/libgcrypt.h index 761f446c1..e8efc4be4 100644 --- a/libssh2/src/libgcrypt.h +++ b/libssh2/src/libgcrypt.h @@ -1,8 +1,8 @@ -#ifndef __LIBSSH2_LIBGCRYPT_H -#define __LIBSSH2_LIBGCRYPT_H +#ifndef LIBSSH2_LIBGCRYPT_H +#define LIBSSH2_LIBGCRYPT_H /* - * Copyright (C) 2008, 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007, The Written Word, Inc. + * Copyright (C) Simon Josefsson + * Copyright (C) The Written Word, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, @@ -37,6 +37,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #define LIBSSH2_CRYPTO_ENGINE libssh2_gcrypt @@ -64,7 +66,11 @@ #define LIBSSH2_ECDSA 0 #define LIBSSH2_ED25519 0 +#include "crypto_config.h" + +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #define MD5_DIGEST_LENGTH 16 +#endif #define SHA_DIGEST_LENGTH 20 #define SHA256_DIGEST_LENGTH 32 #define SHA384_DIGEST_LENGTH 48 @@ -78,86 +84,62 @@ #define libssh2_prepare_iovec(vec, len) /* Empty. */ #define libssh2_sha1_ctx gcry_md_hd_t - /* returns 0 in case of failure */ #define libssh2_sha1_init(ctx) \ (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_SHA1, 0)) #define libssh2_sha1_update(ctx, data, len) \ - gcry_md_write(ctx, (unsigned char *) data, len) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_sha1_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), SHA_DIGEST_LENGTH), gcry_md_close(ctx) + (memcpy(out, gcry_md_read(ctx, 0), SHA_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) #define libssh2_sha1(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_SHA1, out, message, len) + (gcry_md_hash_buffer(GCRY_MD_SHA1, out, message, len), 0) #define libssh2_sha256_ctx gcry_md_hd_t - #define libssh2_sha256_init(ctx) \ (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_SHA256, 0)) #define libssh2_sha256_update(ctx, data, len) \ - gcry_md_write(ctx, (unsigned char *) data, len) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_sha256_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), SHA256_DIGEST_LENGTH), gcry_md_close(ctx) + (memcpy(out, gcry_md_read(ctx, 0), SHA256_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) #define libssh2_sha256(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_SHA256, out, message, len) + (gcry_md_hash_buffer(GCRY_MD_SHA256, out, message, len), 0) #define libssh2_sha384_ctx gcry_md_hd_t - #define libssh2_sha384_init(ctx) \ (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_SHA384, 0)) #define libssh2_sha384_update(ctx, data, len) \ - gcry_md_write(ctx, (unsigned char *) data, len) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_sha384_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), SHA384_DIGEST_LENGTH), gcry_md_close(ctx) + (memcpy(out, gcry_md_read(ctx, 0), SHA384_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) #define libssh2_sha384(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_SHA384, out, message, len) + (gcry_md_hash_buffer(GCRY_MD_SHA384, out, message, len), 0) #define libssh2_sha512_ctx gcry_md_hd_t - #define libssh2_sha512_init(ctx) \ (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_SHA512, 0)) #define libssh2_sha512_update(ctx, data, len) \ - gcry_md_write(ctx, (unsigned char *) data, len) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_sha512_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), SHA512_DIGEST_LENGTH), gcry_md_close(ctx) + (memcpy(out, gcry_md_read(ctx, 0), SHA512_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) #define libssh2_sha512(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_SHA512, out, message, len) + (gcry_md_hash_buffer(GCRY_MD_SHA512, out, message, len), 0) +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #define libssh2_md5_ctx gcry_md_hd_t - -/* returns 0 in case of failure */ #define libssh2_md5_init(ctx) \ (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_MD5, 0)) - #define libssh2_md5_update(ctx, data, len) \ - gcry_md_write(ctx, (unsigned char *) data, len) + (gcry_md_write(ctx, (unsigned char *) data, len), 1) #define libssh2_md5_final(ctx, out) \ - memcpy(out, gcry_md_read(ctx, 0), MD5_DIGEST_LENGTH), gcry_md_close(ctx) -#define libssh2_md5(message, len, out) \ - gcry_md_hash_buffer(GCRY_MD_MD5, out, message, len) + (memcpy(out, gcry_md_read(ctx, 0), MD5_DIGEST_LENGTH), \ + gcry_md_close(ctx), 1) +#endif #define libssh2_hmac_ctx gcry_md_hd_t -#define libssh2_hmac_ctx_init(ctx) -#define libssh2_hmac_sha1_init(ctx, key, keylen) \ - gcry_md_open(ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey(*ctx, key, keylen) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - gcry_md_open(ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey(*ctx, key, keylen) -#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \ - gcry_md_open(ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey(*ctx, key, keylen) -#define libssh2_hmac_sha256_init(ctx, key, keylen) \ - gcry_md_open(ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey(*ctx, key, keylen) -#define libssh2_hmac_sha512_init(ctx, key, keylen) \ - gcry_md_open(ctx, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey(*ctx, key, keylen) -#define libssh2_hmac_update(ctx, data, datalen) \ - gcry_md_write(ctx, (unsigned char *) data, datalen) -#define libssh2_hmac_final(ctx, data) \ - memcpy(data, gcry_md_read(ctx, 0), \ - gcry_md_get_algo_dlen(gcry_md_get_algo(ctx))) -#define libssh2_hmac_cleanup(ctx) gcry_md_close(*ctx) #define libssh2_crypto_init() gcry_control(GCRYCTL_DISABLE_SECMEM) #define libssh2_crypto_exit() @@ -202,6 +184,8 @@ _libssh2_gcry_ciphermode(GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC) #define _libssh2_cipher_3des \ _libssh2_gcry_ciphermode(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC) +#define _libssh2_cipher_chacha20 \ + _libssh2_gcry_ciphermode(GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_STREAM) #define _libssh2_cipher_dtor(ctx) gcry_cipher_close(*(ctx)) @@ -248,4 +232,4 @@ extern int _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, _libssh2_bn *f, _libssh2_bn *p); extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx); -#endif /* __LIBSSH2_LIBGCRYPT_H */ +#endif /* LIBSSH2_LIBGCRYPT_H */ diff --git a/libssh2/src/libssh2.rc b/libssh2/src/libssh2.rc index c154951d9..3021d8e69 100644 --- a/libssh2/src/libssh2.rc +++ b/libssh2/src/libssh2.rc @@ -1,5 +1,8 @@ /*************************************************************************** -* libssh2 Windows resource file * +* libssh2 Windows resource file +* Copyright (C) The libssh2 project and its contributors. +* +* SPDX-License-Identifier: BSD-3-Clause ***************************************************************************/ #include #include "libssh2.h" @@ -26,7 +29,7 @@ BEGIN BEGIN BLOCK "040904b0" /* 0x0409: en-US, 1200/0x04b0: UTF-16LE */ BEGIN - VALUE "CompanyName", "The libssh2 library, https://www.libssh2.org/\0" + VALUE "CompanyName", "The libssh2 library, https://libssh2.org/\0" VALUE "FileDescription", "libssh2 Shared Library\0" VALUE "FileVersion", LIBSSH2_VERSION "\0" VALUE "InternalName", "libssh2\0" @@ -34,7 +37,7 @@ BEGIN VALUE "ProductName", "The libssh2 library\0" VALUE "ProductVersion", LIBSSH2_VERSION "\0" VALUE "LegalCopyright", "Copyright (C) " LIBSSH2_COPYRIGHT "\0" - VALUE "License", "https://www.libssh2.org/license.html\0" + VALUE "License", "https://libssh2.org/license.html\0" END END diff --git a/libssh2/src/libssh2_config.h.in b/libssh2/src/libssh2_config.h.in index 990c2cf95..e7dbf0ac2 100644 --- a/libssh2/src/libssh2_config.h.in +++ b/libssh2/src/libssh2_config.h.in @@ -21,10 +21,10 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H -/* Define to 1 if you have the `explicit_bzero' function. */ +/* Define to 1 if you have the 'explicit_bzero' function. */ #undef HAVE_EXPLICIT_BZERO -/* Define to 1 if you have the `explicit_memset' function. */ +/* Define to 1 if you have the 'explicit_memset' function. */ #undef HAVE_EXPLICIT_MEMSET /* Define to 1 if you have the header file. */ @@ -33,7 +33,7 @@ /* use FIONBIO for non-blocking sockets */ #undef HAVE_FIONBIO -/* Define to 1 if you have the `gettimeofday' function. */ +/* Define to 1 if you have the 'gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ @@ -60,7 +60,7 @@ /* Define if you have the z library. */ #undef HAVE_LIBZ -/* Define to 1 if you have the `memset_s' function. */ +/* Define to 1 if you have the 'memset_s' function. */ #undef HAVE_MEMSET_S /* Define to 1 if you have the header file. */ @@ -69,13 +69,13 @@ /* use O_NONBLOCK for non-blocking sockets */ #undef HAVE_O_NONBLOCK -/* Define to 1 if you have the `poll' function. */ +/* Define to 1 if you have the 'poll' function. */ #undef HAVE_POLL /* Define to 1 if you have the select function. */ #undef HAVE_SELECT -/* Define to 1 if you have the `snprintf' function. */ +/* Define to 1 if you have the 'snprintf' function. */ #undef HAVE_SNPRINTF /* use SO_NONBLOCK for non-blocking sockets */ @@ -96,15 +96,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H -/* Define to 1 if you have the `strtoll' function. */ +/* Define to 1 if you have the 'strtoll' function. */ #undef HAVE_STRTOLL /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PARAM_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H @@ -135,6 +132,9 @@ /* to make a symbol visible */ #undef LIBSSH2_API +/* Enable WinCNG ECDSA support */ +#undef LIBSSH2_ECDSA_WINCNG + /* Compile in zlib support */ #undef LIBSSH2_HAVE_ZLIB @@ -191,7 +191,7 @@ STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION -/* Define to 1 if all of the C90 standard headers exist (not just the ones +/* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS @@ -214,17 +214,23 @@ /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS -/* Define for large files, on AIX-style hosts. */ +/* Define to 1 on platforms where this makes off_t a 64-bit type. */ #undef _LARGE_FILES -/* Define to empty if `const' does not conform to ANSI C. */ +/* Number of bits in time_t, on hosts where this is settable. */ +#undef _TIME_BITS + +/* Define to 1 on platforms where this makes time_t a 64-bit type. */ +#undef __MINGW_USE_VC2005_COMPAT + +/* Define to empty if 'const' does not conform to ANSI C. */ #undef const -/* Define to `__inline__' or `__inline' if that's what the C compiler +/* Define to '__inline__' or '__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif -/* Define to `unsigned int' if does not define. */ +/* Define as 'unsigned int' if doesn't define. */ #undef size_t diff --git a/libssh2/src/libssh2_config_cmake.h.in b/libssh2/src/libssh2_config_cmake.h.in index 5de5c58c3..3f0bc1388 100644 --- a/libssh2/src/libssh2_config_cmake.h.in +++ b/libssh2/src/libssh2_config_cmake.h.in @@ -1,5 +1,6 @@ -/* Copyright (c) 2014 Alexander Lamaison - * Copyright (c) 1999-2011 Douglas Gilbert. All rights reserved. +/* Copyright (C) Alexander Lamaison + * Copyright (C) Douglas Gilbert + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -33,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ /* Headers */ @@ -46,7 +49,6 @@ #cmakedefine HAVE_SYS_UN_H /* for example and tests */ -#cmakedefine HAVE_SYS_PARAM_H #cmakedefine HAVE_ARPA_INET_H #cmakedefine HAVE_NETINET_IN_H diff --git a/libssh2/src/libssh2_priv.h b/libssh2/src/libssh2_priv.h index 82c3afe25..9b8866dcc 100644 --- a/libssh2/src/libssh2_priv.h +++ b/libssh2/src/libssh2_priv.h @@ -1,8 +1,8 @@ -#ifndef __LIBSSH2_PRIV_H -#define __LIBSSH2_PRIV_H -/* Copyright (c) 2004-2008, 2010, Sara Golemon - * Copyright (c) 2009-2014 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson +#ifndef LIBSSH2_PRIV_H +#define LIBSSH2_PRIV_H +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -37,9 +37,18 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ -/* Header used by 'src' */ +/* Header used by 'src' and 'tests' */ + +/* FIXME: Disable warnings for 'src' */ +#if !defined(LIBSSH2_TESTS) && !defined(LIBSSH2_WARN_SIGN_CONVERSION) +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif +#endif #define LIBSSH2_LIBRARY @@ -84,7 +93,7 @@ #include "libssh2_sftp.h" #include "misc.h" -#ifdef WIN32 +#ifdef _WIN32 /* Detect Windows App environment which has a restricted access to the Win32 APIs. */ # if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \ @@ -104,12 +113,32 @@ #define TRUE 1 #endif +#ifndef UINT32_MAX +#define UINT32_MAX 0xffffffffU +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(LIBSSH2_NO_FMT_CHECKS) +#ifdef __MINGW_PRINTF_FORMAT +#define LIBSSH2_PRINTF(fmt, arg) \ + __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, arg))) +#elif !defined(__MINGW32__) +#define LIBSSH2_PRINTF(fmt, arg) \ + __attribute__((format(printf, fmt, arg))) +#endif +#endif +#ifndef LIBSSH2_PRINTF +#define LIBSSH2_PRINTF(fmt, arg) +#endif + /* Use local implementation when not available */ #if !defined(HAVE_SNPRINTF) #undef snprintf #define snprintf _libssh2_snprintf #define LIBSSH2_SNPRINTF -int _libssh2_snprintf(char *cp, size_t cp_max_len, const char *fmt, ...); +int _libssh2_snprintf(char *cp, size_t cp_max_len, const char *fmt, ...) + LIBSSH2_PRINTF(3, 4); #endif #if !defined(HAVE_GETTIMEOFDAY) @@ -122,6 +151,15 @@ int _libssh2_gettimeofday(struct timeval *tp, void *tzp); #include #endif +#if !defined(LIBSSH2_FALLTHROUGH) +#if (defined(__GNUC__) && __GNUC__ >= 7) || \ + (defined(__clang__) && __clang_major__ >= 10) +# define LIBSSH2_FALLTHROUGH() __attribute__((fallthrough)) +#else +# define LIBSSH2_FALLTHROUGH() do {} while (0) +#endif +#endif + /* "inline" keyword is valid only with C++ engine! */ #ifdef __GNUC__ #undef inline @@ -132,7 +170,7 @@ int _libssh2_gettimeofday(struct timeval *tp, void *tzp); #endif /* 3DS doesn't seem to have iovec */ -#if defined(WIN32) || defined(_3DS) +#if defined(_WIN32) || defined(_3DS) struct iovec { size_t iov_len; @@ -163,6 +201,9 @@ struct iovec { #define LIBSSH2_MAX(x, y) ((x) > (y) ? (x) : (y)) #define LIBSSH2_MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */ +#define MAX_MACSIZE 64 /* MUST fit biggest MAC length we support */ + /* RFC4253 section 6.1 Maximum Packet Length says: * * "All implementations MUST be able to process packets with @@ -377,12 +418,6 @@ typedef struct packet_authagent_state_t LIBSSH2_CHANNEL *channel; } packet_authagent_state_t; -typedef enum -{ - libssh2_requires_size_decryption = (1 << 0), - libssh2_requires_size_field_in_packet = (1 << 1) -} libssh2_crypt_flags; - struct _LIBSSH2_PACKET { struct list_node node; /* linked list header */ @@ -413,7 +448,7 @@ struct _LIBSSH2_CHANNEL struct list_node node; unsigned char *channel_type; - unsigned channel_type_len; + size_t channel_type_len; /* channel's program exit status */ int exit_status; @@ -466,7 +501,7 @@ struct _LIBSSH2_CHANNEL size_t flush_refund_bytes; size_t flush_flush_bytes; - /* State variables used in libssh2_channel_receive_window_adjust() */ + /* State variables used in libssh2_channel_receive_window_adjust2() */ libssh2_nonblocking_states adjust_state; unsigned char adjust_adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */ @@ -699,6 +734,9 @@ struct _LIBSSH2_SESSION /* key signing algorithm preferences -- NULL yields server order */ char *sign_algo_prefs; + /* Whether to use the OpenSSH Strict KEX extension */ + int kex_strict; + /* (remote as source of data -- packet_read ) */ libssh2_endpoint_data remote; @@ -721,7 +759,8 @@ struct _LIBSSH2_SESSION int socket_state; int socket_block_directions; int socket_prev_blockstate; /* stores the state of the socket blockiness - when libssh2_session_startup() is called */ + when libssh2_session_handshake() + is called */ /* Error tracking */ const char *err_msg; @@ -739,7 +778,7 @@ struct _LIBSSH2_SESSION /* State variables used in libssh2_banner_send() */ libssh2_nonblocking_states banner_TxRx_state; - char banner_TxRx_banner[256]; + char banner_TxRx_banner[8192]; ssize_t banner_TxRx_total_send; /* State variables used in libssh2_kexinit() */ @@ -747,7 +786,7 @@ struct _LIBSSH2_SESSION unsigned char *kexinit_data; size_t kexinit_data_len; - /* State variables used in libssh2_session_startup() */ + /* State variables used in libssh2_session_handshake() */ libssh2_nonblocking_states startup_state; unsigned char *startup_data; size_t startup_data_len; @@ -870,6 +909,7 @@ struct _LIBSSH2_SESSION int fullpacket_macstate; size_t fullpacket_payload_len; int fullpacket_packet_type; + uint32_t fullpacket_required_type; /* State variables used in libssh2_sftp_init() */ libssh2_nonblocking_states sftpInit_state; @@ -880,7 +920,7 @@ struct _LIBSSH2_SESSION size_t sftpInit_sent; /* number of bytes from the buffer that have been sent */ - /* State variables used in libssh2_scp_recv() / libssh_scp_recv2() */ + /* State variables used in libssh2_scp_recv2() */ libssh2_nonblocking_states scpRecv_state; unsigned char *scpRecv_command; size_t scpRecv_command_len; @@ -910,10 +950,11 @@ struct _LIBSSH2_SESSION }; /* session.state bits */ -#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001 -#define LIBSSH2_STATE_NEWKEYS 0x00000002 -#define LIBSSH2_STATE_AUTHENTICATED 0x00000004 -#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008 +#define LIBSSH2_STATE_INITIAL_KEX 0x00000001 +#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000002 +#define LIBSSH2_STATE_NEWKEYS 0x00000004 +#define LIBSSH2_STATE_AUTHENTICATED 0x00000008 +#define LIBSSH2_STATE_KEX_ACTIVE 0x00000010 /* session.flag helpers */ #ifdef MSG_NOSIGNAL @@ -941,13 +982,16 @@ struct _LIBSSH2_KEX_METHOD int (*exchange_keys) (LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state); + void (*cleanup) (LIBSSH2_SESSION * session, + key_exchange_state_low_t * key_state); + long flags; }; struct _LIBSSH2_HOSTKEY_METHOD { const char *name; - unsigned long hash_len; + size_t hash_len; int (*init) (LIBSSH2_SESSION * session, const unsigned char *hostkey_data, size_t hostkey_data_len, void **abstract); @@ -981,14 +1025,21 @@ struct _LIBSSH2_CRYPT_METHOD int iv_len; int secret_len; + /* length of the authentication tag */ + int auth_len; + long flags; int (*init) (LIBSSH2_SESSION * session, const LIBSSH2_CRYPT_METHOD * method, unsigned char *iv, int *free_iv, unsigned char *secret, int *free_secret, int encrypt, void **abstract); - int (*crypt) (LIBSSH2_SESSION * session, unsigned char *block, - size_t blocksize, void **abstract, int firstlast); + int (*get_len) (LIBSSH2_SESSION * session, unsigned int seqno, + unsigned char *data, size_t data_size, unsigned int *len, + void **abstract); + int (*crypt) (LIBSSH2_SESSION * session, unsigned int seqno, + unsigned char *block, size_t blocksize, void **abstract, + int firstlast); int (*dtor) (LIBSSH2_SESSION * session, void **abstract); _libssh2_cipher_type(algo); @@ -1000,6 +1051,8 @@ struct _LIBSSH2_CRYPT_METHOD #define LIBSSH2_CRYPT_FLAG_INTEGRATED_MAC 1 /* Crypto method does not encrypt the packet length */ #define LIBSSH2_CRYPT_FLAG_PKTLEN_AAD 2 +/* Crypto method must encrypt and decrypt entire messages */ +#define LIBSSH2_CRYPT_FLAG_REQUIRES_FULL_PACKET 4 /* Convenience macros for accessing crypt flags */ /* Local crypto flags */ @@ -1043,7 +1096,7 @@ struct _LIBSSH2_COMP_METHOD #ifdef LIBSSH2DEBUG void _libssh2_debug_low(LIBSSH2_SESSION * session, int context, const char *format, - ...); + ...) LIBSSH2_PRINTF(3, 4); #define _libssh2_debug(x) _libssh2_debug_low x #else #define _libssh2_debug(x) do {} while(0) @@ -1144,6 +1197,11 @@ ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer, int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, key_exchange_state_t * state); +unsigned char *_libssh2_kex_agree_instr(unsigned char *haystack, + size_t haystack_len, + const unsigned char *needle, + size_t needle_len); + /* Let crypt.c/hostkey.c expose their method structs */ const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void); const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void); @@ -1193,6 +1251,8 @@ size_t plain_method(char *method, size_t method_len); /* define to output the libssh2_int64_t type in a *printf() */ #if defined(__BORLANDC__) || defined(_MSC_VER) #define LIBSSH2_INT64_T_FORMAT "I64d" +#elif defined(__MINGW32__) +#define LIBSSH2_INT64_T_FORMAT PRId64 #else #define LIBSSH2_INT64_T_FORMAT "lld" #endif @@ -1200,12 +1260,12 @@ size_t plain_method(char *method, size_t method_len); /* In Windows the default file mode is text but an application can override it. Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 */ -#if defined(WIN32) || defined(MSDOS) +#if defined(_WIN32) || defined(MSDOS) #define FOPEN_READTEXT "rt" #define FOPEN_WRITETEXT "wt" #define FOPEN_APPENDTEXT "at" #elif defined(__CYGWIN__) -/* Cygwin has specific behavior we need to address when WIN32 is not defined. +/* Cygwin has specific behavior we need to address when _WIN32 is not defined. https://cygwin.com/cygwin-ug-net/using-textbinary.html For write we want our output to have line endings of LF and be compatible with other Cygwin utilities. For read we want to handle input that may have @@ -1220,4 +1280,4 @@ size_t plain_method(char *method, size_t method_len); #define FOPEN_APPENDTEXT "a" #endif -#endif /* __LIBSSH2_PRIV_H */ +#endif /* LIBSSH2_PRIV_H */ diff --git a/libssh2/src/libssh2_setup.h b/libssh2/src/libssh2_setup.h index 87fed1c58..0f17a1885 100644 --- a/libssh2/src/libssh2_setup.h +++ b/libssh2/src/libssh2_setup.h @@ -1,4 +1,7 @@ -/* Copyright (c) 2023 Viktor Szakats */ +/* Copyright (C) Viktor Szakats + * + * SPDX-License-Identifier: BSD-3-Clause + */ #ifndef LIBSSH2_SETUP_H #define LIBSSH2_SETUP_H @@ -6,10 +9,6 @@ /* Header for platform/compiler-specific initialization. Used by 'src', 'example', 'tests' */ -#if defined(_WIN32) && !defined(WIN32) -#define WIN32 -#endif - /* Define mingw-w64 version macros, eg __MINGW{32,64}_{MINOR,MAJOR}_VERSION */ #ifdef __MINGW32__ #include <_mingw.h> @@ -23,7 +22,7 @@ /* Hand-crafted configuration for platforms which lack config tool. Keep this synced with root CMakeLists.txt */ -#elif defined(WIN32) +#elif defined(_WIN32) #define HAVE_SELECT #define HAVE_SNPRINTF @@ -32,7 +31,6 @@ # define HAVE_UNISTD_H # define HAVE_INTTYPES_H # define HAVE_SYS_TIME_H -# define HAVE_SYS_PARAM_H # define HAVE_GETTIMEOFDAY # define HAVE_STRTOLL #elif defined(_MSC_VER) @@ -51,7 +49,7 @@ /* Below applies to both auto-detected and hand-crafted configs */ -#ifdef WIN32 +#ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN @@ -100,6 +98,6 @@ # endif #endif -#endif /* WIN32 */ +#endif /* _WIN32 */ #endif /* LIBSSH2_SETUP_H */ diff --git a/libssh2/src/mac.c b/libssh2/src/mac.c index 01c5faa26..00d3c21fb 100644 --- a/libssh2/src/mac.c +++ b/libssh2/src/mac.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2004-2007, Sara Golemon +/* Copyright (C) Sara Golemon * All rights reserved. * * Redistribution and use in source and binary forms, @@ -33,6 +33,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -122,23 +124,27 @@ mac_method_hmac_sha2_512_hash(LIBSSH2_SESSION * session, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (void)session; _libssh2_htonu32(seqno_buf, seqno); - libssh2_hmac_ctx_init(ctx); - libssh2_hmac_sha512_init(&ctx, *abstract, 64); - libssh2_hmac_update(ctx, seqno_buf, 4); - libssh2_hmac_update(ctx, packet, packet_len); - if(addtl && addtl_len) { - libssh2_hmac_update(ctx, addtl, addtl_len); - } - libssh2_hmac_final(ctx, buf); - libssh2_hmac_cleanup(&ctx); + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_sha512_init(&ctx, *abstract, 64) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); - return 0; + return !res; } + + static const LIBSSH2_MAC_METHOD mac_method_hmac_sha2_512 = { "hmac-sha2-512", 64, @@ -177,21 +183,23 @@ mac_method_hmac_sha2_256_hash(LIBSSH2_SESSION * session, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (void)session; _libssh2_htonu32(seqno_buf, seqno); - libssh2_hmac_ctx_init(ctx); - libssh2_hmac_sha256_init(&ctx, *abstract, 32); - libssh2_hmac_update(ctx, seqno_buf, 4); - libssh2_hmac_update(ctx, packet, packet_len); - if(addtl && addtl_len) { - libssh2_hmac_update(ctx, addtl, addtl_len); - } - libssh2_hmac_final(ctx, buf); - libssh2_hmac_cleanup(&ctx); + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_sha256_init(&ctx, *abstract, 32) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); - return 0; + return !res; } @@ -234,21 +242,23 @@ mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (void)session; _libssh2_htonu32(seqno_buf, seqno); - libssh2_hmac_ctx_init(ctx); - libssh2_hmac_sha1_init(&ctx, *abstract, 20); - libssh2_hmac_update(ctx, seqno_buf, 4); - libssh2_hmac_update(ctx, packet, packet_len); - if(addtl && addtl_len) { - libssh2_hmac_update(ctx, addtl, addtl_len); - } - libssh2_hmac_final(ctx, buf); - libssh2_hmac_cleanup(&ctx); + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_sha1_init(&ctx, *abstract, 20) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); - return 0; + return !res; } @@ -286,10 +296,11 @@ mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session, { unsigned char temp[SHA_DIGEST_LENGTH]; - mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len, - addtl, addtl_len, abstract); - memcpy(buf, (char *) temp, 96 / 8); + if(mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len, + addtl, addtl_len, abstract)) + return 1; + memcpy(buf, (char *) temp, 96 / 8); return 0; } @@ -319,21 +330,23 @@ mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (void)session; _libssh2_htonu32(seqno_buf, seqno); - libssh2_hmac_ctx_init(ctx); - libssh2_hmac_md5_init(&ctx, *abstract, 16); - libssh2_hmac_update(ctx, seqno_buf, 4); - libssh2_hmac_update(ctx, packet, packet_len); - if(addtl && addtl_len) { - libssh2_hmac_update(ctx, addtl, addtl_len); - } - libssh2_hmac_final(ctx, buf); - libssh2_hmac_cleanup(&ctx); + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_md5_init(&ctx, *abstract, 16) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); - return 0; + return !res; } @@ -360,8 +373,11 @@ mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session, size_t addtl_len, void **abstract) { unsigned char temp[MD5_DIGEST_LENGTH]; - mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len, - addtl, addtl_len, abstract); + + if(mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len, + addtl, addtl_len, abstract)) + return 1; + memcpy(buf, (char *) temp, 96 / 8); return 0; } @@ -394,21 +410,23 @@ mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session, { libssh2_hmac_ctx ctx; unsigned char seqno_buf[4]; + int res; (void)session; _libssh2_htonu32(seqno_buf, seqno); - libssh2_hmac_ctx_init(ctx); - libssh2_hmac_ripemd160_init(&ctx, *abstract, 20); - libssh2_hmac_update(ctx, seqno_buf, 4); - libssh2_hmac_update(ctx, packet, packet_len); - if(addtl && addtl_len) { - libssh2_hmac_update(ctx, addtl, addtl_len); - } - libssh2_hmac_final(ctx, buf); - libssh2_hmac_cleanup(&ctx); + if(!_libssh2_hmac_ctx_init(&ctx)) + return 1; + res = _libssh2_hmac_ripemd160_init(&ctx, *abstract, 20) && + _libssh2_hmac_update(&ctx, seqno_buf, 4) && + _libssh2_hmac_update(&ctx, packet, packet_len); + if(res && addtl && addtl_len) + res = _libssh2_hmac_update(&ctx, addtl, addtl_len); + if(res) + res = _libssh2_hmac_final(&ctx, buf); + _libssh2_hmac_cleanup(&ctx); - return 0; + return !res; } @@ -467,6 +485,44 @@ _libssh2_mac_methods(void) } #if LIBSSH2_AES_GCM +static int +mac_method_none_init(LIBSSH2_SESSION * session, unsigned char *key, + int *free_key, void **abstract) +{ + (void)session; + (void)key; + (void)free_key; + (void)abstract; + return 0; +} + +static int +mac_method_hmac_none_hash(LIBSSH2_SESSION * session, + unsigned char *buf, uint32_t seqno, + const unsigned char *packet, + size_t packet_len, + const unsigned char *addtl, + size_t addtl_len, void **abstract) +{ + (void)session; + (void)buf; + (void)seqno; + (void)packet; + (void)packet_len; + (void)addtl; + (void)addtl_len; + (void)abstract; + return 0; +} + +static int +mac_method_none_dtor(LIBSSH2_SESSION * session, void **abstract) +{ + (void)session; + (void)abstract; + return 0; +} + /* Stub for aes256-gcm@openssh.com crypto type, which has an integrated HMAC method. This must not be added to mac_methods[] since it cannot be negotiated separately. */ @@ -474,9 +530,9 @@ static const LIBSSH2_MAC_METHOD mac_method_hmac_aesgcm = { "INTEGRATED-AES-GCM", /* made up name for display only */ 16, 16, - NULL, - NULL, - NULL, + mac_method_none_init, + mac_method_hmac_none_hash, + mac_method_none_dtor, 0 }; #endif /* LIBSSH2_AES_GCM */ diff --git a/libssh2/src/mac.h b/libssh2/src/mac.h index 82379b91c..8e5b8c280 100644 --- a/libssh2/src/mac.h +++ b/libssh2/src/mac.h @@ -1,6 +1,7 @@ -#ifndef __LIBSSH2_MAC_H -#define __LIBSSH2_MAC_H -/* Copyright (C) 2009-2010 by Daniel Stenberg +#ifndef LIBSSH2_MAC_H +#define LIBSSH2_MAC_H +/* Copyright (C) Daniel Stenberg + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -35,6 +36,7 @@ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -67,4 +69,4 @@ const LIBSSH2_MAC_METHOD **_libssh2_mac_methods(void); const LIBSSH2_MAC_METHOD *_libssh2_mac_override( const LIBSSH2_CRYPT_METHOD *crypt); -#endif /* __LIBSSH2_MAC_H */ +#endif /* LIBSSH2_MAC_H */ diff --git a/libssh2/src/mbedtls.c b/libssh2/src/mbedtls.c index e387cdb19..a66e36c5a 100644 --- a/libssh2/src/mbedtls.c +++ b/libssh2/src/mbedtls.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, Art +/* Copyright (C) Art * All rights reserved. * * Redistribution and use in source and binary forms, @@ -33,6 +33,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifdef LIBSSH2_CRYPTO_C /* Compile this via crypto.c */ @@ -186,7 +188,7 @@ _libssh2_mbedtls_cipher_dtor(_libssh2_cipher_ctx *ctx) int _libssh2_mbedtls_hash_init(mbedtls_md_context_t *ctx, mbedtls_md_type_t mdtype, - const unsigned char *key, unsigned long keylen) + const unsigned char *key, size_t keylen) { const mbedtls_md_info_t *md_info; int ret, hmac; @@ -217,11 +219,11 @@ _libssh2_mbedtls_hash_final(mbedtls_md_context_t *ctx, unsigned char *hash) ret = mbedtls_md_finish(ctx, hash); mbedtls_md_free(ctx); - return ret == 0 ? 0 : -1; + return ret == 0 ? 1 : 0; } int -_libssh2_mbedtls_hash(const unsigned char *data, unsigned long datalen, +_libssh2_mbedtls_hash(const unsigned char *data, size_t datalen, mbedtls_md_type_t mdtype, unsigned char *hash) { const mbedtls_md_info_t *md_info; @@ -236,6 +238,66 @@ _libssh2_mbedtls_hash(const unsigned char *data, unsigned long datalen, return ret == 0 ? 0 : -1; } +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + return 1; +} + +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return _libssh2_mbedtls_hash_init(ctx, MBEDTLS_MD_MD5, key, keylen); +} +#endif + +#if LIBSSH2_HMAC_RIPEMD +int _libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return _libssh2_mbedtls_hash_init(ctx, MBEDTLS_MD_RIPEMD160, key, keylen); +} +#endif + +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return _libssh2_mbedtls_hash_init(ctx, MBEDTLS_MD_SHA1, key, keylen); +} + +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return _libssh2_mbedtls_hash_init(ctx, MBEDTLS_MD_SHA256, key, keylen); +} + +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return _libssh2_mbedtls_hash_init(ctx, MBEDTLS_MD_SHA512, key, keylen); +} + +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen) +{ + int ret = mbedtls_md_hmac_update(ctx, data, datalen); + + return ret == 0 ? 1 : 0; +} + +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *data) +{ + int ret = mbedtls_md_hmac_finish(ctx, data); + + return ret == 0 ? 1 : 0; +} + +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx) +{ + mbedtls_md_free(ctx); +} + /*******************************************************************/ /* * mbedTLS backend: BigNumber functions @@ -497,8 +559,9 @@ int _libssh2_mbedtls_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, size_t hash_len, const unsigned char *sig, - unsigned long sig_len, - const unsigned char *m, unsigned long m_len) + size_t sig_len, + const unsigned char *m, + size_t m_len) { int ret; int md_type; @@ -548,8 +611,9 @@ _libssh2_mbedtls_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, int _libssh2_mbedtls_rsa_sha1_verify(libssh2_rsa_ctx * rsactx, const unsigned char *sig, - unsigned long sig_len, - const unsigned char *m, unsigned long m_len) + size_t sig_len, + const unsigned char *m, + size_t m_len) { return _libssh2_mbedtls_rsa_sha2_verify(rsactx, SHA_DIGEST_LENGTH, sig, sig_len, m, m_len); @@ -1047,7 +1111,7 @@ cleanup: } \ } while(0) -/* _libssh2_ecdsa_sign +/* _libssh2_ecdsa_verify * * Verifies the ECDSA signature of a hashed message * @@ -1212,6 +1276,11 @@ cleanup: return *ctx ? 0 : -1; } +/* Force-expose internal mbedTLS function */ +#if MBEDTLS_VERSION_NUMBER >= 0x03060000 +int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); +#endif + /* _libssh2_ecdsa_new_private * * Creates a new private key given a file path and password @@ -1225,14 +1294,15 @@ _libssh2_mbedtls_ecdsa_new_private(libssh2_ecdsa_ctx **ctx, const unsigned char *pwd) { mbedtls_pk_context pkey; - unsigned char *data; - size_t data_len; - - if(mbedtls_pk_load_file(filename, &data, &data_len)) - goto cleanup; + unsigned char *data = NULL; + size_t data_len = 0; mbedtls_pk_init(&pkey); + /* FIXME: Reimplement this functionality via a public API. */ + if(mbedtls_pk_load_file(filename, &data, &data_len)) + goto cleanup; + if(_libssh2_mbedtls_parse_eckey(ctx, &pkey, session, data, data_len, pwd) == 0) goto cleanup; @@ -1329,7 +1399,7 @@ int _libssh2_mbedtls_ecdsa_sign(LIBSSH2_SESSION *session, libssh2_ecdsa_ctx *ctx, const unsigned char *hash, - unsigned long hash_len, + size_t hash_len, unsigned char **sign, size_t *sign_len) { @@ -1449,7 +1519,11 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, #if LIBSSH2_RSA_SHA2 if(key_method_len == 7 && memcmp(key_method, "ssh-rsa", key_method_len) == 0) { - return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; + return "rsa-sha2-512,rsa-sha2-256" +#if LIBSSH2_RSA_SHA1 + ",ssh-rsa" +#endif + ; } #endif diff --git a/libssh2/src/mbedtls.h b/libssh2/src/mbedtls.h index d9592f721..b1e6726eb 100644 --- a/libssh2/src/mbedtls.h +++ b/libssh2/src/mbedtls.h @@ -1,6 +1,6 @@ -#ifndef __LIBSSH2_MBEDTLS_H -#define __LIBSSH2_MBEDTLS_H -/* Copyright (c) 2016, Art +#ifndef LIBSSH2_MBEDTLS_H +#define LIBSSH2_MBEDTLS_H +/* Copyright (C) Art * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,10 +35,28 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #define LIBSSH2_CRYPTO_ENGINE libssh2_mbedtls +#ifdef __GNUC__ +#pragma GCC diagnostic push +/* mbedTLS (as of v3.5.1) has a `[-Werror=arith-conversion]` + warning in its public headers. */ +#if !defined(__clang__) && __GNUC__ >= 10 +#pragma GCC diagnostic ignored "-Warith-conversion" +#endif +#if defined(__clang__) +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif +/* mbedTLS (as of v3.5.1) has a duplicate function declaration + in its public headers. Disable the warning that detects it. */ +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + +#include #include #include #include @@ -55,6 +73,10 @@ #include #include +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + /* Define which features are supported. */ #define LIBSSH2_MD5 1 @@ -89,7 +111,11 @@ #endif #define LIBSSH2_ED25519 0 +#include "crypto_config.h" + +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #define MD5_DIGEST_LENGTH 16 +#endif #define SHA_DIGEST_LENGTH 20 #define SHA256_DIGEST_LENGTH 32 #define SHA384_DIGEST_LENGTH 48 @@ -121,27 +147,6 @@ #define libssh2_hmac_ctx mbedtls_md_context_t -#define libssh2_hmac_ctx_init(ctx) -#define libssh2_hmac_cleanup(pctx) \ - mbedtls_md_free(pctx) -#define libssh2_hmac_update(ctx, data, datalen) \ - mbedtls_md_hmac_update(&ctx, (const unsigned char *) data, datalen) -#define libssh2_hmac_final(ctx, hash) \ - mbedtls_md_hmac_finish(&ctx, hash) - -#define libssh2_hmac_sha1_init(pctx, key, keylen) \ - _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA1, key, keylen) -#define libssh2_hmac_md5_init(pctx, key, keylen) \ - _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_MD5, key, keylen) -#define libssh2_hmac_ripemd160_init(pctx, key, keylen) \ - _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_RIPEMD160, key, keylen) -#define libssh2_hmac_sha256_init(pctx, key, keylen) \ - _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA256, key, keylen) -#define libssh2_hmac_sha384_init(pctx, key, keylen) \ - _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA384, key, keylen) -#define libssh2_hmac_sha512_init(pctx, key, keylen) \ - _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA512, key, keylen) - /*******************************************************************/ /* @@ -153,7 +158,7 @@ #define libssh2_sha1_init(pctx) \ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA1, NULL, 0) #define libssh2_sha1_update(ctx, data, datalen) \ - mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) + (mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) == 0) #define libssh2_sha1_final(ctx, hash) \ _libssh2_mbedtls_hash_final(&ctx, hash) #define libssh2_sha1(data, datalen, hash) \ @@ -170,7 +175,7 @@ #define libssh2_sha256_init(pctx) \ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA256, NULL, 0) #define libssh2_sha256_update(ctx, data, datalen) \ - mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) + (mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) == 0) #define libssh2_sha256_final(ctx, hash) \ _libssh2_mbedtls_hash_final(&ctx, hash) #define libssh2_sha256(data, datalen, hash) \ @@ -187,7 +192,7 @@ #define libssh2_sha384_init(pctx) \ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA384, NULL, 0) #define libssh2_sha384_update(ctx, data, datalen) \ - mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) + (mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) == 0) #define libssh2_sha384_final(ctx, hash) \ _libssh2_mbedtls_hash_final(&ctx, hash) #define libssh2_sha384(data, datalen, hash) \ @@ -204,7 +209,7 @@ #define libssh2_sha512_init(pctx) \ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA512, NULL, 0) #define libssh2_sha512_update(ctx, data, datalen) \ - mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) + (mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) == 0) #define libssh2_sha512_final(ctx, hash) \ _libssh2_mbedtls_hash_final(&ctx, hash) #define libssh2_sha512(data, datalen, hash) \ @@ -216,17 +221,16 @@ * mbedTLS backend: MD5 functions */ +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #define libssh2_md5_ctx mbedtls_md_context_t #define libssh2_md5_init(pctx) \ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_MD5, NULL, 0) #define libssh2_md5_update(ctx, data, datalen) \ - mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) + (mbedtls_md_update(&ctx, (const unsigned char *) data, datalen) == 0) #define libssh2_md5_final(ctx, hash) \ _libssh2_mbedtls_hash_final(&ctx, hash) -#define libssh2_md5(data, datalen, hash) \ - _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_MD5, hash) - +#endif /*******************************************************************/ /* @@ -380,6 +384,7 @@ typedef enum { #define _libssh2_cipher_arcfour MBEDTLS_CIPHER_ARC4_128 #endif #define _libssh2_cipher_3des MBEDTLS_CIPHER_DES_EDE3_CBC +#define _libssh2_cipher_chacha20 MBEDTLS_CIPHER_CHACHA20_POLY1305 /*******************************************************************/ @@ -460,30 +465,18 @@ _libssh2_mbedtls_free(void); int _libssh2_mbedtls_random(unsigned char *buf, size_t len); -int -_libssh2_mbedtls_cipher_init(_libssh2_cipher_ctx *ctx, - _libssh2_cipher_type(type), - unsigned char *iv, - unsigned char *secret, - int encrypt); -int -_libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx, - _libssh2_cipher_type(type), - int encrypt, - unsigned char *block, - size_t blocklen, int firstlast); void _libssh2_mbedtls_cipher_dtor(_libssh2_cipher_ctx *ctx); int _libssh2_mbedtls_hash_init(mbedtls_md_context_t *ctx, mbedtls_md_type_t mdtype, - const unsigned char *key, unsigned long keylen); + const unsigned char *key, size_t keylen); int _libssh2_mbedtls_hash_final(mbedtls_md_context_t *ctx, unsigned char *hash); int -_libssh2_mbedtls_hash(const unsigned char *data, unsigned long datalen, +_libssh2_mbedtls_hash(const unsigned char *data, size_t datalen, mbedtls_md_type_t mdtype, unsigned char *hash); _libssh2_bn * @@ -492,123 +485,10 @@ _libssh2_mbedtls_bignum_init(void); void _libssh2_mbedtls_bignum_free(_libssh2_bn *bn); -int -_libssh2_mbedtls_rsa_new(libssh2_rsa_ctx **rsa, - const unsigned char *edata, - unsigned long elen, - const unsigned char *ndata, - unsigned long nlen, - const unsigned char *ddata, - unsigned long dlen, - const unsigned char *pdata, - unsigned long plen, - const unsigned char *qdata, - unsigned long qlen, - const unsigned char *e1data, - unsigned long e1len, - const unsigned char *e2data, - unsigned long e2len, - const unsigned char *coeffdata, - unsigned long coefflen); - -int -_libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa, - LIBSSH2_SESSION *session, - const char *filename, - const unsigned char *passphrase); - -int -_libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, - LIBSSH2_SESSION *session, - const char *filedata, - size_t filedata_len, - unsigned const char *passphrase); -int -_libssh2_mbedtls_rsa_sha1_verify(libssh2_rsa_ctx *rsa, - const unsigned char *sig, - unsigned long sig_len, - const unsigned char *m, - unsigned long m_len); -int -_libssh2_mbedtls_rsa_sha1_sign(LIBSSH2_SESSION *session, - libssh2_rsa_ctx *rsa, - const unsigned char *hash, - size_t hash_len, - unsigned char **signature, - size_t *signature_len); -int -_libssh2_mbedtls_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, - size_t hash_len, - const unsigned char *sig, - unsigned long sig_len, - const unsigned char *m, unsigned long m_len); -int -_libssh2_mbedtls_rsa_sha2_sign(LIBSSH2_SESSION *session, - libssh2_rsa_ctx *rsa, - const unsigned char *hash, - size_t hash_len, - unsigned char **signature, - size_t *signature_len); void _libssh2_mbedtls_rsa_free(libssh2_rsa_ctx *rsa); -int -_libssh2_mbedtls_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekey, - const char *passphrase); -int -_libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekeydata, - size_t privatekeydata_len, - const char *passphrase); #if LIBSSH2_ECDSA -int -_libssh2_mbedtls_ecdsa_create_key(LIBSSH2_SESSION *session, - _libssh2_ec_key **privkey, - unsigned char **pubkey_octal, - size_t *pubkey_octal_len, - libssh2_curve_type curve); -int -_libssh2_mbedtls_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx **ctx, - const unsigned char *k, - size_t k_len, - libssh2_curve_type curve); -int -_libssh2_mbedtls_ecdh_gen_k(_libssh2_bn **k, - _libssh2_ec_key *privkey, - const unsigned char *server_pubkey, - size_t server_pubkey_len); -int -_libssh2_mbedtls_ecdsa_verify(libssh2_ecdsa_ctx *ctx, - const unsigned char *r, size_t r_len, - const unsigned char *s, size_t s_len, - const unsigned char *m, size_t m_len); -int -_libssh2_mbedtls_ecdsa_new_private(libssh2_ecdsa_ctx **ctx, - LIBSSH2_SESSION *session, - const char *filename, - const unsigned char *passphrase); -int -_libssh2_mbedtls_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx **ctx, - LIBSSH2_SESSION *session, - const char *filedata, - size_t filedata_len, - const unsigned char *passphrase); -int -_libssh2_mbedtls_ecdsa_sign(LIBSSH2_SESSION *session, - libssh2_ecdsa_ctx *ctx, - const unsigned char *hash, - unsigned long hash_len, - unsigned char **signature, - size_t *signature_len); libssh2_curve_type _libssh2_mbedtls_ecdsa_key_get_curve_type(libssh2_ecdsa_ctx *ctx); int @@ -631,4 +511,4 @@ _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx); -#endif /* __LIBSSH2_MBEDTLS_H */ +#endif /* LIBSSH2_MBEDTLS_H */ diff --git a/libssh2/src/misc.c b/libssh2/src/misc.c index 7de6511b5..6c28327c2 100644 --- a/libssh2/src/misc.c +++ b/libssh2/src/misc.c @@ -1,6 +1,6 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2019 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,10 +35,11 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" -#include "misc.h" #ifdef HAVE_UNISTD_H #include @@ -47,7 +48,7 @@ #include #include -#ifdef WIN32 +#ifdef _WIN32 /* Force parameter type. */ #define recv(s, b, l, f) recv((s), (b), (int)(l), (f)) #define send(s, b, l, f) send((s), (b), (int)(l), (f)) @@ -124,8 +125,8 @@ int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg) return _libssh2_error_flags(session, errcode, errmsg, 0); } -#ifdef WIN32 -static int wsa2errno(void) +#ifdef _WIN32 +int _libssh2_wsa2errno(void) { switch(WSAGetLastError()) { case WSAEWOULDBLOCK: @@ -159,23 +160,29 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, (void)abstract; rc = recv(sock, buffer, length, flags); -#ifdef WIN32 - if(rc < 0) - return -wsa2errno(); -#else if(rc < 0) { + int err; +#ifdef _WIN32 + err = _libssh2_wsa2errno(); +#else + err = errno; +#endif + /* Profiling tools that use SIGPROF can cause EINTR responses. + recv() does not modify its arguments when it returns EINTR, + but there may be data waiting, so the caller should try again */ + if(err == EINTR) + return -EAGAIN; /* Sometimes the first recv() function call sets errno to ENOENT on Solaris and HP-UX */ - if(errno == ENOENT) + if(err == ENOENT) return -EAGAIN; #ifdef EWOULDBLOCK /* For VMS and other special unixes */ - else if(errno == EWOULDBLOCK) - return -EAGAIN; + else if(err == EWOULDBLOCK) + return -EAGAIN; #endif else - return -errno; + return -err; } -#endif return rc; } @@ -192,18 +199,24 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length, (void)abstract; rc = send(sock, buffer, length, flags); -#ifdef WIN32 - if(rc < 0) - return -wsa2errno(); -#else if(rc < 0) { + int err; +#ifdef _WIN32 + err = _libssh2_wsa2errno(); +#else + err = errno; +#endif + /* Profiling tools that use SIGPROF can cause EINTR responses. + send() is defined as not yet sending any data when it returns EINTR, + so the caller should try again */ + if(err == EINTR) + return -EAGAIN; #ifdef EWOULDBLOCK /* For VMS and other special unixes */ - if(errno == EWOULDBLOCK) + if(err == EWOULDBLOCK) return -EAGAIN; #endif - return -errno; + return -err; } -#endif return rc; } @@ -253,6 +266,24 @@ void _libssh2_store_u32(unsigned char **buf, uint32_t value) *buf += sizeof(uint32_t); } +/* _libssh2_store_u64 + */ +void _libssh2_store_u64(unsigned char **buf, libssh2_uint64_t value) +{ + unsigned char *ptr = *buf; + + ptr[0] = (unsigned char)((value >> 56) & 0xFF); + ptr[1] = (unsigned char)((value >> 48) & 0xFF); + ptr[2] = (unsigned char)((value >> 40) & 0xFF); + ptr[3] = (unsigned char)((value >> 32) & 0xFF); + ptr[4] = (unsigned char)((value >> 24) & 0xFF); + ptr[5] = (unsigned char)((value >> 16) & 0xFF); + ptr[6] = (unsigned char)((value >> 8) & 0xFF); + ptr[7] = (unsigned char)(value & 0xFF); + + *buf += sizeof(libssh2_uint64_t); +} + /* _libssh2_store_str */ int _libssh2_store_str(unsigned char **buf, const char *str, size_t len) @@ -283,7 +314,7 @@ int _libssh2_store_bignum2_bytes(unsigned char **buf, extraByte = (len > 0 && (p[0] & 0x80) != 0); len_stored = (uint32_t)len; - if(extraByte && len_stored == 0xffffffff) + if(extraByte && len_stored == UINT32_MAX) len_stored--; _libssh2_store_u32(buf, len_stored + extraByte); @@ -707,7 +738,7 @@ int _libssh2_gettimeofday(struct timeval *tp, void *tzp) { (void)tzp; if(tp) { -#ifdef WIN32 +#ifdef _WIN32 /* Offset between 1601-01-01 and 1970-01-01 in 100 nanosec units */ #define _WIN32_FT_OFFSET (116444736000000000) @@ -899,7 +930,6 @@ int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf, } } else { - *outlen = 0; *outbuf = NULL; } diff --git a/libssh2/src/misc.h b/libssh2/src/misc.h index 95db71425..eac2e064b 100644 --- a/libssh2/src/misc.h +++ b/libssh2/src/misc.h @@ -1,7 +1,6 @@ -#ifndef __LIBSSH2_MISC_H -#define __LIBSSH2_MISC_H -/* Copyright (c) 2009-2019 by Daniel Stenberg - * +#ifndef LIBSSH2_MISC_H +#define LIBSSH2_MISC_H +/* Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -36,6 +35,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifdef LIBSSH2_NO_CLEAR_MEMORY @@ -43,8 +44,7 @@ (void)(buf); \ (void)(size); \ } while(0) -#else -#ifdef WIN32 +#elif defined(_WIN32) #define _libssh2_explicit_zero(buf, size) SecureZeroMemory(buf, size) #elif defined(HAVE_EXPLICIT_BZERO) #define _libssh2_explicit_zero(buf, size) explicit_bzero(buf, size) @@ -57,7 +57,6 @@ void _libssh2_memzero(void *buf, size_t size); #define _libssh2_explicit_zero(buf, size) _libssh2_memzero(buf, size) #endif -#endif struct list_head { struct list_node *last; @@ -80,6 +79,11 @@ int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char *errmsg, int errflags); int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg); +#ifdef _WIN32 +/* Convert Win32 WSAGetLastError to errno equivalent */ +int _libssh2_wsa2errno(void); +#endif + void _libssh2_list_init(struct list_head *head); /* add a node last in the list */ @@ -108,6 +112,7 @@ uint32_t _libssh2_ntohu32(const unsigned char *buf); libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf); void _libssh2_htonu32(unsigned char *buf, uint32_t val); void _libssh2_store_u32(unsigned char **buf, uint32_t value); +void _libssh2_store_u64(unsigned char **buf, libssh2_uint64_t value); int _libssh2_store_str(unsigned char **buf, const char *str, size_t len); int _libssh2_store_bignum2_bytes(unsigned char **buf, const unsigned char *bytes, @@ -138,4 +143,4 @@ void _libssh2_xor_data(unsigned char *output, void _libssh2_aes_ctr_increment(unsigned char *ctr, size_t length); -#endif /* _LIBSSH2_MISC_H */ +#endif /* LIBSSH2_MISC_H */ diff --git a/libssh2/src/openssl.c b/libssh2/src/openssl.c index 919a8d9b1..eba05031b 100644 --- a/libssh2/src/openssl.c +++ b/libssh2/src/openssl.c @@ -1,8 +1,7 @@ -/* Copyright (C) 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * Copyright (c) 2004-2006, Sara Golemon - * - * Author: Simon Josefsson +/* Copyright (C) Simon Josefsson + * Copyright (C) The Written Word, Inc. + * Copyright (C) Sara Golemon + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -36,6 +35,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifdef LIBSSH2_CRYPTO_C /* Compile this via crypto.c */ @@ -43,16 +44,161 @@ #include #include -#ifndef EVP_MAX_BLOCK_LENGTH -#define EVP_MAX_BLOCK_LENGTH 32 +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx) +{ +#ifdef USE_OPENSSL_3 + *ctx = NULL; + return 1; +#elif defined(HAVE_OPAQUE_STRUCTS) + *ctx = HMAC_CTX_new(); + return *ctx ? 1 : 0; +#else + HMAC_CTX_init(ctx); + return 1; +#endif +} + +#ifdef USE_OPENSSL_3 +static int _libssh2_hmac_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen, + const char *digest_name) +{ + EVP_MAC* mac; + OSSL_PARAM params[3]; + + mac = EVP_MAC_fetch(NULL, OSSL_MAC_NAME_HMAC, NULL); + if(!mac) + return 0; + + *ctx = EVP_MAC_CTX_new(mac); + EVP_MAC_free(mac); + if(!*ctx) + return 0; + + params[0] = OSSL_PARAM_construct_octet_string( + OSSL_MAC_PARAM_KEY, (void *)key, keylen); + params[1] = OSSL_PARAM_construct_utf8_string( + OSSL_MAC_PARAM_DIGEST, (char *)digest_name, 0); + params[2] = OSSL_PARAM_construct_end(); + + return EVP_MAC_init(*ctx, NULL, 0, params); +} #endif -int -read_openssh_private_key_from_memory(void **key_ctx, LIBSSH2_SESSION *session, - const char *key_type, - const char *filedata, - size_t filedata_len, - unsigned const char *passphrase); +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_MD5); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_md5(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_md5(), NULL); +#endif +} +#endif + +#if LIBSSH2_HMAC_RIPEMD +int _libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_RIPEMD160); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_ripemd160(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_ripemd160(), NULL); +#endif +} +#endif + +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_SHA1); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_sha1(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha1(), NULL); +#endif +} + +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_SHA2_256); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_sha256(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha256(), NULL); +#endif +} + +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ +#ifdef USE_OPENSSL_3 + return _libssh2_hmac_init(ctx, key, keylen, OSSL_DIGEST_NAME_SHA2_512); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Init_ex(*ctx, key, (int)keylen, EVP_sha512(), NULL); +#else + return HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha512(), NULL); +#endif +} + +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen) +{ +#ifdef USE_OPENSSL_3 + return EVP_MAC_update(*ctx, data, datalen); +#elif defined(HAVE_OPAQUE_STRUCTS) +/* FIXME: upstream bug as of v5.7.0: datalen is int instead of size_t */ +#if defined(LIBSSH2_WOLFSSL) + return HMAC_Update(*ctx, data, (int)datalen); +#else /* !LIBSSH2_WOLFSSL */ + return HMAC_Update(*ctx, data, datalen); +#endif /* LIBSSH2_WOLFSSL */ +#else + return HMAC_Update(ctx, data, datalen); +#endif +} + +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *data) +{ +#ifdef USE_OPENSSL_3 + return EVP_MAC_final(*ctx, data, NULL, MAX_MACSIZE); +#elif defined(HAVE_OPAQUE_STRUCTS) + return HMAC_Final(*ctx, data, NULL); +#else + return HMAC_Final(ctx, data, NULL); +#endif +} + +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx) +{ +#ifdef USE_OPENSSL_3 + EVP_MAC_CTX_free(*ctx); +#elif defined(HAVE_OPAQUE_STRUCTS) + HMAC_CTX_free(*ctx); +#else + HMAC_cleanup(ctx); +#endif +} + +static int +_libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session, + void **key_ctx, + const char *key_type, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + const char *privatekeydata, + size_t privatekeydata_len, + unsigned const char *passphrase); static int _libssh2_sk_pub_openssh_keyfilememory(LIBSSH2_SESSION *session, @@ -91,6 +237,20 @@ write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes) } #endif +static inline void +_libssh2_swap_bytes(unsigned char *buf, unsigned long len) +{ +#if !defined(WORDS_BIGENDIAN) || !WORDS_BIGENDIAN + unsigned long i, j; + unsigned char temp; + for(i = 0, j = len - 1; i < j; i++, j--) { + temp = buf[i]; + buf[i] = buf[j]; + buf[j] = temp; + } +#endif +} + int _libssh2_openssl_random(void *buf, size_t len) { @@ -120,6 +280,78 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, unsigned long e2len, const unsigned char *coeffdata, unsigned long coefflen) { +#ifdef USE_OPENSSL_3 + int ret = 0; + EVP_PKEY_CTX *ctx; + OSSL_PARAM params[4]; + int param_num = 0; + unsigned char *nbuf = NULL; + unsigned char *ebuf = NULL; + unsigned char *dbuf = NULL; + + (void)pdata; + (void)plen; + (void)qdata; + (void)qlen; + (void)e1data; + (void)e1len; + (void)e2data; + (void)e2len; + (void)coeffdata; + (void)coefflen; + + if(ndata && nlen > 0) { + nbuf = OPENSSL_malloc(nlen); + + if(nbuf) { + memcpy(nbuf, ndata, nlen); + _libssh2_swap_bytes(nbuf, nlen); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, nbuf, nlen); + } + } + + if(edata && elen > 0) { + ebuf = OPENSSL_malloc(elen); + if(ebuf) { + memcpy(ebuf, edata, elen); + _libssh2_swap_bytes(ebuf, elen); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E, ebuf, elen); + } + } + + if(ddata && dlen > 0) { + dbuf = OPENSSL_malloc(dlen); + if(dbuf) { + memcpy(dbuf, ddata, dlen); + _libssh2_swap_bytes(dbuf, dlen); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_D, dbuf, dlen); + } + } + + params[param_num] = OSSL_PARAM_construct_end(); + + *rsa = NULL; + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + + if(EVP_PKEY_fromdata_init(ctx) > 0) { + ret = EVP_PKEY_fromdata(ctx, rsa, EVP_PKEY_KEYPAIR, params); + } + if(nbuf) + OPENSSL_clear_free(nbuf, nlen); + + if(ebuf) + OPENSSL_clear_free(ebuf, elen); + + if(dbuf) + OPENSSL_clear_free(dbuf, dlen); + + EVP_PKEY_CTX_free(ctx); + + return (ret == 1) ? 0 : -1; +#else BIGNUM * e; BIGNUM * n; BIGNUM * d = 0; @@ -179,6 +411,8 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, (*rsa)->iqmp = iqmp; #endif return 0; + +#endif /* USE_OPENSSL_3 */ } int @@ -188,6 +422,11 @@ _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, size_t sig_len, const unsigned char *m, size_t m_len) { +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = NULL; + const EVP_MD *md = NULL; +#endif + int ret; int nid_type; unsigned char *hash = malloc(hash_len); @@ -201,7 +440,6 @@ _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, else if(hash_len == SHA256_DIGEST_LENGTH) { nid_type = NID_sha256; ret = _libssh2_sha256(m, m_len, hash); - } else if(hash_len == SHA512_DIGEST_LENGTH) { nid_type = NID_sha512; @@ -221,9 +459,37 @@ _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, return -1; /* failure */ } +#ifdef USE_OPENSSL_3 + ctx = EVP_PKEY_CTX_new(rsactx, NULL); + + if(nid_type == NID_sha1) { + md = EVP_sha1(); + } + else if(nid_type == NID_sha256) { + md = EVP_sha256(); + } + else if(nid_type == NID_sha512) { + md = EVP_sha512(); + } + + if(ctx && md) { + if(EVP_PKEY_verify_init(ctx) > 0 && + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) > 0 && + EVP_PKEY_CTX_set_signature_md(ctx, md) > 0) { + ret = EVP_PKEY_verify(ctx, sig, sig_len, hash, hash_len); + } + } + + if(ctx) { + EVP_PKEY_CTX_free(ctx); + } + +#else + ret = RSA_verify(nid_type, hash, (unsigned int) hash_len, (unsigned char *) sig, (unsigned int) sig_len, rsactx); +#endif free(hash); @@ -256,6 +522,97 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, unsigned long y_len, const unsigned char *x, unsigned long x_len) { +#ifdef USE_OPENSSL_3 + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM params[6]; + int param_num = 0; + unsigned char *p_buf = NULL; + unsigned char *q_buf = NULL; + unsigned char *g_buf = NULL; + unsigned char *y_buf = NULL; + unsigned char *x_buf = NULL; + + if(p && p_len > 0) { + p_buf = OPENSSL_malloc(p_len); + + if(p_buf) { + memcpy(p_buf, p, p_len); + _libssh2_swap_bytes(p_buf, p_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, p_buf, p_len); + } + } + + if(q && q_len > 0) { + q_buf = OPENSSL_malloc(q_len); + + if(q_buf) { + memcpy(q_buf, q, q_len); + _libssh2_swap_bytes(q_buf, q_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_Q, q_buf, q_len); + } + } + + if(g && g_len > 0) { + g_buf = OPENSSL_malloc(g_len); + + if(g_buf) { + memcpy(g_buf, g, g_len); + _libssh2_swap_bytes(g_buf, g_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_G, g_buf, g_len); + } + } + + if(y && y_len > 0) { + y_buf = OPENSSL_malloc(y_len); + + if(y_buf) { + memcpy(y_buf, y, y_len); + _libssh2_swap_bytes(y_buf, y_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PUB_KEY, y_buf, y_len); + } + } + + if(x && x_len > 0) { + x_buf = OPENSSL_malloc(x_len); + + if(x_buf) { + memcpy(x_buf, x, x_len); + _libssh2_swap_bytes(x_buf, x_len); + params[param_num++] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY, + x_buf, x_len); + } + } + + params[param_num] = OSSL_PARAM_construct_end(); + + *dsactx = NULL; + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL); + + if(EVP_PKEY_fromdata_init(ctx) > 0) { + ret = EVP_PKEY_fromdata(ctx, dsactx, EVP_PKEY_KEYPAIR, params); + } + + if(p_buf) + OPENSSL_clear_free(p_buf, p_len); + if(q_buf) + OPENSSL_clear_free(q_buf, q_len); + if(g_buf) + OPENSSL_clear_free(g_buf, g_len); + if(x_buf) + OPENSSL_clear_free(x_buf, x_len); + if(y_buf) + OPENSSL_clear_free(y_buf, y_len); + + return (ret == 1) ? 0 : -1; + +#else + BIGNUM * p_bn; BIGNUM * q_bn; BIGNUM * g_bn; @@ -296,6 +653,8 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, (*dsactx)->priv_key = priv_key; #endif return 0; + +#endif /* USE_OPENSSL_3 */ } int @@ -303,6 +662,12 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, const unsigned char *sig, const unsigned char *m, size_t m_len) { +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = NULL; + unsigned char *der = NULL; + int der_len = 0; +#endif + unsigned char hash[SHA_DIGEST_LENGTH]; DSA_SIG * dsasig; BIGNUM * r; @@ -321,9 +686,30 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, dsasig->r = r; dsasig->s = s; #endif + +#ifdef USE_OPENSSL_3 + ctx = EVP_PKEY_CTX_new(dsactx, NULL); + der_len = i2d_DSA_SIG(dsasig, &der); + + if(ctx && !_libssh2_sha1(m, m_len, hash)) { + /* _libssh2_sha1() succeeded */ + if(EVP_PKEY_verify_init(ctx) > 0) { + ret = EVP_PKEY_verify(ctx, der, der_len, hash, SHA_DIGEST_LENGTH); + } + } + + if(ctx) { + EVP_PKEY_CTX_free(ctx); + } + + if(der) { + OPENSSL_clear_free(der, der_len); + } +#else if(!_libssh2_sha1(m, m_len, hash)) /* _libssh2_sha1() succeeded */ ret = DSA_do_verify(hash, SHA_DIGEST_LENGTH, dsasig, dsactx); +#endif DSA_SIG_free(dsasig); @@ -342,8 +728,25 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, libssh2_curve_type _libssh2_ecdsa_get_curve_type(libssh2_ecdsa_ctx *ec_ctx) { +#ifdef USE_OPENSSL_3 + int bits = 0; + EVP_PKEY_get_int_param(ec_ctx, OSSL_PKEY_PARAM_BITS, &bits); + + if(bits == 256) { + return LIBSSH2_EC_CURVE_NISTP256; + } + else if(bits == 384) { + return LIBSSH2_EC_CURVE_NISTP384; + } + else if(bits == 521) { + return LIBSSH2_EC_CURVE_NISTP521; + } + + return LIBSSH2_EC_CURVE_NISTP256; +#else const EC_GROUP *group = EC_KEY_get0_group(ec_ctx); return EC_GROUP_get_curve_name(group); +#endif } /* _libssh2_ecdsa_curve_type_from_name @@ -356,7 +759,6 @@ int _libssh2_ecdsa_curve_type_from_name(const char *name, libssh2_curve_type *out_type) { - int ret = 0; libssh2_curve_type type; if(!name || strlen(name) != 19) @@ -369,19 +771,14 @@ _libssh2_ecdsa_curve_type_from_name(const char *name, else if(strcmp(name, "ecdsa-sha2-nistp521") == 0) type = LIBSSH2_EC_CURVE_NISTP521; else { -/* silence: - warning C4701: potentially uninitialized local variable 'type' used */ -#if defined(_MSC_VER) - type = (libssh2_curve_type)0; -#endif - ret = -1; + return -1; } - if(ret == 0 && out_type) { + if(out_type) { *out_type = type; } - return ret; + return 0; } /* _libssh2_ecdsa_curve_name_with_octal_new @@ -395,45 +792,131 @@ _libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ec_ctx, const unsigned char *k, size_t k_len, libssh2_curve_type curve) { - int ret = 0; - const EC_GROUP *ec_group = NULL; + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + const char *n = EC_curve_nid2nist(curve); + char *group_name = NULL; + unsigned char *data = NULL; + + if(!ctx) + return -1; + + if(n) { + group_name = OPENSSL_zalloc(strlen(n) + 1); + } + + if(k_len > 0) { + data = OPENSSL_malloc(k_len); + } + + if(group_name && data) { + OSSL_PARAM params[3] = { 0 }; + + memcpy(group_name, n, strlen(n)); + memcpy(data, k, k_len); + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + group_name, 0); + + params[1] = + OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, + data, k_len); + + params[2] = OSSL_PARAM_construct_end(); + + if(EVP_PKEY_fromdata_init(ctx) > 0) + ret = EVP_PKEY_fromdata(ctx, ec_ctx, EVP_PKEY_PUBLIC_KEY, + params); + else + ret = -1; + } + else + ret = -1; + + if(group_name) + OPENSSL_clear_free(group_name, strlen(n)); + + if(data) + OPENSSL_clear_free(data, k_len); + + EVP_PKEY_CTX_free(ctx); +#else EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve); - EC_POINT *point = NULL; if(ec_key) { + const EC_GROUP *ec_group = NULL; + EC_POINT *point = NULL; + ec_group = EC_KEY_get0_group(ec_key); point = EC_POINT_new(ec_group); - ret = EC_POINT_oct2point(ec_group, point, k, k_len, NULL); - ret = EC_KEY_set_public_key(ec_key, point); - if(point) + if(point) { + ret = EC_POINT_oct2point(ec_group, point, k, k_len, NULL); + if(ret == 1) + ret = EC_KEY_set_public_key(ec_key, point); + EC_POINT_free(point); + } + else + ret = -1; - if(ec_ctx) + if(ret == 1 && ec_ctx) *ec_ctx = ec_key; + else { + EC_KEY_free(ec_key); + ret = -1; + } } + else + ret = -1; +#endif return (ret == 1) ? 0 : -1; } +#ifdef USE_OPENSSL_3 #define LIBSSH2_ECDSA_VERIFY(digest_type) \ do { \ unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ - libssh2_sha##digest_type(m, m_len, hash); \ - ret = ECDSA_do_verify(hash, SHA##digest_type##_DIGEST_LENGTH, \ - ecdsa_sig, ec_key); \ + if(libssh2_sha##digest_type(m, m_len, hash) == 0) { \ + ret = EVP_PKEY_verify_init(ctx); \ + if(ret > 0) { \ + ret = EVP_PKEY_verify(ctx, der, der_len, hash, \ + SHA##digest_type##_DIGEST_LENGTH); \ + } \ + } \ } while(0) +#else +#define LIBSSH2_ECDSA_VERIFY(digest_type) \ + do { \ + unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ + if(libssh2_sha##digest_type(m, m_len, hash) == 0) { \ + ret = ECDSA_do_verify(hash, \ + SHA##digest_type##_DIGEST_LENGTH, \ + ecdsa_sig, ec_key); \ + } \ + } while(0) +#endif int -_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, +_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ecdsa_ctx, const unsigned char *r, size_t r_len, const unsigned char *s, size_t s_len, const unsigned char *m, size_t m_len) { int ret = 0; - EC_KEY *ec_key = (EC_KEY*)ctx; - libssh2_curve_type type = _libssh2_ecdsa_get_curve_type(ec_key); + libssh2_curve_type type = _libssh2_ecdsa_get_curve_type(ecdsa_ctx); + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = NULL; + unsigned char *der = NULL; + int der_len = 0; +#else + EC_KEY *ec_key = (EC_KEY*)ecdsa_ctx; +#endif #ifdef HAVE_OPAQUE_STRUCTS ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new(); @@ -443,7 +926,6 @@ _libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, BN_bin2bn(r, (int) r_len, pr); BN_bin2bn(s, (int) s_len, ps); ECDSA_SIG_set0(ecdsa_sig, pr, ps); - #else ECDSA_SIG ecdsa_sig_; ECDSA_SIG *ecdsa_sig = &ecdsa_sig_; @@ -453,6 +935,20 @@ _libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, BN_bin2bn(s, (int) s_len, ecdsa_sig_.s); #endif +#ifdef USE_OPENSSL_3 + ctx = EVP_PKEY_CTX_new(ecdsa_ctx, NULL); + if(!ctx) { + ret = -1; + goto cleanup; + } + + der_len = i2d_ECDSA_SIG(ecdsa_sig, &der); + if(der_len <= 0) { + ret = -1; + goto cleanup; + } +#endif + if(type == LIBSSH2_EC_CURVE_NISTP256) { LIBSSH2_ECDSA_VERIFY(256); } @@ -463,12 +959,24 @@ _libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, LIBSSH2_ECDSA_VERIFY(512); } +#ifdef USE_OPENSSL_3 +cleanup: + + if(ctx) + EVP_PKEY_CTX_free(ctx); + + if(der) + OPENSSL_free(der); +#endif + #ifdef HAVE_OPAQUE_STRUCTS if(ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); #else - BN_clear_free(ecdsa_sig_.s); - BN_clear_free(ecdsa_sig_.r); + if(ecdsa_sig_.s) + BN_clear_free(ecdsa_sig_.s); + if(ecdsa_sig_.r) + BN_clear_free(ecdsa_sig_.r); #endif return (ret == 1) ? 0 : -1; @@ -507,6 +1015,10 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h, #endif } +#ifndef EVP_MAX_BLOCK_LENGTH +#define EVP_MAX_BLOCK_LENGTH 32 +#endif + int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, _libssh2_cipher_type(algo), @@ -573,8 +1085,7 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, #endif } -#if (defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) || \ - defined(LIBSSH2_WOLFSSL) +#if defined(USE_OPENSSL_3) || defined(LIBSSH2_WOLFSSL) if(ret != -1) #else if(ret >= 1) @@ -587,7 +1098,13 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, decrypt: verify tag, if applicable in!=NULL is equivalent to EVP_CipherUpdate in==NULL is equivalent to EVP_CipherFinal */ -#ifdef HAVE_OPAQUE_STRUCTS +#if defined(LIBSSH2_WOLFSSL) && LIBWOLFSSL_VERSION_HEX < 0x05007000 + /* Workaround for wolfSSL bug fixed in v5.7.0: + https://github.com/wolfSSL/wolfssl/pull/7143 */ + unsigned char buf2[EVP_MAX_BLOCK_LENGTH]; + int outb; + ret = EVP_CipherFinal(*ctx, buf2, &outb); +#elif defined(HAVE_OPAQUE_STRUCTS) ret = EVP_Cipher(*ctx, NULL, NULL, 0); /* final */ #else ret = EVP_Cipher(ctx, NULL, NULL, 0); /* final */ @@ -622,13 +1139,8 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, void _libssh2_openssl_crypto_init(void) { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ - !defined(LIBRESSL_VERSION_NUMBER) -#ifndef OPENSSL_NO_ENGINE - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); -#endif -#else +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); @@ -637,6 +1149,9 @@ void _libssh2_openssl_crypto_init(void) ENGINE_register_all_complete(); #endif #endif +#if defined(LIBSSH2_WOLFSSL) && defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif } void _libssh2_openssl_crypto_exit(void) @@ -722,43 +1237,69 @@ read_private_key_from_file(void **key_ctx, int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa, LIBSSH2_SESSION * session, - const char *filedata, size_t filedata_len, + const char *filedata, + size_t filedata_len, unsigned const char *passphrase) { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_rsa = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_rsa = (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; +#endif _libssh2_init_if_needed(); - rc = read_private_key_from_memory((void **) rsa, read_rsa, - filedata, filedata_len, passphrase); + rc = read_private_key_from_memory((void **)rsa, read_rsa, + filedata, filedata_len, + passphrase); if(rc) { - rc = read_openssh_private_key_from_memory((void **)rsa, session, - "ssh-rsa", filedata, filedata_len, passphrase); + rc = _libssh2_pub_priv_openssh_keyfilememory(session, (void **)rsa, + "ssh-rsa", + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); } return rc; } static unsigned char * -gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, +gen_publickey_from_rsa(LIBSSH2_SESSION *session, libssh2_rsa_ctx *rsa, size_t *key_len) { int e_bytes, n_bytes; unsigned long len; - unsigned char *key; + unsigned char *key = NULL; unsigned char *p; + +#ifdef USE_OPENSSL_3 + BIGNUM * e = NULL; + BIGNUM * n = NULL; + + EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_E, &e); + EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_N, &n); +#else const BIGNUM * e; const BIGNUM * n; -#ifdef HAVE_OPAQUE_STRUCTS +#if defined(HAVE_OPAQUE_STRUCTS) + e = NULL; + n = NULL; + RSA_get0_key(rsa, &n, &e, NULL); #else e = rsa->e; n = rsa->n; #endif +#endif + if(!e || !n) { + goto fail; + } + e_bytes = BN_num_bytes(e) + 1; n_bytes = BN_num_bytes(n) + 1; @@ -767,7 +1308,7 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, key = LIBSSH2_ALLOC(session, len); if(!key) { - return NULL; + goto fail; } /* Process key encoding. */ @@ -782,6 +1323,11 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, p = write_bn(p, n, n_bytes); *key_len = (size_t)(p - key); +fail: +#ifdef USE_OPENSSL_3 + BN_clear_free(e); + BN_clear_free(n); +#endif return key; } @@ -793,7 +1339,7 @@ gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, size_t *pubkeydata_len, EVP_PKEY *pk) { - RSA* rsa = NULL; + libssh2_rsa_ctx* rsa = NULL; unsigned char *key; unsigned char *method_buf = NULL; size_t key_len; @@ -802,7 +1348,11 @@ gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, LIBSSH2_TRACE_AUTH, "Computing public key from RSA private key envelope")); +#ifdef USE_OPENSSL_3 + rsa = pk; +#else rsa = EVP_PKEY_get1_RSA(pk); +#endif if(!rsa) { /* Assume memory allocation error... what else could it be ? */ goto __alloc_error; @@ -817,19 +1367,27 @@ gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, if(!key) { goto __alloc_error; } +#ifndef USE_OPENSSL_3 RSA_free(rsa); +#endif memcpy(method_buf, "ssh-rsa", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; + *method = method_buf; + if(method_len) { + *method_len = 7; + } + *pubkeydata = key; + if(pubkeydata_len) { + *pubkeydata_len = key_len; + } return 0; __alloc_error: +#ifndef USE_OPENSSL_3 if(rsa) { RSA_free(rsa); } +#endif if(method_buf) { LIBSSH2_FREE(session, method_buf); } @@ -839,7 +1397,8 @@ __alloc_error: "Unable to allocate memory for private key data"); } -static int _libssh2_rsa_new_additional_parameters(RSA *rsa) +#ifndef USE_OPENSSL_3 +static int _libssh2_rsa_new_additional_parameters(libssh2_rsa_ctx *rsa) { BN_CTX *ctx = NULL; BIGNUM *aux = NULL; @@ -910,6 +1469,7 @@ out: return rc; } +#endif /* ndef USE_OPENSSL_3 */ static int gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session, @@ -923,7 +1483,7 @@ gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session, int rc = 0; size_t nlen, elen, dlen, plen, qlen, coefflen, commentlen; unsigned char *n, *e, *d, *p, *q, *coeff, *comment; - RSA *rsa = NULL; + libssh2_rsa_ctx *rsa = NULL; _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -988,32 +1548,40 @@ gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session, goto fail; } +#ifndef USE_OPENSSL_3 if(rsa) rc = _libssh2_rsa_new_additional_parameters(rsa); +#endif if(rsa && pubkeydata && method) { +#ifdef USE_OPENSSL_3 + EVP_PKEY *pk = rsa; +#else EVP_PKEY *pk = EVP_PKEY_new(); EVP_PKEY_set1_RSA(pk, rsa); +#endif rc = gen_publickey_from_rsa_evp(session, method, method_len, pubkeydata, pubkeydata_len, pk); +#ifndef USE_OPENSSL_3 if(pk) EVP_PKEY_free(pk); +#endif } if(rsa_ctx) *rsa_ctx = rsa; else - RSA_free(rsa); + _libssh2_rsa_free(rsa); return rc; fail: if(rsa) - RSA_free(rsa); + _libssh2_rsa_free(rsa); return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, @@ -1063,8 +1631,8 @@ _libssh2_rsa_new_openssh_private(libssh2_rsa_ctx ** rsa, if(strcmp("ssh-rsa", (const char *)buf) == 0) { rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted, - NULL, 0, - NULL, 0, rsa); + NULL, NULL, + NULL, NULL, rsa); } else { rc = -1; @@ -1083,8 +1651,13 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_rsa = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_rsa = (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; +#endif _libssh2_init_if_needed(); @@ -1104,13 +1677,19 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, int _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa, LIBSSH2_SESSION * session, - const char *filedata, size_t filedata_len, + const char *filedata, + size_t filedata_len, unsigned const char *passphrase) { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_dsa = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_dsa = (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; +#endif _libssh2_init_if_needed(); @@ -1119,24 +1698,36 @@ _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa, passphrase); if(rc) { - rc = read_openssh_private_key_from_memory((void **)dsa, session, - "ssh-dsa", - filedata, filedata_len, - passphrase); + rc = _libssh2_pub_priv_openssh_keyfilememory(session, (void **)dsa, + "ssh-dsa", + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); } return rc; } static unsigned char * -gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, +gen_publickey_from_dsa(LIBSSH2_SESSION* session, libssh2_dsa_ctx *dsa, size_t *key_len) { int p_bytes, q_bytes, g_bytes, k_bytes; unsigned long len; - unsigned char *key; + unsigned char *key = NULL; unsigned char *p; +#ifdef USE_OPENSSL_3 + BIGNUM * p_bn = NULL; + BIGNUM * q = NULL; + BIGNUM * g = NULL; + BIGNUM * pub_key = NULL; + + EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_P, &p_bn); + EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_Q, &q); + EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_G, &g); + EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_PUB_KEY, &pub_key); +#else const BIGNUM * p_bn; const BIGNUM * q; const BIGNUM * g; @@ -1153,6 +1744,7 @@ gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, DSA_get0_key(dsa, &pub_key, NULL); #else pub_key = dsa->pub_key; +#endif #endif p_bytes = BN_num_bytes(p_bn) + 1; q_bytes = BN_num_bytes(q) + 1; @@ -1164,7 +1756,7 @@ gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, key = LIBSSH2_ALLOC(session, len); if(!key) { - return NULL; + goto fail; } /* Process key encoding. */ @@ -1181,6 +1773,13 @@ gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, p = write_bn(p, pub_key, k_bytes); *key_len = (size_t)(p - key); +fail: +#ifdef USE_OPENSSL_3 + BN_clear_free(p_bn); + BN_clear_free(q); + BN_clear_free(g); + BN_clear_free(pub_key); +#endif return key; } @@ -1192,7 +1791,7 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, size_t *pubkeydata_len, EVP_PKEY *pk) { - DSA* dsa = NULL; + libssh2_dsa_ctx *dsa = NULL; unsigned char *key; unsigned char *method_buf = NULL; size_t key_len; @@ -1201,7 +1800,11 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, LIBSSH2_TRACE_AUTH, "Computing public key from DSA private key envelope")); +#ifdef USE_OPENSSL_3 + dsa = pk; +#else dsa = EVP_PKEY_get1_DSA(pk); +#endif if(!dsa) { /* Assume memory allocation error... what else could it be ? */ goto __alloc_error; @@ -1216,19 +1819,27 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, if(!key) { goto __alloc_error; } +#ifndef USE_OPENSSL_3 DSA_free(dsa); +#endif memcpy(method_buf, "ssh-dss", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; + *method = method_buf; + if(method_len) { + *method_len = 7; + } + *pubkeydata = key; + if(pubkeydata_len) { + *pubkeydata_len = key_len; + } return 0; __alloc_error: +#ifndef USE_OPENSSL_3 if(dsa) { DSA_free(dsa); } +#endif if(method_buf) { LIBSSH2_FREE(session, method_buf); } @@ -1250,7 +1861,7 @@ gen_publickey_from_dsa_openssh_priv_data(LIBSSH2_SESSION *session, int rc = 0; size_t plen, qlen, glen, pub_len, priv_len; unsigned char *p, *q, *g, *pub_key, *priv_key; - DSA *dsa = NULL; + libssh2_dsa_ctx *dsa = NULL; _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -1300,28 +1911,34 @@ gen_publickey_from_dsa_openssh_priv_data(LIBSSH2_SESSION *session, } if(dsa && pubkeydata && method) { +#ifdef USE_OPENSSL_3 + EVP_PKEY *pk = dsa; +#else EVP_PKEY *pk = EVP_PKEY_new(); EVP_PKEY_set1_DSA(pk, dsa); +#endif rc = gen_publickey_from_dsa_evp(session, method, method_len, pubkeydata, pubkeydata_len, pk); +#ifndef USE_OPENSSL_3 if(pk) EVP_PKEY_free(pk); +#endif } if(dsa_ctx) *dsa_ctx = dsa; else - DSA_free(dsa); + _libssh2_dsa_free(dsa); return rc; fail: if(dsa) - DSA_free(dsa); + _libssh2_dsa_free(dsa); return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, @@ -1371,8 +1988,8 @@ _libssh2_dsa_new_openssh_private(libssh2_dsa_ctx ** dsa, if(strcmp("ssh-dss", (const char *)buf) == 0) { rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted, - NULL, 0, - NULL, 0, dsa); + NULL, NULL, + NULL, NULL, dsa); } else { rc = -1; @@ -1391,8 +2008,13 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_dsa = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_dsa = (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; +#endif _libssh2_init_if_needed(); @@ -1409,7 +2031,6 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, #endif /* LIBSSH_DSA */ #if LIBSSH2_ECDSA - int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, LIBSSH2_SESSION * session, @@ -1419,20 +2040,26 @@ _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, { int rc; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#endif _libssh2_init_if_needed(); - rc = read_private_key_from_memory((void **) ec_ctx, read_ec, + rc = read_private_key_from_memory((void **)ec_ctx, read_ec, filedata, filedata_len, passphrase); if(rc) { - rc = read_openssh_private_key_from_memory((void **)ec_ctx, session, - "ssh-ecdsa", - filedata, filedata_len, - passphrase); + rc = _libssh2_pub_priv_openssh_keyfilememory(session, (void **)ec_ctx, + "ssh-ecdsa", + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); } return rc; @@ -1589,10 +2216,14 @@ gen_publickey_from_ed_evp(LIBSSH2_SESSION *session, goto fail; } - *method = methodBuf; - *method_len = sizeof(methodName) - 1; - *pubkeydata = keyBuf; - *pubkeydata_len = bufLen; + *method = methodBuf; + if(method_len) { + *method_len = sizeof(methodName) - 1; + } + *pubkeydata = keyBuf; + if(pubkeydata_len) { + *pubkeydata_len = bufLen; + } return 0; fail: @@ -1901,7 +2532,6 @@ clean_exit: return -1; } - int _libssh2_ed25519_new_private(libssh2_ed25519_ctx ** ed_ctx, LIBSSH2_SESSION * session, @@ -1944,12 +2574,9 @@ _libssh2_ed25519_new_private(libssh2_ed25519_ctx ** ed_ctx, } if(strcmp("ssh-ed25519", (const char *)buf) == 0) { - rc = gen_publickey_from_ed25519_openssh_priv_data(session, - decrypted, - NULL, - NULL, - NULL, - NULL, + rc = gen_publickey_from_ed25519_openssh_priv_data(session, decrypted, + NULL, NULL, + NULL, NULL, &ctx); } else { @@ -2018,10 +2645,8 @@ _libssh2_ed25519_new_private_sk(libssh2_ed25519_ctx **ed_ctx, if(strcmp("sk-ssh-ed25519@openssh.com", (const char *)buf) == 0) { rc = gen_publickey_from_sk_ed25519_openssh_priv_data(session, decrypted, - NULL, - NULL, - NULL, - NULL, + NULL, NULL, + NULL, NULL, flags, application, key_handle, @@ -2071,10 +2696,11 @@ _libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx ** ed_ctx, return 0; } - return read_openssh_private_key_from_memory((void **)ed_ctx, session, - "ssh-ed25519", - filedata, filedata_len, - passphrase); + return _libssh2_pub_priv_openssh_keyfilememory(session, (void **)ed_ctx, + "ssh-ed25519", + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); } int @@ -2141,17 +2767,58 @@ _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, size_t hash_len, unsigned char **signature, size_t *signature_len) { - int ret; - unsigned char *sig; - unsigned int sig_len; + int ret = -1; + unsigned char *sig = NULL; + +#ifdef USE_OPENSSL_3 + size_t sig_len = 0; + BIGNUM *n = NULL; + const EVP_MD *md = NULL; + + if(EVP_PKEY_get_bn_param(rsactx, OSSL_PKEY_PARAM_RSA_N, &n) > 0) { + sig_len = BN_num_bytes(n); + BN_clear_free(n); + } + + if(sig_len > 0) + sig = LIBSSH2_ALLOC(session, sig_len); +#else + unsigned int sig_len = 0; sig_len = RSA_size(rsactx); sig = LIBSSH2_ALLOC(session, sig_len); +#endif if(!sig) { return -1; } +#ifdef USE_OPENSSL_3 + if(hash_len == SHA_DIGEST_LENGTH) + md = EVP_sha1(); + else if(hash_len == SHA256_DIGEST_LENGTH) + md = EVP_sha256(); + else if(hash_len == SHA512_DIGEST_LENGTH) + md = EVP_sha512(); + else { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unsupported hash digest length"); + } + + if(md) { + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(rsactx, NULL); + if(ctx && + EVP_PKEY_sign_init(ctx) > 0 && + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) > 0 && + EVP_PKEY_CTX_set_signature_md(ctx, md) > 0) { + ret = EVP_PKEY_sign(ctx, sig, &sig_len, hash, hash_len); + } + + if(ctx) { + EVP_PKEY_CTX_free(ctx); + } + } +#else if(hash_len == SHA_DIGEST_LENGTH) ret = RSA_sign(NID_sha1, hash, (unsigned int) hash_len, sig, &sig_len, rsactx); @@ -2166,6 +2833,7 @@ _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, "Unsupported hash digest length"); ret = -1; } +#endif if(!ret) { LIBSSH2_FREE(session, sig); @@ -2196,16 +2864,43 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, const unsigned char *hash, - unsigned long hash_len, unsigned char *signature) + size_t hash_len, unsigned char *signature) { - DSA_SIG *sig; + DSA_SIG *sig = NULL; const BIGNUM * r; const BIGNUM * s; int r_len, s_len; +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(dsactx, NULL); + unsigned char *buf = NULL; + size_t sig_len = 0; + int size = 0; + + if(EVP_PKEY_get_int_param(dsactx, OSSL_PKEY_PARAM_MAX_SIZE, &size) > 0) { + sig_len = size; + buf = OPENSSL_malloc(size); + } + + if(buf && ctx && EVP_PKEY_sign_init(ctx) > 0) { + EVP_PKEY_sign(ctx, buf, &sig_len, hash, hash_len); + } + + if(ctx) { + EVP_PKEY_CTX_free(ctx); + } + + if(buf) { + const unsigned char *in = buf; + d2i_DSA_SIG(&sig, &in, (long)sig_len); + OPENSSL_clear_free(buf, size); + } +#else (void)hash_len; sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx); +#endif + if(!sig) { return -1; } @@ -2217,20 +2912,20 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, s = sig->s; #endif r_len = BN_num_bytes(r); - if(r_len < 1 || r_len > 20) { + if(r_len < 1 || r_len > SHA_DIGEST_LENGTH) { DSA_SIG_free(sig); return -1; } s_len = BN_num_bytes(s); - if(s_len < 1 || s_len > 20) { + if(s_len < 1 || s_len > SHA_DIGEST_LENGTH) { DSA_SIG_free(sig); return -1; } - memset(signature, 0, 40); + memset(signature, 0, SHA_DIGEST_LENGTH * 2); - BN_bn2bin(r, signature + (20 - r_len)); - BN_bn2bin(s, signature + 20 + (20 - s_len)); + BN_bn2bin(r, signature + (SHA_DIGEST_LENGTH - r_len)); + BN_bn2bin(s, signature + SHA_DIGEST_LENGTH + (SHA_DIGEST_LENGTH - s_len)); DSA_SIG_free(sig); @@ -2242,7 +2937,7 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, int _libssh2_ecdsa_sign(LIBSSH2_SESSION * session, libssh2_ecdsa_ctx * ec_ctx, - const unsigned char *hash, unsigned long hash_len, + const unsigned char *hash, size_t hash_len, unsigned char **signature, size_t *signature_len) { int r_len, s_len; @@ -2252,10 +2947,47 @@ _libssh2_ecdsa_sign(LIBSSH2_SESSION * session, libssh2_ecdsa_ctx * ec_ctx, const BIGNUM *pr = NULL, *ps = NULL; unsigned char *temp_buffer = NULL; unsigned char *out_buffer = NULL; + ECDSA_SIG *sig = NULL; - ECDSA_SIG *sig = ECDSA_do_sign(hash, (int) hash_len, ec_ctx); +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ec_ctx, NULL); + const unsigned char *p = NULL; + rc = -1; + + if(!ctx) { + return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "out of memory"); + } + + out_buffer_len = EVP_PKEY_get_size(ec_ctx); + temp_buffer = LIBSSH2_ALLOC(session, out_buffer_len); + if(!temp_buffer) { + goto clean_exit; + } + + rc = EVP_PKEY_sign_init(ctx); + if(rc <= 0) { + rc = -1; + goto clean_exit; + } + + rc = EVP_PKEY_sign(ctx, temp_buffer, &out_buffer_len, hash, hash_len); + if(rc <= 0) { + rc = -1; + goto clean_exit; + } + + rc = 0; + + p = temp_buffer; + sig = d2i_ECDSA_SIG(NULL, &p, (long)out_buffer_len); + OPENSSL_clear_free(temp_buffer, out_buffer_len); +#else + sig = ECDSA_do_sign(hash, (int)hash_len, ec_ctx); if(!sig) return -1; +#endif + #ifdef HAVE_OPAQUE_STRUCTS ECDSA_SIG_get0(sig, &pr, &ps); #else @@ -2297,6 +3029,11 @@ clean_exit: if(sig) ECDSA_SIG_free(sig); +#ifdef USE_OPENSSL_3 + if(ctx) + EVP_PKEY_CTX_free(ctx); +#endif + return rc; } #endif /* LIBSSH2_ECDSA */ @@ -2323,6 +3060,30 @@ _libssh2_sha1_init(libssh2_sha1_ctx *ctx) #endif } +int +_libssh2_sha1_update(libssh2_sha1_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_sha1_final(libssh2_sha1_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} + int _libssh2_sha1(const unsigned char *message, size_t len, unsigned char *out) @@ -2375,6 +3136,30 @@ _libssh2_sha256_init(libssh2_sha256_ctx *ctx) #endif } +int +_libssh2_sha256_update(libssh2_sha256_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_sha256_final(libssh2_sha256_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} + int _libssh2_sha256(const unsigned char *message, size_t len, unsigned char *out) @@ -2427,6 +3212,30 @@ _libssh2_sha384_init(libssh2_sha384_ctx *ctx) #endif } +int +_libssh2_sha384_update(libssh2_sha384_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_sha384_final(libssh2_sha384_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} + int _libssh2_sha384(const unsigned char *message, size_t len, unsigned char *out) @@ -2479,6 +3288,30 @@ _libssh2_sha512_init(libssh2_sha512_ctx *ctx) #endif } +int +_libssh2_sha512_update(libssh2_sha512_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_sha512_final(libssh2_sha512_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} + int _libssh2_sha512(const unsigned char *message, size_t len, unsigned char *out) @@ -2509,6 +3342,7 @@ _libssh2_sha512(const unsigned char *message, size_t len, return 1; /* error */ } +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM int _libssh2_md5_init(libssh2_md5_ctx *ctx) { @@ -2518,8 +3352,7 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx) * So, just return 0 in FIPS mode */ #if OPENSSL_VERSION_NUMBER >= 0x000907000L && \ - defined(OPENSSL_VERSION_MAJOR) && \ - OPENSSL_VERSION_MAJOR < 3 && \ + !defined(USE_OPENSSL_3) && \ !defined(LIBRESSL_VERSION_NUMBER) if(FIPS_mode()) @@ -2545,6 +3378,31 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx) #endif } +int +_libssh2_md5_update(libssh2_md5_ctx *ctx, + const void *data, size_t len) +{ +#ifdef HAVE_OPAQUE_STRUCTS + return EVP_DigestUpdate(*ctx, data, len); +#else + return EVP_DigestUpdate(ctx, data, len); +#endif +} + +int +_libssh2_md5_final(libssh2_md5_ctx *ctx, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + int ret = EVP_DigestFinal(*ctx, out, NULL); + EVP_MD_CTX_free(*ctx); + return ret; +#else + return EVP_DigestFinal(ctx, out, NULL); +#endif +} +#endif + #if LIBSSH2_ECDSA static int @@ -2557,17 +3415,26 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, EVP_PKEY *pk) { int rc = 0; - EC_KEY *ec = NULL; unsigned char *p; unsigned char *method_buf = NULL; unsigned char *key; + size_t method_buf_len = 0; size_t key_len = 0; unsigned char *octal_value = NULL; size_t octal_len; + libssh2_curve_type type; + +#ifdef USE_OPENSSL_3 + _libssh2_debug((session, + LIBSSH2_TRACE_AUTH, + "Computing public key from EC private key envelope")); + + type = _libssh2_ecdsa_get_curve_type(pk); +#else + EC_KEY *ec = NULL; const EC_POINT *public_key; const EC_GROUP *group; - BN_CTX *bn_ctx; - libssh2_curve_type type; + BN_CTX *bn_ctx = NULL; _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -2586,26 +3453,32 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, public_key = EC_KEY_get0_public_key(ec); group = EC_KEY_get0_group(ec); type = _libssh2_ecdsa_get_curve_type(ec); +#endif if(is_sk) - *method_len = 34; + method_buf_len = 34; else - *method_len = 19; + method_buf_len = 19; - method_buf = LIBSSH2_ALLOC(session, *method_len); + method_buf = LIBSSH2_ALLOC(session, method_buf_len); if(!method_buf) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "out of memory"); } - if(is_sk) - memcpy(method_buf, "sk-ecdsa-sha2-nistp256@openssh.com", *method_len); - else if(type == LIBSSH2_EC_CURVE_NISTP256) - memcpy(method_buf, "ecdsa-sha2-nistp256", *method_len); - else if(type == LIBSSH2_EC_CURVE_NISTP384) - memcpy(method_buf, "ecdsa-sha2-nistp384", *method_len); - else if(type == LIBSSH2_EC_CURVE_NISTP521) - memcpy(method_buf, "ecdsa-sha2-nistp521", *method_len); + if(is_sk) { + memcpy(method_buf, "sk-ecdsa-sha2-nistp256@openssh.com", + method_buf_len); + } + else if(type == LIBSSH2_EC_CURVE_NISTP256) { + memcpy(method_buf, "ecdsa-sha2-nistp256", method_buf_len); + } + else if(type == LIBSSH2_EC_CURVE_NISTP384) { + memcpy(method_buf, "ecdsa-sha2-nistp384", method_buf_len); + } + else if(type == LIBSSH2_EC_CURVE_NISTP521) { + memcpy(method_buf, "ecdsa-sha2-nistp521", method_buf_len); + } else { _libssh2_debug((session, LIBSSH2_TRACE_ERROR, @@ -2614,6 +3487,12 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, goto clean_exit; } +#ifdef USE_OPENSSL_3 + octal_len = EC_MAX_POINT_LEN; + octal_value = LIBSSH2_ALLOC(session, octal_len); + EVP_PKEY_get_octet_string_param(pk, OSSL_PKEY_PARAM_PUB_KEY, + octal_value, octal_len, &octal_len); +#else /* get length */ octal_len = EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, @@ -2635,10 +3514,11 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, rc = -1; goto clean_exit; } +#endif - /* Key form is: type_len(4) + type(method_len) + domain_len(4) + domain(8) - + pub_key_len(4) + pub_key(~65). */ - key_len = 4 + *method_len + 4 + 8 + 4 + octal_len; + /* Key form is: type_len(4) + type(method_buf_len) + domain_len(4) + + domain(8) + pub_key_len(4) + pub_key(~65). */ + key_len = 4 + method_buf_len + 4 + 8 + 4 + octal_len; key = LIBSSH2_ALLOC(session, key_len); if(!key) { rc = -1; @@ -2649,7 +3529,7 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, p = key; /* Key type */ - _libssh2_store_str(&p, (const char *)method_buf, *method_len); + _libssh2_store_str(&p, (const char *)method_buf, method_buf_len); /* Name domain */ if(is_sk) { @@ -2662,18 +3542,25 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, /* Public key */ _libssh2_store_str(&p, (const char *)octal_value, octal_len); - *method = method_buf; - *pubkeydata = key; - *pubkeydata_len = key_len; + *method = method_buf; + if(method_len) { + *method_len = method_buf_len; + } + *pubkeydata = key; + if(pubkeydata_len) { + *pubkeydata_len = key_len; + } clean_exit: +#ifndef USE_OPENSSL_3 if(ec) EC_KEY_free(ec); if(bn_ctx) { BN_CTX_free(bn_ctx); } +#endif if(octal_value) free(octal_value); @@ -2700,8 +3587,16 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, int rc = 0; size_t curvelen, exponentlen, pointlen; unsigned char *curve, *exponent, *point_buf; - EC_KEY *ec_key = NULL; + libssh2_ecdsa_ctx *ec_key = NULL; + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *fromdata_ctx = NULL; + OSSL_PARAM params[4]; + const char *n = EC_curve_nid2nist(curve_type); + char *group_name = NULL; +#else BIGNUM *bn_exponent; +#endif _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -2726,6 +3621,43 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, return -1; } +#ifdef USE_OPENSSL_3 + if(!n) + return -1; + + fromdata_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + + if(!fromdata_ctx) + goto fail; + + group_name = OPENSSL_zalloc(strlen(n) + 1); + + if(!group_name) + goto fail; + + memcpy(group_name, n, strlen(n)); + _libssh2_swap_bytes(exponent, (unsigned long)exponentlen); + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + group_name, 0); + + params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, + point_buf, pointlen); + + params[2] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY, exponent, + exponentlen); + + params[3] = OSSL_PARAM_construct_end(); + + if(EVP_PKEY_fromdata_init(fromdata_ctx) <= 0) + goto fail; + + rc = EVP_PKEY_fromdata(fromdata_ctx, &ec_key, EVP_PKEY_KEYPAIR, params); + rc = rc != 1; + + if(group_name) + OPENSSL_clear_free(group_name, strlen(n)); +#else rc = _libssh2_ecdsa_curve_name_with_octal_new(&ec_key, point_buf, pointlen, curve_type); @@ -2746,29 +3678,46 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, BN_bin2bn(exponent, (int) exponentlen, bn_exponent); rc = (EC_KEY_set_private_key(ec_key, bn_exponent) != 1); +#endif if(rc == 0 && ec_key && pubkeydata && method) { +#ifdef USE_OPENSSL_3 + EVP_PKEY *pk = ec_key; +#else EVP_PKEY *pk = EVP_PKEY_new(); EVP_PKEY_set1_EC_KEY(pk, ec_key); +#endif rc = gen_publickey_from_ec_evp(session, method, method_len, pubkeydata, pubkeydata_len, 0, pk); +#ifndef USE_OPENSSL_3 if(pk) EVP_PKEY_free(pk); +#endif } +#ifdef USE_OPENSSL_3 + if(fromdata_ctx) + EVP_PKEY_CTX_free(fromdata_ctx); +#endif + if(ec_ctx) *ec_ctx = ec_key; else - EC_KEY_free(ec_key); + _libssh2_ecdsa_free(ec_key); return rc; fail: +#ifdef USE_OPENSSL_3 + if(fromdata_ctx) + EVP_PKEY_CTX_free(fromdata_ctx); +#endif + if(ec_key) - EC_KEY_free(ec_key); + _libssh2_ecdsa_free(ec_key); return rc; } @@ -2789,7 +3738,7 @@ gen_publickey_from_sk_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, int rc = 0; size_t curvelen, pointlen, key_len, app_len; unsigned char *curve, *point_buf, *p, *key, *app; - EC_KEY *ec_key = NULL; + libssh2_ecdsa_ctx *ec_key = NULL; _libssh2_debug((session, LIBSSH2_TRACE_AUTH, @@ -2848,15 +3797,21 @@ gen_publickey_from_sk_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, } if(rc == 0 && ec_key && pubkeydata && method) { +#ifdef USE_OPENSSL_3 + EVP_PKEY *pk = ec_key; +#else EVP_PKEY *pk = EVP_PKEY_new(); EVP_PKEY_set1_EC_KEY(pk, ec_key); +#endif rc = gen_publickey_from_ec_evp(session, method, method_len, pubkeydata, pubkeydata_len, 1, pk); +#ifndef USE_OPENSSL_3 if(pk) EVP_PKEY_free(pk); +#endif } if(rc == 0 && pubkeydata) { @@ -2891,13 +3846,13 @@ gen_publickey_from_sk_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, if(ec_ctx) *ec_ctx = ec_key; else - EC_KEY_free(ec_key); + _libssh2_ecdsa_free(ec_key); return rc; fail: if(ec_key) - EC_KEY_free(ec_key); + _libssh2_ecdsa_free(ec_key); if(application && *application) { LIBSSH2_FREE(session, (void *)application); @@ -2959,8 +3914,9 @@ _libssh2_ecdsa_new_openssh_private(libssh2_ecdsa_ctx ** ec_ctx, if(rc == 0) { rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type, - decrypted, NULL, 0, - NULL, 0, ec_ctx); + decrypted, + NULL, NULL, + NULL, NULL, ec_ctx); } else { rc = -1; @@ -3020,8 +3976,8 @@ _libssh2_ecdsa_new_openssh_private_sk(libssh2_ecdsa_ctx ** ec_ctx, if(strcmp("sk-ecdsa-sha2-nistp256@openssh.com", (const char *)buf) == 0) { rc = gen_publickey_from_sk_ecdsa_openssh_priv_data(session, decrypted, - NULL, 0, - NULL, 0, + NULL, NULL, + NULL, NULL, flags, application, key_handle, @@ -3045,12 +4001,18 @@ _libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx, { int rc; - pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#endif _libssh2_init_if_needed(); rc = read_private_key_from_file((void **) ec_ctx, read_ec, - filename, passphrase); + filename, passphrase); if(rc) { return _libssh2_ecdsa_new_openssh_private(ec_ctx, session, @@ -3072,12 +4034,18 @@ _libssh2_ecdsa_new_private_sk(libssh2_ecdsa_ctx ** ec_ctx, { int rc; - pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#if defined(USE_OPENSSL_3) + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_PrivateKey; +#else + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; +#endif _libssh2_init_if_needed(); rc = read_private_key_from_file((void **) ec_ctx, read_ec, - filename, passphrase); + filename, passphrase); if(rc) { return _libssh2_ecdsa_new_openssh_private_sk(ec_ctx, @@ -3112,8 +4080,51 @@ _libssh2_ecdsa_create_key(LIBSSH2_SESSION *session, int ret = 1; size_t octal_len = 0; unsigned char octal_value[EC_MAX_POINT_LEN]; + _libssh2_ec_key *private_key = NULL; + +#ifdef USE_OPENSSL_3 + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + + if(ctx && + EVP_PKEY_keygen_init(ctx) > 0 && + EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, curve_type) > 0) { + ret = EVP_PKEY_keygen(ctx, &private_key); + } + + if(ret <= 0) { + goto clean_exit; + } + + if(out_private_key) + *out_private_key = private_key; + + ret = EVP_PKEY_get_octet_string_param(private_key, OSSL_PKEY_PARAM_PUB_KEY, + NULL, 0, &octal_len); + + if(ret <= 0) { + goto clean_exit; + } + + *out_public_key_octal = LIBSSH2_ALLOC(session, octal_len); + + if(!(*out_public_key_octal)) { + ret = -1; + goto clean_exit; + } + + ret = EVP_PKEY_get_octet_string_param(private_key, OSSL_PKEY_PARAM_PUB_KEY, + octal_value, octal_len, &octal_len); + + if(ret <= 0) { + goto clean_exit; + } + + memcpy(*out_public_key_octal, octal_value, octal_len); + + if(out_public_key_octal_len) + *out_public_key_octal_len = octal_len; +#else const EC_POINT *public_key = NULL; - EC_KEY *private_key = NULL; const EC_GROUP *group = NULL; /* create key */ @@ -3158,11 +4169,16 @@ _libssh2_ecdsa_create_key(LIBSSH2_SESSION *session, if(out_public_key_octal_len) *out_public_key_octal_len = octal_len; +#endif /* USE_OPENSSL_3 */ clean_exit: - +#ifdef USE_OPENSSL_3 + if(ctx) + EVP_PKEY_CTX_free(ctx); +#else if(bn_ctx) BN_CTX_free(bn_ctx); +#endif return (ret == 1) ? 0 : -1; } @@ -3175,16 +4191,120 @@ clean_exit: int _libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key, - const unsigned char *server_public_key, size_t server_public_key_len) + const unsigned char *server_public_key, + size_t server_public_key_len) { int ret = 0; - int rc; + BN_CTX *bn_ctx = NULL; + +#ifdef USE_OPENSSL_3 + char *group_name = NULL; + size_t group_name_len = 0; + unsigned char *out_shared_key = NULL; + EVP_PKEY *peer_key = NULL, *server_key = NULL; + EVP_PKEY_CTX *key_fromdata_ctx = NULL; + EVP_PKEY_CTX *server_key_ctx = NULL; + OSSL_PARAM params[3]; + + size_t out_len = 0; + + if(!k || !(*k) || server_public_key_len <= 0) + return -1; + + bn_ctx = BN_CTX_new(); + if(!bn_ctx) + goto clean_exit; + + key_fromdata_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if(!key_fromdata_ctx) + goto clean_exit; + + ret = EVP_PKEY_get_utf8_string_param(private_key, + OSSL_PKEY_PARAM_GROUP_NAME, + NULL, 0, &group_name_len); + + if(ret <= 0) + goto clean_exit; + + group_name_len += 1; + group_name = OPENSSL_zalloc(group_name_len); + + if(!group_name) + goto clean_exit; + + ret = EVP_PKEY_get_utf8_string_param(private_key, + OSSL_PKEY_PARAM_GROUP_NAME, + group_name, group_name_len, + &group_name_len); + + if(ret <= 0) + goto clean_exit; + + out_shared_key = OPENSSL_malloc(server_public_key_len); + + if(!out_shared_key) + goto clean_exit; + + memcpy(out_shared_key, server_public_key, server_public_key_len); + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + group_name, 0); + + params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, + out_shared_key, + server_public_key_len); + + params[2] = OSSL_PARAM_construct_end(); + + ret = EVP_PKEY_fromdata_init(key_fromdata_ctx); + if(ret <= 0) + goto clean_exit; + + ret = EVP_PKEY_fromdata(key_fromdata_ctx, &peer_key, + EVP_PKEY_PUBLIC_KEY, params); + + if(ret <= 0) + goto clean_exit; + + server_key = private_key; + + if(!peer_key || !server_key) { + goto clean_exit; + } + + server_key_ctx = EVP_PKEY_CTX_new(server_key, NULL); + if(!server_key_ctx) { + goto clean_exit; + } + + ret = EVP_PKEY_derive_init(server_key_ctx); + if(ret <= 0) + goto clean_exit; + + ret = EVP_PKEY_derive_set_peer(server_key_ctx, peer_key); + if(ret <= 0) + goto clean_exit; + + ret = EVP_PKEY_derive(server_key_ctx, NULL, &out_len); + if(ret <= 0) + goto clean_exit; + + ret = EVP_PKEY_derive(server_key_ctx, out_shared_key, &out_len); + + if(ret == 1) { + BN_bin2bn(out_shared_key, (int)out_len, *k); + } + else { + ret = -1; + } +#else + int rc = -1; size_t secret_len; unsigned char *secret = NULL; const EC_GROUP *private_key_group; EC_POINT *server_public_key_point; - BN_CTX *bn_ctx = BN_CTX_new(); + bn_ctx = BN_CTX_new(); if(!bn_ctx) return -1; @@ -3221,9 +4341,19 @@ _libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key, } BN_bin2bn(secret, (int) secret_len, *k); +#endif clean_exit: +#ifdef USE_OPENSSL_3 + if(group_name) + OPENSSL_clear_free(group_name, group_name_len); + if(out_shared_key) + OPENSSL_clear_free(out_shared_key, server_public_key_len); + + if(server_key_ctx) + EVP_PKEY_CTX_free(server_key_ctx); +#else if(server_public_key_point) EC_POINT_free(server_public_key_point); @@ -3232,8 +4362,13 @@ clean_exit: if(secret) free(secret); +#endif +#ifdef USE_OPENSSL_3 + return ret == 1 ? 0 : -1; +#else return ret; +#endif } @@ -3527,7 +4662,7 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, "file: Unable to open private key file"); } - BIO_reset(bp); + (void)BIO_reset(bp); pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase); BIO_free(bp); @@ -3669,10 +4804,8 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session, method_len, pubkeydata, pubkeydata_len, - NULL, - NULL, - NULL, - NULL, + NULL, NULL, + NULL, NULL, (libssh2_ed25519_ctx**)key_ctx); } } @@ -3701,16 +4834,15 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session, #endif #if LIBSSH2_ECDSA { - libssh2_curve_type type; + libssh2_curve_type type; if(strcmp("sk-ecdsa-sha2-nistp256@openssh.com", (const char *)buf) == 0) { rc = gen_publickey_from_sk_ecdsa_openssh_priv_data(session, decrypted, method, method_len, pubkeydata, pubkeydata_len, - NULL, NULL, NULL, - NULL, + NULL, NULL, (libssh2_ecdsa_ctx**)key_ctx); } else if(_libssh2_ecdsa_curve_type_from_name((const char *)buf, &type) @@ -3845,19 +4977,6 @@ _libssh2_sk_pub_openssh_keyfilememory(LIBSSH2_SESSION *session, return rc; } -int -read_openssh_private_key_from_memory(void **key_ctx, LIBSSH2_SESSION *session, - const char *key_type, - const char *filedata, - size_t filedata_len, - unsigned const char *passphrase) -{ - return _libssh2_pub_priv_openssh_keyfilememory(session, key_ctx, key_type, - NULL, NULL, NULL, NULL, - filedata, filedata_len, - passphrase); -} - #if OPENSSL_VERSION_NUMBER >= 0x30000000L #define HAVE_SSLERROR_BAD_DECRYPT #endif @@ -3893,7 +5012,7 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory when" "computing public key"); - BIO_reset(bp); + (void)BIO_reset(bp); pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase); #ifdef HAVE_SSLERROR_BAD_DECRYPT sslError = ERR_get_error(); @@ -3937,8 +5056,8 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, switch(pktype) { #if LIBSSH2_ED25519 case EVP_PKEY_ED25519: - st = gen_publickey_from_ed_evp( - session, method, method_len, pubkeydata, pubkeydata_len, pk); + st = gen_publickey_from_ed_evp(session, method, method_len, + pubkeydata, pubkeydata_len, pk); break; #endif /* LIBSSH2_ED25519 */ #if LIBSSH2_RSA @@ -3956,8 +5075,7 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, #if LIBSSH2_ECDSA case EVP_PKEY_EC: st = gen_publickey_from_ec_evp(session, method, method_len, - pubkeydata, pubkeydata_len, - 0, pk); + pubkeydata, pubkeydata_len, 0, pk); break; #endif /* LIBSSH2_ECDSA */ default: @@ -4005,7 +5123,7 @@ _libssh2_sk_pub_keyfilememory(LIBSSH2_SESSION *session, return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory when" "computing public key"); - BIO_reset(bp); + (void)BIO_reset(bp); pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase); BIO_free(bp); @@ -4063,6 +5181,16 @@ _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx) *dhctx = NULL; } +int +_libssh2_bn_from_bin(_libssh2_bn *bn, size_t len, const unsigned char *val) +{ + if(!BN_bin2bn(val, (int)len, bn)) { + return -1; + } + + return 0; +} + /* _libssh2_supported_key_sign_algorithms * * Return supported key hash algo upgrades, see crypto.h @@ -4077,9 +5205,17 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, (void)session; #if LIBSSH2_RSA_SHA2 - if(key_method_len == 7 && - memcmp(key_method, "ssh-rsa", key_method_len) == 0) { - return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; + if((key_method_len == 7 && + memcmp(key_method, "ssh-rsa", key_method_len) == 0) || + (key_method_len == 28 && + memcmp(key_method, "ssh-rsa-cert-v01@openssh.com", + key_method_len) == 0) + ) { + return "rsa-sha2-512,rsa-sha2-256" +#if LIBSSH2_RSA_SHA1 + ",ssh-rsa" +#endif + ; } #endif diff --git a/libssh2/src/openssl.h b/libssh2/src/openssl.h index b7652c0e6..e41c1df47 100644 --- a/libssh2/src/openssl.h +++ b/libssh2/src/openssl.h @@ -1,9 +1,8 @@ -#ifndef __LIBSSH2_OPENSSL_H -#define __LIBSSH2_OPENSSL_H -/* Copyright (C) 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * - * Author: Simon Josefsson +#ifndef LIBSSH2_OPENSSL_H +#define LIBSSH2_OPENSSL_H +/* Copyright (C) Simon Josefsson + * Copyright (C) The Written Word, Inc. + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -37,6 +36,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #define LIBSSH2_CRYPTO_ENGINE libssh2_openssl @@ -47,7 +48,7 @@ #ifdef LIBSSH2_WOLFSSL #include -#include +#include #if defined(NO_DSA) || defined(HAVE_FIPS) #define OPENSSL_NO_DSA @@ -75,7 +76,23 @@ /* wolfSSL has no engine framework. */ #define OPENSSL_NO_ENGINE -#endif /* LIBSSH2_WOLFSSL */ +#include +#include +#include +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_MD5 +#include +#endif +#include +#include +#include +#include +#include +#include + +#else /* !LIBSSH2_WOLFSSL */ #include #include @@ -96,9 +113,17 @@ #include #include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#define USE_OPENSSL_3 1 +#include +#endif + +#endif /* LIBSSH2_WOLFSSL */ + #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER)) || defined(LIBSSH2_WOLFSSL) || \ - LIBRESSL_VERSION_NUMBER >= 0x3050000fL + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER >= 0x3050000fL) /* For wolfSSL, whether the structs are truly opaque or not, it's best to not * rely on their internal data members being exposed publicly. */ # define HAVE_OPAQUE_STRUCTS 1 @@ -160,8 +185,11 @@ # define LIBSSH2_AES_CBC 0 #endif +/* wolfSSL v5.4.0 is required due to possibly this bug: + https://github.com/wolfSSL/wolfssl/pull/5205 + Before this release, all libssh2 tests crash with AES-GCM enabled */ #if (OPENSSL_VERSION_NUMBER >= 0x01010100fL && !defined(OPENSSL_NO_AES)) || \ - (defined(LIBSSH2_WOLFSSL) && \ + (defined(LIBSSH2_WOLFSSL) && LIBWOLFSSL_VERSION_HEX >= 0x05004000 && \ defined(HAVE_AESGCM) && defined(WOLFSSL_AESGCM_STREAM)) # define LIBSSH2_AES_GCM 1 #else @@ -192,6 +220,8 @@ # define LIBSSH2_3DES 1 #endif +#include "crypto_config.h" + #define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) #define _libssh2_random(buf, len) \ @@ -207,19 +237,15 @@ /* returns 0 in case of failure */ int _libssh2_sha1_init(libssh2_sha1_ctx *ctx); -#define libssh2_sha1_init(x) _libssh2_sha1_init(x) -#ifdef HAVE_OPAQUE_STRUCTS -#define libssh2_sha1_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) -#define libssh2_sha1_final(ctx, out) do { \ - EVP_DigestFinal(ctx, out, NULL); \ - EVP_MD_CTX_free(ctx); \ - } while(0) -#else -#define libssh2_sha1_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_sha1_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -#endif +int _libssh2_sha1_update(libssh2_sha1_ctx *ctx, + const void *data, size_t len); +int _libssh2_sha1_final(libssh2_sha1_ctx *ctx, unsigned char *out); int _libssh2_sha1(const unsigned char *message, size_t len, unsigned char *out); +#define libssh2_sha1_init(x) _libssh2_sha1_init(x) +#define libssh2_sha1_update(ctx, data, len) \ + _libssh2_sha1_update(&(ctx), data, len) +#define libssh2_sha1_final(ctx, out) _libssh2_sha1_final(&(ctx), out) #define libssh2_sha1(x,y,z) _libssh2_sha1(x,y,z) #ifdef HAVE_OPAQUE_STRUCTS @@ -230,20 +256,15 @@ int _libssh2_sha1(const unsigned char *message, size_t len, /* returns 0 in case of failure */ int _libssh2_sha256_init(libssh2_sha256_ctx *ctx); -#define libssh2_sha256_init(x) _libssh2_sha256_init(x) -#ifdef HAVE_OPAQUE_STRUCTS -#define libssh2_sha256_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) -#define libssh2_sha256_final(ctx, out) do { \ - EVP_DigestFinal(ctx, out, NULL); \ - EVP_MD_CTX_free(ctx); \ - } while(0) -#else -#define libssh2_sha256_update(ctx, data, len) \ - EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_sha256_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -#endif +int _libssh2_sha256_update(libssh2_sha256_ctx *ctx, + const void *data, size_t len); +int _libssh2_sha256_final(libssh2_sha256_ctx *ctx, unsigned char *out); int _libssh2_sha256(const unsigned char *message, size_t len, unsigned char *out); +#define libssh2_sha256_init(x) _libssh2_sha256_init(x) +#define libssh2_sha256_update(ctx, data, len) \ + _libssh2_sha256_update(&(ctx), data, len) +#define libssh2_sha256_final(ctx, out) _libssh2_sha256_final(&(ctx), out) #define libssh2_sha256(x,y,z) _libssh2_sha256(x,y,z) #ifdef HAVE_OPAQUE_STRUCTS @@ -254,20 +275,15 @@ int _libssh2_sha256(const unsigned char *message, size_t len, /* returns 0 in case of failure */ int _libssh2_sha384_init(libssh2_sha384_ctx *ctx); -#define libssh2_sha384_init(x) _libssh2_sha384_init(x) -#ifdef HAVE_OPAQUE_STRUCTS -#define libssh2_sha384_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) -#define libssh2_sha384_final(ctx, out) do { \ - EVP_DigestFinal(ctx, out, NULL); \ - EVP_MD_CTX_free(ctx); \ - } while(0) -#else -#define libssh2_sha384_update(ctx, data, len) \ - EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_sha384_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -#endif +int _libssh2_sha384_update(libssh2_sha384_ctx *ctx, + const void *data, size_t len); +int _libssh2_sha384_final(libssh2_sha384_ctx *ctx, unsigned char *out); int _libssh2_sha384(const unsigned char *message, size_t len, unsigned char *out); +#define libssh2_sha384_init(x) _libssh2_sha384_init(x) +#define libssh2_sha384_update(ctx, data, len) \ + _libssh2_sha384_update(&(ctx), data, len) +#define libssh2_sha384_final(ctx, out) _libssh2_sha384_final(&(ctx), out) #define libssh2_sha384(x,y,z) _libssh2_sha384(x,y,z) #ifdef HAVE_OPAQUE_STRUCTS @@ -278,22 +294,18 @@ int _libssh2_sha384(const unsigned char *message, size_t len, /* returns 0 in case of failure */ int _libssh2_sha512_init(libssh2_sha512_ctx *ctx); -#define libssh2_sha512_init(x) _libssh2_sha512_init(x) -#ifdef HAVE_OPAQUE_STRUCTS -#define libssh2_sha512_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) -#define libssh2_sha512_final(ctx, out) do { \ - EVP_DigestFinal(ctx, out, NULL); \ - EVP_MD_CTX_free(ctx); \ - } while(0) -#else -#define libssh2_sha512_update(ctx, data, len) \ - EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_sha512_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -#endif +int _libssh2_sha512_update(libssh2_sha512_ctx *ctx, + const void *data, size_t len); +int _libssh2_sha512_final(libssh2_sha512_ctx *ctx, unsigned char *out); int _libssh2_sha512(const unsigned char *message, size_t len, unsigned char *out); +#define libssh2_sha512_init(x) _libssh2_sha512_init(x) +#define libssh2_sha512_update(ctx, data, len) \ + _libssh2_sha512_update(&(ctx), data, len) +#define libssh2_sha512_final(ctx, out) _libssh2_sha512_final(&(ctx), out) #define libssh2_sha512(x,y,z) _libssh2_sha512(x,y,z) +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #ifdef HAVE_OPAQUE_STRUCTS #define libssh2_md5_ctx EVP_MD_CTX * #else @@ -302,62 +314,22 @@ int _libssh2_sha512(const unsigned char *message, size_t len, /* returns 0 in case of failure */ int _libssh2_md5_init(libssh2_md5_ctx *ctx); +int _libssh2_md5_update(libssh2_md5_ctx *ctx, + const void *data, size_t len); +int _libssh2_md5_final(libssh2_md5_ctx *ctx, unsigned char *out); #define libssh2_md5_init(x) _libssh2_md5_init(x) -#ifdef HAVE_OPAQUE_STRUCTS -#define libssh2_md5_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) -#define libssh2_md5_final(ctx, out) do { \ - EVP_DigestFinal(ctx, out, NULL); \ - EVP_MD_CTX_free(ctx); \ - } while(0) -#else -#define libssh2_md5_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_md5_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -#endif +#define libssh2_md5_update(ctx, data, len) \ + _libssh2_md5_update(&(ctx), data, len) +#define libssh2_md5_final(ctx, out) _libssh2_md5_final(&(ctx), out) +#endif /* LIBSSH2_MD5 || LIBSSH2_MD5_PEM */ -#ifdef HAVE_OPAQUE_STRUCTS +#ifdef USE_OPENSSL_3 +#define libssh2_hmac_ctx EVP_MAC_CTX * +#elif defined(HAVE_OPAQUE_STRUCTS) #define libssh2_hmac_ctx HMAC_CTX * -#define libssh2_hmac_ctx_init(ctx) ctx = HMAC_CTX_new() -#define libssh2_hmac_sha1_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_sha1(), NULL) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_md5(), NULL) -#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_ripemd160(), NULL) -#define libssh2_hmac_sha256_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_sha256(), NULL) -#define libssh2_hmac_sha512_init(ctx, key, keylen) \ - HMAC_Init_ex(*(ctx), key, (int)keylen, EVP_sha512(), NULL) - -#ifdef LIBSSH2_WOLFSSL -/* FIXME: upstream bug as of v5.6.0: datalen is int instead of size_t */ -#define libssh2_hmac_update(ctx, data, datalen) \ - HMAC_Update(ctx, data, (int)datalen) -#else -#define libssh2_hmac_update(ctx, data, datalen) \ - HMAC_Update(ctx, data, datalen) -#endif /* LIBSSH2_WOLFSSL */ -#define libssh2_hmac_final(ctx, data) HMAC_Final(ctx, data, NULL) -#define libssh2_hmac_cleanup(ctx) HMAC_CTX_free(*(ctx)) -#else +#else /* !HAVE_OPAQUE_STRUCTS */ #define libssh2_hmac_ctx HMAC_CTX -#define libssh2_hmac_ctx_init(ctx) \ - HMAC_CTX_init(&ctx) -#define libssh2_hmac_sha1_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha1(), NULL) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)keylen, EVP_md5(), NULL) -#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)keylen, EVP_ripemd160(), NULL) -#define libssh2_hmac_sha256_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha256(), NULL) -#define libssh2_hmac_sha512_init(ctx, key, keylen) \ - HMAC_Init_ex(ctx, key, (int)keylen, EVP_sha512(), NULL) - -#define libssh2_hmac_update(ctx, data, datalen) \ - HMAC_Update(&(ctx), data, datalen) -#define libssh2_hmac_final(ctx, data) HMAC_Final(&(ctx), data, NULL) -#define libssh2_hmac_cleanup(ctx) HMAC_cleanup(ctx) -#endif +#endif /* USE_OPENSSL_3 */ extern void _libssh2_openssl_crypto_init(void); extern void _libssh2_openssl_crypto_exit(void); @@ -365,21 +337,40 @@ extern void _libssh2_openssl_crypto_exit(void); #define libssh2_crypto_exit() _libssh2_openssl_crypto_exit() #if LIBSSH2_RSA -#define libssh2_rsa_ctx RSA +#ifdef USE_OPENSSL_3 +#define libssh2_rsa_ctx EVP_PKEY +#define _libssh2_rsa_free(rsactx) EVP_PKEY_free(rsactx) +#else +#define libssh2_rsa_ctx RSA #define _libssh2_rsa_free(rsactx) RSA_free(rsactx) #endif -#if LIBSSH2_DSA -#define libssh2_dsa_ctx DSA +#endif /* LIBSSH2_RSA */ +#if LIBSSH2_DSA + +#ifdef USE_OPENSSL_3 +#define libssh2_dsa_ctx EVP_PKEY +#define _libssh2_dsa_free(rsactx) EVP_PKEY_free(rsactx) +#else +#define libssh2_dsa_ctx DSA #define _libssh2_dsa_free(dsactx) DSA_free(dsactx) #endif +#endif /* LIBSSH2_DSA */ + #if LIBSSH2_ECDSA + +#ifdef USE_OPENSSL_3 +#define libssh2_ecdsa_ctx EVP_PKEY +#define _libssh2_ecdsa_free(ecdsactx) EVP_PKEY_free(ecdsactx) +#define _libssh2_ec_key EVP_PKEY +#else #define libssh2_ecdsa_ctx EC_KEY #define _libssh2_ecdsa_free(ecdsactx) EC_KEY_free(ecdsactx) #define _libssh2_ec_key EC_KEY +#endif typedef enum { LIBSSH2_EC_CURVE_NISTP256 = NID_X9_62_prime256v1, @@ -387,15 +378,14 @@ typedef enum { LIBSSH2_EC_CURVE_NISTP521 = NID_secp521r1 } libssh2_curve_type; -#else +#else /* !LIBSSH2_ECDSA */ #define _libssh2_ec_key void #endif /* LIBSSH2_ECDSA */ #if LIBSSH2_ED25519 #define libssh2_ed25519_ctx EVP_PKEY - #define _libssh2_ed25519_free(ctx) EVP_PKEY_free(ctx) -#endif /* ED25519 */ +#endif /* LIBSSH2_ED25519 */ #define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void) #ifdef HAVE_OPAQUE_STRUCTS @@ -417,6 +407,7 @@ libssh2_curve_type; #define _libssh2_cipher_arcfour EVP_rc4 #define _libssh2_cipher_cast5 EVP_cast5_cbc #define _libssh2_cipher_3des EVP_des_ede3_cbc +#define _libssh2_cipher_chacha20 NULL #ifdef HAVE_OPAQUE_STRUCTS #define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_free(*(ctx)) @@ -430,9 +421,10 @@ libssh2_curve_type; #define _libssh2_bn_ctx_free(bnctx) BN_CTX_free(bnctx) #define _libssh2_bn_init() BN_new() #define _libssh2_bn_init_from_bin() _libssh2_bn_init() -#define _libssh2_bn_set_word(bn, val) BN_set_word(bn, val) -#define _libssh2_bn_from_bin(bn, len, val) BN_bin2bn(val, (int)len, bn) -#define _libssh2_bn_to_bin(bn, val) BN_bn2bin(bn, val) +#define _libssh2_bn_set_word(bn, val) !BN_set_word(bn, val) +extern int _libssh2_bn_from_bin(_libssh2_bn *bn, size_t len, + const unsigned char *v); +#define _libssh2_bn_to_bin(bn, val) (BN_bn2bin(bn, val) <= 0) #define _libssh2_bn_bytes(bn) BN_num_bytes(bn) #define _libssh2_bn_bits(bn) BN_num_bits(bn) #define _libssh2_bn_free(bn) BN_clear_free(bn) @@ -468,4 +460,4 @@ const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void); const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void); const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void); -#endif /* __LIBSSH2_OPENSSL_H */ +#endif /* LIBSSH2_OPENSSL_H */ diff --git a/libssh2/src/os400qc3.c b/libssh2/src/os400qc3.c index ed7e8f6e3..9ec9b0360 100644 --- a/libssh2/src/os400qc3.c +++ b/libssh2/src/os400qc3.c @@ -1,6 +1,5 @@ /* - * Copyright (C) 2015-2016 Patrick Monnerat, D+H - * Copyright (C) 2020-2023 Patrick Monnerat . + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifdef LIBSSH2_CRYPTO_C /* Compile this via crypto.c */ @@ -217,12 +218,14 @@ static const pkcs5algo rc2CBC = { '\0', 0, 0, 0, 8, 0, 32 }; +static int parse_pbes1(LIBSSH2_SESSION *session, pkcs5params *pkcs5, + pkcs5algo *algo, asn1Element *param); + +#if LIBSSH2_MD5 /* pbeWithMD5AndDES-CBC OID: 1.2.840.113549.1.5.3 */ static const unsigned char OID_pbeWithMD5AndDES_CBC[] = { 9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x03 }; -static int parse_pbes1(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param); static const pkcs5algo pbeWithMD5AndDES_CBC = { OID_pbeWithMD5AndDES_CBC, parse_pbes1, Qc3_DES, 8, Qc3_CBC, Qc3_Pad_Counter, '\0', 8, Qc3_MD5, MD5_DIGEST_LENGTH, 8, 0, 0 @@ -236,6 +239,7 @@ static const pkcs5algo pbeWithMD5AndRC2_CBC = { OID_pbeWithMD5AndRC2_CBC, parse_pbes1, Qc3_RC2, 8, Qc3_CBC, Qc3_Pad_Counter, '\0', 0, Qc3_MD5, MD5_DIGEST_LENGTH, 8, 0, 64 }; +#endif /* pbeWithSHA1AndDES-CBC OID: 1.2.840.113549.1.5.10 */ static const unsigned char OID_pbeWithSHA1AndDES_CBC[] = { @@ -260,8 +264,10 @@ static const pkcs5algo pbeWithSHA1AndRC2_CBC = { /* pbeWithMD2AndRC2-CBC OID: 1.2.840.113549.1.5.4: MD2 not implemented. */ static const pkcs5algo * pbestable[] = { +#if LIBSSH2_MD5 &pbeWithMD5AndDES_CBC, &pbeWithMD5AndRC2_CBC, +#endif &pbeWithSHA1AndDES_CBC, &pbeWithSHA1AndRC2_CBC, &PBES2, @@ -361,7 +367,7 @@ _libssh2_random(unsigned char *buf, size_t len) set_EC_length(errcode, sizeof(errcode)); Qc3GenPRNs(buf, len, Qc3PRN_TYPE_NORMAL, Qc3PRN_NO_PARITY, (char *) &errcode); - return errcode.Bytes_Available? -1: 0; + return errcode.Bytes_Available ? -1 : 0; } _libssh2_bn * @@ -452,9 +458,9 @@ _libssh2_bn_bits(_libssh2_bn *bn) } int -_libssh2_bn_from_bin(_libssh2_bn *bn, int len, const unsigned char *val) +_libssh2_bn_from_bin(_libssh2_bn *bn, size_t len, const unsigned char *val) { - int i; + size_t i; if(!bn || (len && !val)) return -1; @@ -633,11 +639,11 @@ static asn1Element * asn1_new_from_bytes(const unsigned char *data, unsigned int length) { asn1Element *e; - asn1Element te; + asn1Element et; - getASN1Element(&te, + getASN1Element(&et, (unsigned char *) data, (unsigned char *) data + length); - e = asn1_new(te.tag, te.end - te.beg); + e = asn1_new(et.tag, et.end - et.beg); if(e) memcpy(e->header, data, e->end - e->header); @@ -947,7 +953,7 @@ _libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x) *******************************************************************/ int -libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, unsigned int algorithm) +_libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, unsigned int algorithm) { Qc3_Format_ALGD0500_T algd; Qus_EC_t errcode; @@ -961,91 +967,150 @@ libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, unsigned int algorithm) set_EC_length(errcode, sizeof(errcode)); Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Hash, x->Alg_Context_Token, &errcode); - return errcode.Bytes_Available? 0: 1; -} - -void -libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx, - const unsigned char *data, int len) -{ - char dummy[64]; - - ctx->Final_Op_Flag = Qc3_Continue; - Qc3CalculateHash((char *) data, &len, Qc3_Data, (char *) ctx, - Qc3_Alg_Token, anycsp, NULL, dummy, (char *) &ecnull); -} - -void -libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx, unsigned char *out) -{ - char data; - - ctx->Final_Op_Flag = Qc3_Final; - Qc3CalculateHash(&data, &zero, Qc3_Data, (char *) ctx, Qc3_Alg_Token, - anycsp, NULL, (char *) out, (char *) &ecnull); - Qc3DestroyAlgorithmContext(ctx->Alg_Context_Token, (char *) &ecnull); - memset(ctx->Alg_Context_Token, 0, sizeof(ctx->Alg_Context_Token)); + return errcode.Bytes_Available ? 0 : 1; } int -libssh2_os400qc3_hash(const unsigned char *message, unsigned long len, - unsigned char *out, unsigned int algo) +_libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx, + const unsigned char *data, int len) +{ + char dummy[64]; + Qus_EC_t errcode; + + ctx->Final_Op_Flag = Qc3_Continue; + set_EC_length(errcode, sizeof(errcode)); + Qc3CalculateHash((char *) data, &len, Qc3_Data, (char *) ctx, + Qc3_Alg_Token, anycsp, NULL, dummy, &errcode); + return errcode.Bytes_Available ? 0 : 1; +} + +int +_libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx, unsigned char *out) +{ + char data; + Qus_EC_t errcode; + + ctx->Final_Op_Flag = Qc3_Final; + set_EC_length(errcode, sizeof(errcode)); + Qc3CalculateHash(&data, &zero, Qc3_Data, (char *) ctx, Qc3_Alg_Token, + anycsp, NULL, (char *) out, &errcode); + Qc3DestroyAlgorithmContext(ctx->Alg_Context_Token, (char *) &ecnull); + memset(ctx->Alg_Context_Token, 0, sizeof(ctx->Alg_Context_Token)); + return errcode.Bytes_Available ? 0 : 1; +} + +int +_libssh2_os400qc3_hash(const unsigned char *message, unsigned long len, + unsigned char *out, unsigned int algo) { Qc3_Format_ALGD0100_T ctx; - if(!libssh2_os400qc3_hash_init(&ctx, algo)) + if(!_libssh2_os400qc3_hash_init(&ctx, algo) || + !_libssh2_os400qc3_hash_update(&ctx, message, len) || + !_libssh2_os400qc3_hash_final(&ctx, out)) return 1; - libssh2_os400qc3_hash_update(&ctx, message, len); - libssh2_os400qc3_hash_final(&ctx, out); return 0; } -void +static int libssh2_os400qc3_hmac_init(_libssh2_os400qc3_crypto_ctx *ctx, int algo, size_t minkeylen, void *key, int keylen) { + Qus_EC_t errcode; + if(keylen < minkeylen) { char *lkey = alloca(minkeylen); /* Pad key with zeroes if too short. */ if(!lkey) - return; + return 0; memcpy(lkey, (char *) key, keylen); memset(lkey + keylen, 0, minkeylen - keylen); key = (void *) lkey; keylen = minkeylen; } - libssh2_os400qc3_hash_init(&ctx->hash, algo); + if(!_libssh2_os400qc3_hash_init(&ctx->hash, algo)) + return 0; + set_EC_length(errcode, sizeof(errcode)); Qc3CreateKeyContext((char *) key, &keylen, binstring, &algo, qc3clear, NULL, NULL, ctx->key.Key_Context_Token, - (char *) &ecnull); + (char *) &errcode); + return errcode.Bytes_Available ? 0 : 1; } -void -libssh2_os400qc3_hmac_update(_libssh2_os400qc3_crypto_ctx *ctx, - unsigned char *data, int len) +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx) +{ + memset((char *) ctx, 0, sizeof(libssh2_hmac_ctx)); + return 1; +} + +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return libssh2_os400qc3_hmac_init(ctx, Qc3_MD5, \ + MD5_DIGEST_LENGTH, \ + key, keylen); +} +#endif + +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return libssh2_os400qc3_hmac_init(ctx, Qc3_SHA1, \ + SHA_DIGEST_LENGTH, \ + key, keylen); +} + +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return libssh2_os400qc3_hmac_init(ctx, Qc3_SHA256, \ + SHA256_DIGEST_LENGTH, \ + key, keylen); +} + +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + return libssh2_os400qc3_hmac_init(ctx, Qc3_SHA512, \ + SHA512_DIGEST_LENGTH, \ + key, keylen); +} + +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen) { char dummy[64]; + int len = (int) datalen; + Qus_EC_t errcode; ctx->hash.Final_Op_Flag = Qc3_Continue; + set_EC_length(errcode, sizeof(errcode)); Qc3CalculateHMAC((char *) data, &len, Qc3_Data, (char *) &ctx->hash, Qc3_Alg_Token, ctx->key.Key_Context_Token, Qc3_Key_Token, - anycsp, NULL, dummy, (char *) &ecnull); + anycsp, NULL, dummy, (char *) &errcode); + return errcode.Bytes_Available ? 0 : 1; } -void -libssh2_os400qc3_hmac_final(_libssh2_os400qc3_crypto_ctx *ctx, - unsigned char *out) +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *out) { char data; + Qus_EC_t errcode; ctx->hash.Final_Op_Flag = Qc3_Final; + set_EC_length(errcode, sizeof(errcode)); Qc3CalculateHMAC((char *) data, &zero, Qc3_Data, (char *) &ctx->hash, Qc3_Alg_Token, ctx->key.Key_Context_Token, Qc3_Key_Token, - anycsp, NULL, (char *) out, (char *) &ecnull); + anycsp, NULL, (char *) out, (char *) &errcode); + return errcode.Bytes_Available ? 0 : 1; } +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx) +{ + _libssh2_os400qc3_crypto_dtor(ctx); +} /******************************************************************* * @@ -1117,7 +1182,7 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx, ctx->key.Key_Context_Token, Qc3_Key_Token, anycsp, NULL, (char *) block, &blksize, &outlen, (char *) &errcode); - return errcode.Bytes_Available? -1: 0; + return errcode.Bytes_Available ? -1 : 0; } @@ -1366,6 +1431,7 @@ pbkdf1(LIBSSH2_SESSION *session, char **dk, const unsigned char *passphrase, Qc3_Format_ALGD0100_T hctx; int len = pkcs5->saltlen; char *data = (char *) pkcs5->salt; + Qus_EC_t errcode; *dk = NULL; if(pkcs5->dklen > pkcs5->hashlen) @@ -1376,18 +1442,34 @@ pbkdf1(LIBSSH2_SESSION *session, char **dk, const unsigned char *passphrase, if(!*dk) return -1; - /* Initial hash. */ - libssh2_os400qc3_hash_init(&hctx, pkcs5->hash); - libssh2_os400qc3_hash_update(&hctx, passphrase, strlen(passphrase)); - hctx.Final_Op_Flag = Qc3_Final; - Qc3CalculateHash((char *) pkcs5->salt, &len, Qc3_Data, (char *) &hctx, - Qc3_Alg_Token, anycsp, NULL, *dk, (char *) &ecnull); + set_EC_length(errcode, sizeof(errcode)); + errcode.Bytes_Available = 1; /* Defaults to error flagging. */ - /* Iterate. */ - len = pkcs5->hashlen; - for(i = 1; i < pkcs5->itercount; i++) - Qc3CalculateHash((char *) *dk, &len, Qc3_Data, (char *) &hctx, - Qc3_Alg_Token, anycsp, NULL, *dk, (char *) &ecnull); + /* Initial hash. */ + if(_libssh2_os400qc3_hash_init(&hctx, pkcs5->hash)) { + if(_libssh2_os400qc3_hash_update(&hctx, + passphrase, strlen(passphrase))) { + hctx.Final_Op_Flag = Qc3_Final; + Qc3CalculateHash((char *) pkcs5->salt, &len, Qc3_Data, + (char *) &hctx, Qc3_Alg_Token, anycsp, NULL, *dk, + (char *) &errcode); + + /* Iterate. */ + len = pkcs5->hashlen; + for(i = 1; !errcode.Bytes_Available && i < pkcs5->itercount; i++) + Qc3CalculateHash((char *) *dk, &len, Qc3_Data, (char *) &hctx, + Qc3_Alg_Token, anycsp, NULL, *dk, + (char *) &errcode); + } + + Qc3DestroyAlgorithmContext(hctx.Alg_Context_Token, (char *) &ecnull); + } + + if(errcode.Bytes_Available) { + LIBSSH2_FREE(session, *dk); + *dk = NULL; + return -1; + } /* Special stuff for PBES1: split derived key into 8-byte key and 8-byte initialization vector. */ @@ -1395,8 +1477,6 @@ pbkdf1(LIBSSH2_SESSION *session, char **dk, const unsigned char *passphrase, pkcs5->ivlen = 8; pkcs5->iv = *dk + 8; - /* Clean-up and exit. */ - Qc3DestroyAlgorithmContext(hctx.Alg_Context_Token, (char *) &ecnull); return 0; } @@ -1423,6 +1503,11 @@ pbkdf2(LIBSSH2_SESSION *session, char **dk, const unsigned char *passphrase, if(!mac) return -1; + /* Create an HMAC context for our computations. */ + if(!libssh2_os400qc3_hmac_init(&hctx, pkcs5->hash, pkcs5->hashlen, + (void *) passphrase, strlen(passphrase))) + return -1; + /* Allocate the derived key buffer. */ l = t; buf = LIBSSH2_ALLOC(session, l * pkcs5->hashlen); @@ -1430,20 +1515,26 @@ pbkdf2(LIBSSH2_SESSION *session, char **dk, const unsigned char *passphrase, return -1; *dk = buf; - /* Create an HMAC context for our computations. */ - libssh2_os400qc3_hmac_init(&hctx, pkcs5->hash, pkcs5->hashlen, - (void *) passphrase, strlen(passphrase)); - /* Process each hLen-size blocks. */ for(i = 1; i <= l; i++) { ni = htonl(i); - libssh2_os400qc3_hmac_update(&hctx, pkcs5->salt, pkcs5->saltlen); - libssh2_os400qc3_hmac_update(&hctx, (char *) &ni, sizeof(ni)); - libssh2_os400qc3_hmac_final(&hctx, mac); + if(!_libssh2_hmac_update(&hctx, pkcs5->salt, pkcs5->saltlen) || + !_libssh2_hmac_update(&hctx, &ni, sizeof(ni)) || + !_libssh2_hmac_final(&hctx, mac)) { + LIBSSH2_FREE(session, buf); + *dk = NULL; + _libssh2_os400qc3_crypto_dtor(&hctx); + return -1; + } memcpy(buf, mac, pkcs5->hashlen); for(j = 1; j < pkcs5->itercount; j++) { - libssh2_os400qc3_hmac_update(&hctx, mac, pkcs5->hashlen); - libssh2_os400qc3_hmac_final(&hctx, mac); + if(!_libssh2_hmac_update(&hctx, mac, pkcs5->hashlen) || + !_libssh2_hmac_final(&hctx, mac)) { + LIBSSH2_FREE(session, buf); + *dk = NULL; + _libssh2_os400qc3_crypto_dtor(&hctx); + return -1; + } for(k = 0; k < pkcs5->hashlen; k++) buf[k] ^= mac[k]; } @@ -1474,7 +1565,7 @@ parse_pkcs5_algorithm(LIBSSH2_SESSION *session, pkcs5params *pkcs5, for(; *algotable; algotable++) if(!oidcmp(&oid, (*algotable)->oid)) return (*(*algotable)->parse)(session, pkcs5, *algotable, - param.header? ¶m: NULL); + param.header ? ¶m : NULL); return -1; } @@ -2365,7 +2456,7 @@ _libssh2_rsa_sha2_verify(libssh2_rsa_ctx *rsa, size_t hash_len, (char *) &algd, Qc3_Alg_Public_Key, (char *) &rsa->key, Qc3_Key_Token, anycsp, NULL, (char *) &errcode); - return errcode.Bytes_Available? -1: 0; + return errcode.Bytes_Available ? -1 : 0; } int @@ -2429,7 +2520,11 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, if(key_method_len == 7 && memcmp(key_method, "ssh-rsa", key_method_len) == 0) { - return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; + return "rsa-sha2-512,rsa-sha2-256" +#if LIBSSH2_RSA_SHA1 + ",ssh-rsa" +#endif + ; } return NULL; diff --git a/libssh2/src/os400qc3.h b/libssh2/src/os400qc3.h index 5d1ba48a0..8c4096b51 100644 --- a/libssh2/src/os400qc3.h +++ b/libssh2/src/os400qc3.h @@ -1,8 +1,7 @@ -#ifndef __LIBSSH2_OS400QC3_H -#define __LIBSSH2_OS400QC3_H +#ifndef LIBSSH2_OS400QC3_H +#define LIBSSH2_OS400QC3_H /* - * Copyright (C) 2015-2016 Patrick Monnerat, D+H - * Copyright (C) 2020-2023 Patrick Monnerat . + * Copyright (C) Patrick Monnerat * All rights reserved. * * Redistribution and use in source and binary forms, @@ -37,6 +36,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #define LIBSSH2_CRYPTO_ENGINE libssh2_os400qc3 @@ -162,9 +163,13 @@ #undef Qc3_MK_Pending #define Qc3_MK_Pending '\xF3' /* '3' */ - /* Define which features are supported. */ -#define LIBSSH2_MD5 1 +#ifdef OPENSSL_NO_MD5 +# define LIBSSH2_MD5 0 +#else +# define LIBSSH2_MD5 1 +#endif + #define LIBSSH2_HMAC_RIPEMD 0 #define LIBSSH2_HMAC_SHA256 1 #define LIBSSH2_HMAC_SHA512 1 @@ -184,7 +189,8 @@ #define LIBSSH2_ECDSA 0 #define LIBSSH2_ED25519 0 -#define MD5_DIGEST_LENGTH 16 +#include "crypto_config.h" + #define SHA_DIGEST_LENGTH 20 #define SHA256_DIGEST_LENGTH 32 #define SHA384_DIGEST_LENGTH 48 @@ -241,71 +247,48 @@ typedef struct { /* Diffie-Hellman context. */ #define libssh2_sha256_ctx Qc3_Format_ALGD0100_T #define libssh2_sha384_ctx Qc3_Format_ALGD0100_T #define libssh2_sha512_ctx Qc3_Format_ALGD0100_T -#define libssh2_md5_ctx Qc3_Format_ALGD0100_T #define libssh2_hmac_ctx _libssh2_os400qc3_crypto_ctx #define _libssh2_cipher_ctx _libssh2_os400qc3_crypto_ctx -#define libssh2_sha1_init(x) libssh2_os400qc3_hash_init(x, Qc3_SHA1) +#define libssh2_sha1_init(x) _libssh2_os400qc3_hash_init(x, Qc3_SHA1) #define libssh2_sha1_update(ctx, data, len) \ - libssh2_os400qc3_hash_update(&(ctx), data, len) + _libssh2_os400qc3_hash_update(&(ctx), data, len) #define libssh2_sha1_final(ctx, out) \ - libssh2_os400qc3_hash_final(&(ctx), out) -#define libssh2_sha256_init(x) libssh2_os400qc3_hash_init(x, Qc3_SHA256) + _libssh2_os400qc3_hash_final(&(ctx), out) +#define libssh2_sha256_init(x) _libssh2_os400qc3_hash_init(x, Qc3_SHA256) #define libssh2_sha256_update(ctx, data, len) \ - libssh2_os400qc3_hash_update(&(ctx), data, len) + _libssh2_os400qc3_hash_update(&(ctx), data, len) #define libssh2_sha256_final(ctx, out) \ - libssh2_os400qc3_hash_final(&(ctx), out) + _libssh2_os400qc3_hash_final(&(ctx), out) #define libssh2_sha256(message, len, out) \ - libssh2_os400qc3_hash(message, len, out, \ - Qc3_SHA256) -#define libssh2_sha384_init(x) libssh2_os400qc3_hash_init(x, Qc3_SHA384) + _libssh2_os400qc3_hash(message, len, out, \ + Qc3_SHA256) +#define libssh2_sha384_init(x) _libssh2_os400qc3_hash_init(x, Qc3_SHA384) #define libssh2_sha384_update(ctx, data, len) \ - libssh2_os400qc3_hash_update(&(ctx), data, len) + _libssh2_os400qc3_hash_update(&(ctx), data, len) #define libssh2_sha384_final(ctx, out) \ - libssh2_os400qc3_hash_final(&(ctx), out) + _libssh2_os400qc3_hash_final(&(ctx), out) #define libssh2_sha384(message, len, out) \ - libssh2_os400qc3_hash(message, len, out, \ - Qc3_SHA384) -#define libssh2_sha512_init(x) libssh2_os400qc3_hash_init(x, Qc3_SHA512) + _libssh2_os400qc3_hash(message, len, out, \ + Qc3_SHA384) +#define libssh2_sha512_init(x) _libssh2_os400qc3_hash_init(x, Qc3_SHA512) #define libssh2_sha512_update(ctx, data, len) \ - libssh2_os400qc3_hash_update(&(ctx), data, len) + _libssh2_os400qc3_hash_update(&(ctx), data, len) #define libssh2_sha512_final(ctx, out) \ - libssh2_os400qc3_hash_final(&(ctx), out) + _libssh2_os400qc3_hash_final(&(ctx), out) #define libssh2_sha512(message, len, out) \ - libssh2_os400qc3_hash(message, len, out, \ - Qc3_SHA512) -#define libssh2_md5_init(x) libssh2_os400qc3_hash_init(x, Qc3_MD5) -#define libssh2_md5_update(ctx, data, len) \ - libssh2_os400qc3_hash_update(&(ctx), data, len) -#define libssh2_md5_final(ctx, out) \ - libssh2_os400qc3_hash_final(&(ctx), out) -#define libssh2_hmac_ctx_init(ctx) \ - memset((char *) &(ctx), 0, \ - sizeof(libssh2_hmac_ctx)) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - libssh2_os400qc3_hmac_init(ctx, Qc3_MD5, \ - MD5_DIGEST_LENGTH, \ - key, keylen) -#define libssh2_hmac_sha1_init(ctx, key, keylen) \ - libssh2_os400qc3_hmac_init(ctx, Qc3_SHA1, \ - SHA_DIGEST_LENGTH, \ - key, keylen) -#define libssh2_hmac_sha256_init(ctx, key, keylen) \ - libssh2_os400qc3_hmac_init(ctx, Qc3_SHA256, \ - SHA256_DIGEST_LENGTH, \ - key, keylen) -#define libssh2_hmac_sha512_init(ctx, key, keylen) \ - libssh2_os400qc3_hmac_init(ctx, Qc3_SHA512, \ - SHA512_DIGEST_LENGTH, \ - key, keylen) -#define libssh2_hmac_update(ctx, data, datalen) \ - libssh2_os400qc3_hmac_update(&(ctx), \ - data, datalen) -#define libssh2_hmac_final(ctx, data) \ - libssh2_os400qc3_hmac_final(&(ctx), data) -#define libssh2_hmac_cleanup(ctx) \ - _libssh2_os400qc3_crypto_dtor(ctx) + _libssh2_os400qc3_hash(message, len, out, \ + Qc3_SHA512) +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM +#define MD5_DIGEST_LENGTH 16 +#define libssh2_md5_ctx Qc3_Format_ALGD0100_T +#define libssh2_md5_init(x) _libssh2_os400qc3_hash_init(x, Qc3_MD5) +#define libssh2_md5_update(ctx, data, len) \ + _libssh2_os400qc3_hash_update(&(ctx), data, len) +#define libssh2_md5_final(ctx, out) \ + _libssh2_os400qc3_hash_final(&(ctx), out) +#endif #define _libssh2_bn_ctx int /* Not used. */ @@ -330,6 +313,8 @@ typedef struct { /* Diffie-Hellman context. */ Qc3_CTR, 32} #define _libssh2_cipher_3des {Qc3_Alg_Block_Cipher, Qc3_TDES, 8, \ Qc3_CBC, 24} +/* Nonsense values for chacha20-poly1305 */ +#define _libssh2_cipher_chacha20 {Qc3_Alg_Stream_Cipher, Qc3_RC4, 8, 0, 16} #define _libssh2_cipher_arcfour {Qc3_Alg_Stream_Cipher, Qc3_RC4, 8, 0, 16} #define _libssh2_cipher_dtor(ctx) _libssh2_os400qc3_crypto_dtor(ctx) @@ -375,30 +360,22 @@ typedef struct { /* Diffie-Hellman context. */ extern _libssh2_bn * _libssh2_bn_init(void); extern void _libssh2_bn_free(_libssh2_bn *bn); extern unsigned long _libssh2_bn_bits(_libssh2_bn *bn); -extern int _libssh2_bn_from_bin(_libssh2_bn *bn, int len, +extern int _libssh2_bn_from_bin(_libssh2_bn *bn, size_t len, const unsigned char *v); extern int _libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val); extern int _libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val); extern int _libssh2_random(unsigned char *buf, size_t len); extern void _libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x); -extern int libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, - unsigned int algo); -extern void libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx, - const unsigned char *data, - int len); -extern void libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx, - unsigned char *out); -extern int libssh2_os400qc3_hash(const unsigned char *message, - unsigned long len, unsigned char *out, - unsigned int algo); -extern void libssh2_os400qc3_hmac_init(_libssh2_os400qc3_crypto_ctx *x, - int algo, size_t minkeylen, - void *key, int keylen); -extern void libssh2_os400qc3_hmac_update(_libssh2_os400qc3_crypto_ctx *ctx, - const unsigned char *data, - int len); -extern void libssh2_os400qc3_hmac_final(_libssh2_os400qc3_crypto_ctx *ctx, - unsigned char *out); +extern int _libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, + unsigned int algo); +extern int _libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx, + const unsigned char *data, + int len); +extern int _libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx, + unsigned char *out); +extern int _libssh2_os400qc3_hash(const unsigned char *message, + unsigned long len, unsigned char *out, + unsigned int algo); extern int _libssh2_os400qc3_rsa_signv(LIBSSH2_SESSION *session, int algo, unsigned char **signature, size_t *signature_len, @@ -415,6 +392,6 @@ extern int _libssh2_os400qc3_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *f, _libssh2_bn *p); extern void _libssh2_os400qc3_dh_dtor(_libssh2_dh_ctx *dhctx); -#endif /* __LIBSSH2_OS400QC3_H */ +#endif /* LIBSSH2_OS400QC3_H */ /* vim: set expandtab ts=4 sw=4: */ diff --git a/libssh2/src/packet.c b/libssh2/src/packet.c index b5b41981a..6da14e9fa 100644 --- a/libssh2/src/packet.c +++ b/libssh2/src/packet.c @@ -1,7 +1,7 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2005,2006 Mikhail Gusarov - * Copyright (c) 2009-2014 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson +/* Copyright (C) Sara Golemon + * Copyright (C) Mikhail Gusarov + * Copyright (C) Daniel Stenberg + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -36,6 +36,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -69,14 +71,14 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, * Look for a matching listener */ /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - size_t packet_len = 17 + (sizeof(FwdNotReq) - 1); + size_t packet_len = 17 + strlen(FwdNotReq); unsigned char *p; LIBSSH2_LISTENER *listn = _libssh2_list_first(&session->listeners); char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; int rc; if(listen_state->state == libssh2_NB_state_idle) { - size_t offset = (sizeof("forwarded-tcpip") - 1) + 5; + size_t offset = strlen("forwarded-tcpip") + 5; size_t temp_len = 0; struct string_buf buf; buf.data = data; @@ -124,7 +126,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Remote received connection from %s:%ld to %s:%ld", + "Remote received connection from %s:%u to %s:%u", listen_state->shost, listen_state->sport, listen_state->host, listen_state->port)); @@ -135,8 +137,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, while(listn) { if((listn->port == (int) listen_state->port) && (strlen(listn->host) == listen_state->host_len) && - (memcmp (listn->host, listen_state->host, - listen_state->host_len) == 0)) { + (memcmp(listn->host, listen_state->host, + listen_state->host_len) == 0)) { /* This is our listener */ LIBSSH2_CHANNEL *channel = NULL; listen_state->channel = NULL; @@ -164,7 +166,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, listen_state->channel = channel; channel->session = session; - channel->channel_type_len = sizeof("forwarded-tcpip") - 1; + channel->channel_type_len = strlen("forwarded-tcpip"); channel->channel_type = LIBSSH2_ALLOC(session, channel-> channel_type_len + @@ -197,8 +199,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, channel->local.packet_size = listen_state->packet_size; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Connection queued: channel %lu/%lu " - "win %lu/%lu packet %lu/%lu", + "Connection queued: channel %u/%u " + "win %u/%u packet %u/%u", channel->local.id, channel->remote.id, channel->local.window_size, channel->remote.window_size, @@ -251,7 +253,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; _libssh2_store_u32(&p, listen_state->sender_channel); _libssh2_store_u32(&p, failure_code); - _libssh2_store_str(&p, FwdNotReq, sizeof(FwdNotReq) - 1); + _libssh2_store_str(&p, FwdNotReq, strlen(FwdNotReq)); _libssh2_htonu32(p, 0); rc = _libssh2_transport_send(session, listen_state->packet, @@ -280,14 +282,14 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, { int failure_code = SSH_OPEN_CONNECT_FAILED; /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - size_t packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); + size_t packet_len = 17 + strlen(X11FwdUnAvil); unsigned char *p; LIBSSH2_CHANNEL *channel = x11open_state->channel; int rc; if(x11open_state->state == libssh2_NB_state_idle) { - size_t offset = (sizeof("x11") - 1) + 5; + size_t offset = strlen("x11") + 5; size_t temp_len = 0; struct string_buf buf; buf.data = data; @@ -337,7 +339,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "X11 Connection Received from %s:%ld on channel %lu", + "X11 Connection Received from %s:%u on channel %u", x11open_state->shost, x11open_state->sport, x11open_state->sender_channel)); @@ -355,7 +357,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, } channel->session = session; - channel->channel_type_len = sizeof("x11") - 1; + channel->channel_type_len = strlen("x11"); channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1); @@ -382,8 +384,8 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, channel->local.packet_size = x11open_state->packet_size; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "X11 Connection established: channel %lu/%lu " - "win %lu/%lu packet %lu/%lu", + "X11 Connection established: channel %u/%u " + "win %u/%u packet %u/%u", channel->local.id, channel->remote.id, channel->local.window_size, channel->remote.window_size, @@ -434,7 +436,7 @@ x11_exit: *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; _libssh2_store_u32(&p, x11open_state->sender_channel); _libssh2_store_u32(&p, failure_code); - _libssh2_store_str(&p, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1); + _libssh2_store_str(&p, X11FwdUnAvil, strlen(X11FwdUnAvil)); _libssh2_htonu32(p, 0); rc = _libssh2_transport_send(session, x11open_state->packet, packet_len, @@ -462,23 +464,40 @@ packet_authagent_open(LIBSSH2_SESSION * session, { int failure_code = SSH_OPEN_CONNECT_FAILED; /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */ - size_t packet_len = 17 + (sizeof(X11FwdUnAvil) - 1); + size_t packet_len = 17 + strlen(X11FwdUnAvil); unsigned char *p; LIBSSH2_CHANNEL *channel = authagent_state->channel; int rc; + struct string_buf buf; + size_t offset = strlen("auth-agent@openssh.org") + 5; - (void)datalen; + buf.data = data; + buf.dataptr = buf.data; + buf.len = datalen; + + buf.dataptr += offset; + + if(datalen < offset) { + return _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Unexpected packet size"); + } if(authagent_state->state == libssh2_NB_state_idle) { - unsigned char *s = data + (sizeof("auth-agent@openssh.org") - 1) + 5; - authagent_state->sender_channel = _libssh2_ntohu32(s); - s += 4; - authagent_state->initial_window_size = _libssh2_ntohu32(s); - s += 4; - authagent_state->packet_size = _libssh2_ntohu32(s); + if(_libssh2_get_u32(&buf, &(authagent_state->sender_channel))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting channel"); + } + if(_libssh2_get_u32(&buf, &(authagent_state->initial_window_size))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting window size"); + } + if(_libssh2_get_u32(&buf, &(authagent_state->packet_size))) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting packet"); + } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Auth Agent Connection Received on channel %lu", + "Auth Agent Connection Received on channel %u", authagent_state->sender_channel)); authagent_state->state = libssh2_NB_state_allocated; @@ -498,7 +517,7 @@ packet_authagent_open(LIBSSH2_SESSION * session, memset(channel, 0, sizeof(LIBSSH2_CHANNEL)); channel->session = session; - channel->channel_type_len = sizeof("auth agent") - 1; + channel->channel_type_len = strlen("auth agent"); channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1); @@ -526,7 +545,7 @@ packet_authagent_open(LIBSSH2_SESSION * session, _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Auth Agent Connection established: channel " - "%lu/%lu win %lu/%lu packet %lu/%lu", + "%u/%u win %u/%u packet %u/%u", channel->local.id, channel->remote.id, channel->local.window_size, channel->remote.window_size, @@ -582,7 +601,7 @@ authagent_exit: *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; _libssh2_store_u32(&p, authagent_state->sender_channel); _libssh2_store_u32(&p, failure_code); - _libssh2_store_str(&p, AuthAgentUnavail, sizeof(AuthAgentUnavail) - 1); + _libssh2_store_str(&p, AuthAgentUnavail, strlen(AuthAgentUnavail)); _libssh2_htonu32(p, 0); rc = _libssh2_transport_send(session, authagent_state->packet, packet_len, @@ -605,14 +624,13 @@ authagent_exit: * layer when it has received a packet. * * The input pointer 'data' is pointing to allocated data that this function - * is asked to deal with so on failure OR success, it must be freed fine. - * The only exception is when the return code is LIBSSH2_ERROR_EAGAIN. + * will be freed unless return the code is LIBSSH2_ERROR_EAGAIN. * * This function will always be called with 'datalen' greater than zero. */ int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - size_t datalen, int macstate) + size_t datalen, int macstate, uint32_t seq) { int rc = 0; unsigned char *message = NULL; @@ -626,8 +644,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, switch(session->packAdd_state) { case libssh2_NB_state_idle: _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "Packet type %d received, length=%d", - (int) msg, (int) datalen)); + "Packet type %u received, length=%ld", + (unsigned int) msg, (long) datalen)); if((macstate == LIBSSH2_MAC_INVALID) && (!session->macerror || @@ -657,6 +675,70 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, break; } + if(session->state & LIBSSH2_STATE_INITIAL_KEX) { + if(msg == SSH_MSG_KEXINIT) { + if(!session->kex_strict) { + if(datalen < 17) { + LIBSSH2_FREE(session, data); + session->packAdd_state = libssh2_NB_state_idle; + return _libssh2_error(session, + LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short extracting kex"); + } + else { + const unsigned char *strict = + (unsigned char *)"kex-strict-s-v00@openssh.com"; + struct string_buf buf; + unsigned char *algs = NULL; + size_t algs_len = 0; + + buf.data = (unsigned char *)data; + buf.dataptr = buf.data; + buf.len = datalen; + buf.dataptr += 17; /* advance past type and cookie */ + + if(_libssh2_get_string(&buf, &algs, &algs_len)) { + LIBSSH2_FREE(session, data); + session->packAdd_state = libssh2_NB_state_idle; + return _libssh2_error(session, + LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Algs too short"); + } + + if(algs_len == 0 || + _libssh2_kex_agree_instr(algs, algs_len, strict, 28)) { + session->kex_strict = 1; + } + } + } + + if(session->kex_strict && seq) { + LIBSSH2_FREE(session, data); + session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; + session->packAdd_state = libssh2_NB_state_idle; + libssh2_session_disconnect(session, "strict KEX violation: " + "KEXINIT was not the first packet"); + + return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, + "strict KEX violation: " + "KEXINIT was not the first packet"); + } + } + + if(session->kex_strict && session->fullpacket_required_type && + session->fullpacket_required_type != msg) { + LIBSSH2_FREE(session, data); + session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; + session->packAdd_state = libssh2_NB_state_idle; + libssh2_session_disconnect(session, "strict KEX violation: " + "unexpected packet type"); + + return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, + "strict KEX violation: " + "unexpected packet type"); + } + } + if(session->packAdd_state == libssh2_NB_state_allocated) { /* A couple exceptions to the packet adding rule: */ switch(msg) { @@ -793,7 +875,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Server to Client extension %.*s: %.*s", - name_len, name, value_len, value)); + (int)name_len, name, + (int)value_len, value)); } if(name_len == 15 && @@ -841,7 +924,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Received global request type %.*s (wr %X)", - len, data + 5, want_reply)); + (int)len, data + 5, want_reply)); } @@ -870,7 +953,7 @@ libssh2_packet_add_jump_point5: /* streamid(4) */ data_head += 4; - /* fall-through */ + LIBSSH2_FALLTHROUGH(); /* byte SSH_MSG_CHANNEL_DATA @@ -901,8 +984,8 @@ libssh2_packet_add_jump_point5: stream_id = _libssh2_ntohu32(data + 5); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "%d bytes packet_add() for %lu/%lu/%lu", - (int) (datalen - data_head), + "%ld bytes packet_add() for %u/%u/%u", + (long) (datalen - data_head), channelp->local.id, channelp->remote.id, stream_id)); @@ -915,8 +998,8 @@ libssh2_packet_add_jump_point5: LIBSSH2_FREE(session, data); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Ignoring extended data and refunding %d bytes", - (int) (datalen - 13))); + "Ignoring extended data and refunding %ld bytes", + (long) (datalen - 13))); if(channelp->read_avail + datalen - data_head >= channelp->remote.window_size) datalen = channelp->remote.window_size - @@ -925,11 +1008,11 @@ libssh2_packet_add_jump_point5: channelp->remote.window_size -= (uint32_t)(datalen - data_head); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "shrinking window size by %lu bytes to %lu, " - "read_avail %lu", - datalen - data_head, + "shrinking window size by %ld bytes to %u, " + "read_avail %ld", + (long) (datalen - data_head), channelp->remote.window_size, - channelp->read_avail)); + (long) channelp->read_avail)); session->packAdd_channelp = channelp; @@ -991,10 +1074,10 @@ libssh2_packet_add_jump_point1: channelp->read_avail += datalen - data_head; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "increasing read_avail by %lu bytes to %lu/%lu", + "increasing read_avail by %ld bytes to %ld/%u", (long)(datalen - data_head), (long)channelp->read_avail, - (long)channelp->remote.window_size)); + channelp->remote.window_size)); break; @@ -1014,7 +1097,7 @@ libssh2_packet_add_jump_point1: else { _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "EOF received for channel %lu/%lu", + "EOF received for channel %u/%u", channelp->local.id, channelp->remote.id)); channelp->remote.eof = 1; @@ -1042,43 +1125,45 @@ libssh2_packet_add_jump_point1: _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Channel %d received request type %.*s (wr %X)", - channel, len, data + 9, want_reply)); + "Channel %u received request type %.*s (wr %X)", + channel, (int)len, data + 9, want_reply)); - if(len == sizeof("exit-status") - 1 - && (sizeof("exit-status") - 1 + 9) <= datalen + if(len == strlen("exit-status") + && (strlen("exit-status") + 9) <= datalen && !memcmp("exit-status", data + 9, - sizeof("exit-status") - 1)) { + strlen("exit-status"))) { /* we've got "exit-status" packet. Set the session value */ if(datalen >= 20) channelp = _libssh2_channel_locate(session, channel); - if(channelp && (sizeof("exit-status") + 13) <= datalen) { + if(channelp && (strlen("exit-status") + 14) <= datalen) { channelp->exit_status = - _libssh2_ntohu32(data + 9 + sizeof("exit-status")); + _libssh2_ntohu32(data + 10 + + strlen("exit-status")); _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Exit status %lu received for " - "channel %lu/%lu", + "Exit status %d received for " + "channel %u/%u", channelp->exit_status, channelp->local.id, channelp->remote.id)); } } - else if(len == sizeof("exit-signal") - 1 - && (sizeof("exit-signal") - 1 + 9) <= datalen + else if(len == strlen("exit-signal") + && (strlen("exit-signal") + 9) <= datalen && !memcmp("exit-signal", data + 9, - sizeof("exit-signal") - 1)) { + strlen("exit-signal"))) { /* command terminated due to signal */ if(datalen >= 20) channelp = _libssh2_channel_locate(session, channel); - if(channelp && (sizeof("exit-signal") + 13) <= datalen) { + if(channelp && (strlen("exit-signal") + 14) <= datalen) { /* set signal name (without SIG prefix) */ uint32_t namelen = - _libssh2_ntohu32(data + 9 + sizeof("exit-signal")); + _libssh2_ntohu32(data + 10 + + strlen("exit-signal")); if(namelen <= UINT_MAX - 1) { channelp->exit_signal = @@ -1091,15 +1176,15 @@ libssh2_packet_add_jump_point1: if(!channelp->exit_signal) rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "memory for signal name"); - else if((sizeof("exit-signal") + 13 + namelen <= + else if((strlen("exit-signal") + 14 + namelen <= datalen)) { memcpy(channelp->exit_signal, - data + 13 + sizeof("exit-signal"), namelen); + data + 14 + strlen("exit-signal"), namelen); channelp->exit_signal[namelen] = '\0'; /* TODO: save error message and language tag */ _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Exit signal %s received for " - "channel %lu/%lu", + "channel %u/%u", channelp->exit_signal, channelp->local.id, channelp->remote.id)); @@ -1140,7 +1225,7 @@ libssh2_packet_add_jump_point4: return 0; } _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Close received for channel %lu/%lu", + "Close received for channel %u/%u", channelp->local.id, channelp->remote.id)); @@ -1162,12 +1247,12 @@ libssh2_packet_add_jump_point4: case SSH_MSG_CHANNEL_OPEN: if(datalen < 17) ; - else if((datalen >= (sizeof("forwarded-tcpip") + 4)) && - ((sizeof("forwarded-tcpip") - 1) == + else if((datalen >= (strlen("forwarded-tcpip") + 5)) && + (strlen("forwarded-tcpip") == _libssh2_ntohu32(data + 1)) && (memcmp(data + 5, "forwarded-tcpip", - sizeof("forwarded-tcpip") - 1) == 0)) { + strlen("forwarded-tcpip")) == 0)) { /* init the state struct */ memset(&session->packAdd_Qlstn_state, 0, @@ -1178,9 +1263,9 @@ libssh2_packet_add_jump_point2: rc = packet_queue_listener(session, data, datalen, &session->packAdd_Qlstn_state); } - else if((datalen >= (sizeof("x11") + 4)) && - ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) && - (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) { + else if((datalen >= (strlen("x11") + 5)) && + ((strlen("x11")) == _libssh2_ntohu32(data + 1)) && + (memcmp(data + 5, "x11", strlen("x11")) == 0)) { /* init the state struct */ memset(&session->packAdd_x11open_state, 0, @@ -1191,11 +1276,11 @@ libssh2_packet_add_jump_point3: rc = packet_x11_open(session, data, datalen, &session->packAdd_x11open_state); } - else if((datalen >= (sizeof("auth-agent@openssh.com") + 4)) && - ((sizeof("auth-agent@openssh.com") - 1) == + else if((datalen >= (strlen("auth-agent@openssh.com") + 5)) && + (strlen("auth-agent@openssh.com") == _libssh2_ntohu32(data + 1)) && (memcmp(data + 5, "auth-agent@openssh.com", - sizeof("auth-agent@openssh.com") - 1) == 0)) { + strlen("auth-agent@openssh.com")) == 0)) { /* init the state struct */ memset(&session->packAdd_authagent_state, 0, @@ -1230,8 +1315,8 @@ libssh2_packet_add_jump_authagent: channelp->local.window_size += bytestoadd; _libssh2_debug((session, LIBSSH2_TRACE_CONN, - "Window adjust for channel %lu/%lu, " - "adding %lu bytes, new window_size=%lu", + "Window adjust for channel %u/%u, " + "adding %u bytes, new window_size=%u", channelp->local.id, channelp->remote.id, bytestoadd, @@ -1323,7 +1408,8 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets); _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "Looking for packet of type: %d", (int) packet_type)); + "Looking for packet of type: %u", + (unsigned int)packet_type)); while(packet) { if(packet->data[0] == packet_type @@ -1341,6 +1427,15 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, return 0; } + else if(session->kex_strict && + (session->state & LIBSSH2_STATE_INITIAL_KEX)) { + libssh2_session_disconnect(session, "strict KEX violation: " + "unexpected packet type"); + + return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, + "strict KEX violation: " + "unexpected packet type"); + } packet = _libssh2_list_next(&packet->node); } return -1; @@ -1402,7 +1497,10 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type, } while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - int ret = _libssh2_transport_read(session); + int ret; + session->fullpacket_required_type = packet_type; + ret = _libssh2_transport_read(session); + session->fullpacket_required_type = 0; if(ret == LIBSSH2_ERROR_EAGAIN) return ret; else if(ret < 0) { diff --git a/libssh2/src/packet.h b/libssh2/src/packet.h index 79018bcf1..955351e5f 100644 --- a/libssh2/src/packet.h +++ b/libssh2/src/packet.h @@ -1,8 +1,8 @@ -#ifndef __LIBSSH2_PACKET_H -#define __LIBSSH2_PACKET_H +#ifndef LIBSSH2_PACKET_H +#define LIBSSH2_PACKET_H /* - * Copyright (C) 2010 by Daniel Stenberg - * Author: Daniel Stenberg + * Copyright (C) Daniel Stenberg + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -37,6 +37,7 @@ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * + * SPDX-License-Identifier: BSD-3-Clause */ int _libssh2_packet_read(LIBSSH2_SESSION * session); @@ -71,6 +72,6 @@ int _libssh2_packet_burn(LIBSSH2_SESSION * session, int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data, unsigned long data_len); int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - size_t datalen, int macstate); + size_t datalen, int macstate, uint32_t seq); -#endif /* __LIBSSH2_PACKET_H */ +#endif /* LIBSSH2_PACKET_H */ diff --git a/libssh2/src/pem.c b/libssh2/src/pem.c index 8b3659e3b..c9ab77469 100644 --- a/libssh2/src/pem.c +++ b/libssh2/src/pem.c @@ -1,5 +1,5 @@ -/* Copyright (C) 2007 The Written Word, Inc. - * Copyright (C) 2008, Simon Josefsson +/* Copyright (C) The Written Word, Inc. + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -104,12 +106,6 @@ static unsigned char hex_decode(char digit) ((digit >= 'A') ? (0xA + (digit - 'A')) : (digit - '0')); } -/* Hack to fix builds with crypto backends with MD5 support disabled. - FIXME: Honor our LIBSSH2_MD5 macro for MD5-dependent logic. */ -#ifdef OPENSSL_NO_MD5 -#define MD5_DIGEST_LENGTH 16 -#endif - int _libssh2_pem_parse(LIBSSH2_SESSION * session, const char *headerbegin, @@ -130,8 +126,7 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, if(readline(line, LINE_SIZE, fp)) { return -1; } - } - while(strcmp(line, headerbegin) != 0); + } while(strcmp(line, headerbegin) != 0); if(readline(line, LINE_SIZE, fp)) { return -1; @@ -213,6 +208,7 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, } if(method) { +#if LIBSSH2_MD5_PEM /* Set up decryption */ int free_iv = 0, free_secret = 0, len_decrypted = 0, padding = 0; int blocksize = method->blocksize; @@ -221,24 +217,26 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, libssh2_md5_ctx fingerprint_ctx; /* Perform key derivation (PBKDF1/MD5) */ - if(!libssh2_md5_init(&fingerprint_ctx)) { + if(!libssh2_md5_init(&fingerprint_ctx) || + !libssh2_md5_update(fingerprint_ctx, passphrase, + strlen((char *)passphrase)) || + !libssh2_md5_update(fingerprint_ctx, iv, 8) || + !libssh2_md5_final(fingerprint_ctx, secret)) { ret = -1; goto out; } - libssh2_md5_update(fingerprint_ctx, passphrase, - strlen((char *)passphrase)); - libssh2_md5_update(fingerprint_ctx, iv, 8); - libssh2_md5_final(fingerprint_ctx, secret); if(method->secret_len > MD5_DIGEST_LENGTH) { - if(!libssh2_md5_init(&fingerprint_ctx)) { + if(!libssh2_md5_init(&fingerprint_ctx) || + !libssh2_md5_update(fingerprint_ctx, + secret, MD5_DIGEST_LENGTH) || + !libssh2_md5_update(fingerprint_ctx, + passphrase, strlen((char *)passphrase)) || + !libssh2_md5_update(fingerprint_ctx, iv, 8) || + !libssh2_md5_final(fingerprint_ctx, + secret + MD5_DIGEST_LENGTH)) { ret = -1; goto out; } - libssh2_md5_update(fingerprint_ctx, secret, MD5_DIGEST_LENGTH); - libssh2_md5_update(fingerprint_ctx, passphrase, - strlen((char *)passphrase)); - libssh2_md5_update(fingerprint_ctx, iv, 8); - libssh2_md5_final(fingerprint_ctx, secret + MD5_DIGEST_LENGTH); } /* Initialize the decryption */ @@ -264,13 +262,8 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, goto out; } - while(len_decrypted <= (int)*datalen - blocksize) { - if(method->crypt(session, *data + len_decrypted, blocksize, - &abstract, - len_decrypted == 0 ? FIRST_BLOCK : - ((len_decrypted == (int)*datalen - blocksize) ? - LAST_BLOCK : MIDDLE_BLOCK) - )) { + if(method->flags & LIBSSH2_CRYPT_FLAG_REQUIRES_FULL_PACKET) { + if(method->crypt(session, 0, *data, *datalen, &abstract, 0)) { ret = LIBSSH2_ERROR_DECRYPT; _libssh2_explicit_zero((char *)secret, sizeof(secret)); method->dtor(session, &abstract); @@ -278,8 +271,25 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, LIBSSH2_FREE(session, *data); goto out; } + } + else { + while(len_decrypted <= (int)*datalen - blocksize) { + if(method->crypt(session, 0, *data + len_decrypted, blocksize, + &abstract, + len_decrypted == 0 ? FIRST_BLOCK : + ((len_decrypted == (int)*datalen - blocksize) ? + LAST_BLOCK : MIDDLE_BLOCK) + )) { + ret = LIBSSH2_ERROR_DECRYPT; + _libssh2_explicit_zero((char *)secret, sizeof(secret)); + method->dtor(session, &abstract); + _libssh2_explicit_zero(*data, *datalen); + LIBSSH2_FREE(session, *data); + goto out; + } - len_decrypted += blocksize; + len_decrypted += blocksize; + } } /* Account for padding */ @@ -290,6 +300,10 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, /* Clean up */ _libssh2_explicit_zero((char *)secret, sizeof(secret)); method->dtor(session, &abstract); +#else + ret = -1; + goto out; +#endif } ret = 0; @@ -320,8 +334,7 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session, if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { return -1; } - } - while(strcmp(line, headerbegin) != 0); + } while(strcmp(line, headerbegin) != 0); *line = '\0'; @@ -596,23 +609,59 @@ _libssh2_openssh_pem_parse_data(LIBSSH2_SESSION * session, goto out; } - while((size_t)len_decrypted <= decrypted.len - blocksize) { - if(method->crypt(session, decrypted.data + len_decrypted, - blocksize, + if(method->flags & LIBSSH2_CRYPT_FLAG_REQUIRES_FULL_PACKET) { + if(method->crypt(session, 0, decrypted.data, + decrypted.len, &abstract, - len_decrypted == 0 ? FIRST_BLOCK : ( - ((size_t)len_decrypted == decrypted.len - blocksize) ? - LAST_BLOCK : MIDDLE_BLOCK) - )) { + MIDDLE_BLOCK)) { ret = LIBSSH2_ERROR_DECRYPT; method->dtor(session, &abstract); goto out; } - - len_decrypted += blocksize; } + else { + while((size_t)len_decrypted <= decrypted.len - blocksize) { + /* We always pass MIDDLE_BLOCK here because OpenSSH Key Files + * do not use AAD to authenticate the length. + * Furthermore, the authentication tag is appended after the + * encrypted key, and the length of the authentication tag is + * not included in the key length, so we check it after the + * loop. + */ + if(method->crypt(session, 0, decrypted.data + len_decrypted, + blocksize, + &abstract, + MIDDLE_BLOCK)) { + ret = LIBSSH2_ERROR_DECRYPT; + method->dtor(session, &abstract); + goto out; + } - /* No padding */ + len_decrypted += blocksize; + } + + /* No padding */ + + /* for the AES GCM methods, the 16 byte authentication tag is + * appended to the encrypted key */ + if(strcmp(method->name, "aes256-gcm@openssh.com") == 0 || + strcmp(method->name, "aes128-gcm@openssh.com") == 0) { + if(!_libssh2_check_length(&decoded, 16)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "GCM auth tag missing"); + method->dtor(session, &abstract); + goto out; + } + if(method->crypt(session, 0, decoded.dataptr, 16, &abstract, + LAST_BLOCK)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_DECRYPT, + "GCM auth tag invalid"); + method->dtor(session, &abstract); + goto out; + } + decoded.dataptr += 16; + } + } method->dtor(session, &abstract); } @@ -695,8 +744,7 @@ _libssh2_openssh_pem_parse(LIBSSH2_SESSION * session, if(readline(line, LINE_SIZE, fp)) { return -1; } - } - while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); + } while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); if(readline(line, LINE_SIZE, fp)) { return -1; @@ -776,8 +824,7 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session, if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { return -1; } - } - while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); + } while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); *line = '\0'; diff --git a/libssh2/src/poly1305.c b/libssh2/src/poly1305.c new file mode 100644 index 000000000..2d7b23248 --- /dev/null +++ b/libssh2/src/poly1305.c @@ -0,0 +1,206 @@ +/* + * Public Domain poly1305 from Andrew Moon + * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna + * Copyright not intended 2024. + * + * SPDX-License-Identifier: SAX-PD-2.0 + */ + +/* $OpenBSD: poly1305.c,v 1.3 2013/12/19 22:57:13 djm Exp $ */ + +#include "libssh2_priv.h" + +#include "poly1305.h" + +#define mul32x32_64(a,b) ((uint64_t)(a) * (b)) + +#define U8TO32_LE(p) \ + (((uint32_t)((p)[0])) | \ + ((uint32_t)((p)[1]) << 8) | \ + ((uint32_t)((p)[2]) << 16) | \ + ((uint32_t)((p)[3]) << 24)) + +#define U32TO8_LE(p, v) \ + do { \ + (p)[0] = (uint8_t)((v)); \ + (p)[1] = (uint8_t)((v) >> 8); \ + (p)[2] = (uint8_t)((v) >> 16); \ + (p)[3] = (uint8_t)((v) >> 24); \ + } while (0) + +void +poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, + size_t inlen, const unsigned char key[POLY1305_KEYLEN]) { + uint32_t t0; + uint32_t t1; + uint32_t t2; + uint32_t t3; + uint32_t h0; + uint32_t h1; + uint32_t h2; + uint32_t h3; + uint32_t h4; + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t s1; + uint32_t s2; + uint32_t s3; + uint32_t s4; + uint32_t b; + uint32_t nb; + size_t j; + uint64_t t[5]; + uint64_t f0; + uint64_t f1; + uint64_t f2; + uint64_t f3; + uint32_t g0; + uint32_t g1; + uint32_t g2; + uint32_t g3; + uint32_t g4; + uint64_t c; + unsigned char mp[16]; + + /* clamp key */ + t0 = U8TO32_LE(key + 0); + t1 = U8TO32_LE(key + 4); + t2 = U8TO32_LE(key + 8); + t3 = U8TO32_LE(key + 12); + + /* precompute multipliers */ + r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6; + r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12; + r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18; + r3 = t2 & 0x3f03fff; t3 >>= 8; + r4 = t3 & 0x00fffff; + + s1 = r1 * 5; + s2 = r2 * 5; + s3 = r3 * 5; + s4 = r4 * 5; + + /* init state */ + h0 = 0; + h1 = 0; + h2 = 0; + h3 = 0; + h4 = 0; + + /* full blocks */ + if(inlen < 16) + goto poly1305_donna_atmost15bytes; + +poly1305_donna_16bytes: + m += 16; + inlen -= 16; + + t0 = U8TO32_LE(m-16); + t1 = U8TO32_LE(m-12); + t2 = U8TO32_LE(m-8); + t3 = U8TO32_LE(m-4); + + h0 += t0 & 0x3ffffff; + h1 += ((uint32_t)((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff); + h2 += ((uint32_t)((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff); + h3 += ((uint32_t)((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff); + h4 += (t3 >> 8) | (1 << 24); + + +poly1305_donna_mul: + t[0] = mul32x32_64(h0, r0) + mul32x32_64(h1, s4) + mul32x32_64(h2, s3) + + mul32x32_64(h3, s2) + mul32x32_64(h4, s1); + t[1] = mul32x32_64(h0, r1) + mul32x32_64(h1, r0) + mul32x32_64(h2, s4) + + mul32x32_64(h3, s3) + mul32x32_64(h4, s2); + t[2] = mul32x32_64(h0, r2) + mul32x32_64(h1, r1) + mul32x32_64(h2, r0) + + mul32x32_64(h3, s4) + mul32x32_64(h4, s3); + t[3] = mul32x32_64(h0, r3) + mul32x32_64(h1, r2) + mul32x32_64(h2, r1) + + mul32x32_64(h3, r0) + mul32x32_64(h4, s4); + t[4] = mul32x32_64(h0, r4) + mul32x32_64(h1, r3) + mul32x32_64(h2, r2) + + mul32x32_64(h3, r1) + mul32x32_64(h4, r0); + + h0 = (uint32_t)t[0] & 0x3ffffff; + c = (t[0] >> 26); + + t[1] += c; + h1 = (uint32_t)t[1] & 0x3ffffff; + b = (uint32_t)(t[1] >> 26); + + t[2] += b; + h2 = (uint32_t)t[2] & 0x3ffffff; + b = (uint32_t)(t[2] >> 26); + + t[3] += b; + h3 = (uint32_t)t[3] & 0x3ffffff; + b = (uint32_t)(t[3] >> 26); + + t[4] += b; + h4 = (uint32_t)t[4] & 0x3ffffff; + b = (uint32_t)(t[4] >> 26); + + h0 += b * 5; + + if(inlen >= 16) + goto poly1305_donna_16bytes; + + /* final bytes */ +poly1305_donna_atmost15bytes: + if(!inlen) + goto poly1305_donna_finish; + + for(j = 0; j < inlen; j++) mp[j] = m[j]; + mp[j++] = 1; + for(; j < 16; j++) + mp[j] = 0; + + inlen = 0; + + t0 = U8TO32_LE(mp + 0); + t1 = U8TO32_LE(mp + 4); + t2 = U8TO32_LE(mp + 8); + t3 = U8TO32_LE(mp + 12); + + h0 += t0 & 0x3ffffff; + h1 += ((uint32_t)((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff); + h2 += ((uint32_t)((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff); + h3 += ((uint32_t)((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff); + h4 += (t3 >> 8); + + goto poly1305_donna_mul; + +poly1305_donna_finish: + b = h0 >> 26; h0 = h0 & 0x3ffffff; + h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff; + h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff; + h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff; + h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff; + h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff; + h1 += b; + + g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff; + g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff; + g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff; + g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff; + g4 = h4 + b - (1 << 26); + + b = (g4 >> 31) - 1; + nb = ~b; + h0 = (h0 & nb) | (g0 & b); + h1 = (h1 & nb) | (g1 & b); + h2 = (h2 & nb) | (g2 & b); + h3 = (h3 & nb) | (g3 & b); + h4 = (h4 & nb) | (g4 & b); + + f0 = ((h0 ) | (h1 << 26)) + (uint64_t)U8TO32_LE(&key[16]); + f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)U8TO32_LE(&key[20]); + f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)U8TO32_LE(&key[24]); + f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)U8TO32_LE(&key[28]); + + U32TO8_LE(&out[ 0], f0); f1 += (f0 >> 32); + U32TO8_LE(&out[ 4], f1); f2 += (f1 >> 32); + U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32); + U32TO8_LE(&out[12], f3); +} diff --git a/libssh2/src/poly1305.h b/libssh2/src/poly1305.h new file mode 100644 index 000000000..21efca93f --- /dev/null +++ b/libssh2/src/poly1305.h @@ -0,0 +1,20 @@ +/* $OpenBSD: poly1305.h,v 1.4 2014/05/02 03:27:54 djm Exp $ */ + +/* + * Public Domain poly1305 from Andrew Moon + * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna + * Copyright not intended 2024. + * + * SPDX-License-Identifier: SAX-PD-2.0 + */ + +#ifndef POLY1305_H +#define POLY1305_H + +#define POLY1305_KEYLEN 32 +#define POLY1305_TAGLEN 16 + +void poly1305_auth(u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen, + const u_char key[POLY1305_KEYLEN]); + +#endif /* POLY1305_H */ diff --git a/libssh2/src/publickey.c b/libssh2/src/publickey.c index ddc0e8a3b..9c9fa6188 100644 --- a/libssh2/src/publickey.c +++ b/libssh2/src/publickey.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010-2014 by Daniel Stenberg +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -514,13 +516,13 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) LIBSSH2_PUBLICKEY_VERSION) { _libssh2_debug((session, LIBSSH2_TRACE_PUBLICKEY, "Truncate remote publickey version " - "from %lu", + "from %u", session->pkeyInit_pkey->version)); session->pkeyInit_pkey->version = LIBSSH2_PUBLICKEY_VERSION; } _libssh2_debug((session, LIBSSH2_TRACE_PUBLICKEY, - "Enabling publickey subsystem version %lu", + "Enabling publickey subsystem version %u", session->pkeyInit_pkey->version)); LIBSSH2_FREE(session, session->pkeyInit_data); session->pkeyInit_data = NULL; diff --git a/libssh2/src/scp.c b/libssh2/src/scp.c index ede0b88c9..8a8e7d9ea 100644 --- a/libssh2/src/scp.c +++ b/libssh2/src/scp.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2009-2019 by Daniel Stenberg - * Copyright (c) 2004-2008, Sara Golemon +/* Copyright (C) Daniel Stenberg + * Copyright (C) Sara Golemon * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -746,7 +748,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) } _libssh2_debug((session, LIBSSH2_TRACE_SCP, "mode = 0%lo size = %ld", session->scpRecv_mode, - session->scpRecv_size)); + (long)session->scpRecv_size)); /* We *should* check that basename is valid, but why let that stop us? */ @@ -762,7 +764,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) sb->st_mtime = session->scpRecv_mtime; sb->st_atime = session->scpRecv_atime; - sb->st_size = session->scpRecv_size; + sb->st_size = (libssh2_struct_stat_size)session->scpRecv_size; sb->st_mode = (unsigned short)session->scpRecv_mode; } @@ -782,7 +784,7 @@ scp_recv_error: tmp_err_code = session->err_code; tmp_err_msg = session->err_msg; while(libssh2_channel_free(session->scpRecv_channel) == - LIBSSH2_ERROR_EAGAIN); + LIBSSH2_ERROR_EAGAIN); session->err_code = tmp_err_code; session->err_msg = tmp_err_msg; session->scpRecv_channel = NULL; @@ -790,6 +792,7 @@ scp_recv_error: return NULL; } +#ifndef LIBSSH2_NO_DEPRECATED /* * libssh2_scp_recv * @@ -826,6 +829,7 @@ libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat *sb) return ptr; } +#endif /* * libssh2_scp_recv2 diff --git a/libssh2/src/session.c b/libssh2/src/session.c index a4d602bad..2d77b05e9 100644 --- a/libssh2/src/session.c +++ b/libssh2/src/session.c @@ -1,6 +1,6 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2015 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,11 +35,13 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" -#ifdef WIN32 +#ifdef _WIN32 #include /* for socklen_t */ #endif #ifdef HAVE_UNISTD_H @@ -58,7 +60,7 @@ #include "channel.h" #include "mac.h" -#if defined(WIN32) +#if defined(_WIN32) #define libssh2_usec_t long #elif defined(__APPLE__) #define libssh2_usec_t suseconds_t @@ -130,11 +132,11 @@ banner_receive(LIBSSH2_SESSION * session) if(session->api_block_mode || (ret != -EAGAIN)) /* ignore EAGAIN when non-blocking */ _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Error recving %d bytes: %d", 1, (int)-ret)); + "Error recving %d bytes: %ld", 1, (long)-ret)); } else _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Recved %d bytes banner", (int)ret)); + "Recved %ld bytes banner", (long)ret)); if(ret < 0) { if(ret == -EAGAIN) { @@ -251,13 +253,14 @@ banner_send(LIBSSH2_SESSION * session) LIBSSH2_SOCKET_SEND_FLAGS(session)); if(ret < 0) _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", - banner_len - session->banner_TxRx_total_send, -ret)); + "Error sending %ld bytes: %ld", + (long)(banner_len - session->banner_TxRx_total_send), + (long)-ret)); else _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p+%d", ret, - banner_len - session->banner_TxRx_total_send, - banner, session->banner_TxRx_total_send)); + "Sent %ld/%ld bytes at %p+%ld", (long)ret, + (long)(banner_len - session->banner_TxRx_total_send), + (void *)banner, (long)session->banner_TxRx_total_send)); if(ret != (ssize_t)(banner_len - session->banner_TxRx_total_send)) { if(ret >= 0 || ret == -EAGAIN) { @@ -311,7 +314,7 @@ session_nonblock(libssh2_socket_t sockfd, /* operate on this */ /* BeOS */ long b = nonblock ? 1 : 0; return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); -#elif defined(WIN32) +#elif defined(_WIN32) unsigned long flags; flags = nonblock; @@ -364,7 +367,7 @@ get_socket_nonblocking(libssh2_socket_t sockfd) return 1; } return 0; -#elif defined(WIN32) +#elif defined(_WIN32) unsigned int option_value; socklen_t option_len = sizeof(option_value); @@ -415,6 +418,7 @@ libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner) return 0; } +#ifndef LIBSSH2_NO_DEPRECATED /* libssh2_banner_set * Set the local banner. DEPRECATED VERSION */ @@ -423,6 +427,7 @@ libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner) { return libssh2_session_banner_set(session, banner); } +#endif /* * libssh2_session_init_ex @@ -464,9 +469,12 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), session->abstract = abstract; session->api_timeout = 0; /* timeout-free API by default */ session->api_block_mode = 1; /* blocking API by default */ + session->state = LIBSSH2_STATE_INITIAL_KEX; + session->fullpacket_required_type = 0; session->packet_read_timeout = LIBSSH2_DEFAULT_READ_TIMEOUT; session->flag.quote_paths = 1; /* default behavior is to quote paths for the scp subsystem */ + session->kex = NULL; _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "New session resource allocated")); _libssh2_init_if_needed(); @@ -475,7 +483,78 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), } /* - * libssh2_session_callback_set + * libssh2_session_callback_set2 + * + * Set (or reset) a callback function + * Returns the prior address + */ +LIBSSH2_API libssh2_cb_generic * +libssh2_session_callback_set2(LIBSSH2_SESSION *session, int cbtype, + libssh2_cb_generic *callback) +{ + libssh2_cb_generic *oldcb; + + switch(cbtype) { + case LIBSSH2_CALLBACK_IGNORE: + oldcb = (libssh2_cb_generic *)session->ssh_msg_ignore; + session->ssh_msg_ignore = (LIBSSH2_IGNORE_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_DEBUG: + oldcb = (libssh2_cb_generic *)session->ssh_msg_debug; + session->ssh_msg_debug = (LIBSSH2_DEBUG_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_DISCONNECT: + oldcb = (libssh2_cb_generic *)session->ssh_msg_disconnect; + session->ssh_msg_disconnect = (LIBSSH2_DISCONNECT_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_MACERROR: + oldcb = (libssh2_cb_generic *)session->macerror; + session->macerror = (LIBSSH2_MACERROR_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_X11: + oldcb = (libssh2_cb_generic *)session->x11; + session->x11 = (LIBSSH2_X11_OPEN_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_SEND: + oldcb = (libssh2_cb_generic *)session->send; + session->send = (LIBSSH2_SEND_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_RECV: + oldcb = (libssh2_cb_generic *)session->recv; + session->recv = (LIBSSH2_RECV_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_AUTHAGENT: + oldcb = (libssh2_cb_generic *)session->authagent; + session->authagent = (LIBSSH2_AUTHAGENT_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_AUTHAGENT_IDENTITIES: + oldcb = (libssh2_cb_generic *)session->addLocalIdentities; + session->addLocalIdentities = + (LIBSSH2_ADD_IDENTITIES_FUNC((*)))callback; + return oldcb; + + case LIBSSH2_CALLBACK_AUTHAGENT_SIGN: + oldcb = (libssh2_cb_generic *)session->agentSignCallback; + session->agentSignCallback = + (LIBSSH2_AUTHAGENT_SIGN_FUNC((*)))callback; + return oldcb; + } + _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", + cbtype)); + + return NULL; +} + +/* + * libssh2_session_callback_set (DEPRECATED, DO NOT USE!) * * Set (or reset) a callback function * Returns the prior address @@ -485,8 +564,10 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), */ #ifdef _MSC_VER #pragma warning(push) -/* nonstandard extension, function/data pointer conversion in expression */ -#pragma warning(disable:4152) +/* 'type cast': from data pointer to function pointer */ +#pragma warning(disable:4054) +/* 'type cast': from function pointer to data pointer */ +#pragma warning(disable:4055) #else #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" @@ -495,63 +576,8 @@ LIBSSH2_API void * libssh2_session_callback_set(LIBSSH2_SESSION * session, int cbtype, void *callback) { - void *oldcb; - - switch(cbtype) { - case LIBSSH2_CALLBACK_IGNORE: - oldcb = session->ssh_msg_ignore; - session->ssh_msg_ignore = callback; - return oldcb; - - case LIBSSH2_CALLBACK_DEBUG: - oldcb = session->ssh_msg_debug; - session->ssh_msg_debug = callback; - return oldcb; - - case LIBSSH2_CALLBACK_DISCONNECT: - oldcb = session->ssh_msg_disconnect; - session->ssh_msg_disconnect = callback; - return oldcb; - - case LIBSSH2_CALLBACK_MACERROR: - oldcb = session->macerror; - session->macerror = callback; - return oldcb; - - case LIBSSH2_CALLBACK_X11: - oldcb = session->x11; - session->x11 = callback; - return oldcb; - - case LIBSSH2_CALLBACK_SEND: - oldcb = session->send; - session->send = callback; - return oldcb; - - case LIBSSH2_CALLBACK_RECV: - oldcb = session->recv; - session->recv = callback; - return oldcb; - - case LIBSSH2_CALLBACK_AUTHAGENT: - oldcb = session->authagent; - session->authagent = callback; - return oldcb; - - case LIBSSH2_CALLBACK_AUTHAGENT_IDENTITIES: - oldcb = session->addLocalIdentities; - session->addLocalIdentities = callback; - return oldcb; - - case LIBSSH2_CALLBACK_AUTHAGENT_SIGN: - oldcb = session->agentSignCallback; - session->agentSignCallback = callback; - return oldcb; - } - _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", - cbtype)); - - return NULL; + return (void *)libssh2_session_callback_set2(session, cbtype, + (libssh2_cb_generic *)callback); } #ifdef _MSC_VER #pragma warning(pop) @@ -649,13 +675,27 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time) if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) { FD_ZERO(&rfd); +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif FD_SET(session->socket_fd, &rfd); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif readfd = &rfd; } if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) { FD_ZERO(&wfd); +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif FD_SET(session->socket_fd, &wfd); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif writefd = &wfd; } @@ -668,6 +708,18 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time) "Timed out waiting on socket"); } if(rc < 0) { + int err; +#ifdef _WIN32 + err = _libssh2_wsa2errno(); +#else + err = errno; +#endif + /* Profiling tools that use SIGPROF can cause EINTR responses. + poll() / select() do not set any descriptor states on EINTR, + but some fds may be ready, so the caller should try again */ + if(err == EINTR) + return 0; + return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Error waiting on socket"); } @@ -682,7 +734,7 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) if(session->startup_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "session_startup for socket %d", sock)); + "session_startup for socket %ld", (long)sock)); if(LIBSSH2_INVALID_SOCKET == sock) { /* Did we forget something? */ return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET, @@ -828,6 +880,7 @@ libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock) return rc; } +#ifndef LIBSSH2_NO_DEPRECATED /* * libssh2_session_startup * @@ -844,6 +897,7 @@ libssh2_session_startup(LIBSSH2_SESSION *session, int sock) { return libssh2_session_handshake(session, (libssh2_socket_t) sock); } +#endif /* * session_free @@ -862,8 +916,8 @@ session_free(LIBSSH2_SESSION *session) if(session->free_state == libssh2_NB_state_idle) { _libssh2_debug((session, LIBSSH2_TRACE_TRANS, - "Freeing session resource", - session->remote.banner)); + "Freeing session resource %p", + (void *)session->remote.banner)); session->free_state = libssh2_NB_state_created; } @@ -890,6 +944,11 @@ session_free(LIBSSH2_SESSION *session) session->free_state = libssh2_NB_state_sent1; } + if(session->kex && session->kex->cleanup) { + session->kex->cleanup(session, + &session->startup_key_state.key_state_low); + } + if(session->state & LIBSSH2_STATE_NEWKEYS) { /* hostkey */ if(session->hostkey && session->hostkey->dtor) { @@ -1186,6 +1245,7 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *desc, const char *lang) { int rc; + session->state &= ~LIBSSH2_STATE_INITIAL_KEX; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; BLOCK_ADJUST(rc, session, session_disconnect(session, reason, desc, lang)); @@ -1595,19 +1655,40 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) switch(fds[i].type) { case LIBSSH2_POLLFD_SOCKET: if(fds[i].events & LIBSSH2_POLLFD_POLLIN) { +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif FD_SET(fds[i].fd.socket, &rfds); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif if(fds[i].fd.socket > maxfd) maxfd = fds[i].fd.socket; } if(fds[i].events & LIBSSH2_POLLFD_POLLOUT) { +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif FD_SET(fds[i].fd.socket, &wfds); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif if(fds[i].fd.socket > maxfd) maxfd = fds[i].fd.socket; } break; case LIBSSH2_POLLFD_CHANNEL: +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif FD_SET(fds[i].fd.channel->session->socket_fd, &rfds); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif if(fds[i].fd.channel->session->socket_fd > maxfd) maxfd = fds[i].fd.channel->session->socket_fd; if(!session) @@ -1615,7 +1696,14 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) break; case LIBSSH2_POLLFD_LISTENER: +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif FD_SET(fds[i].fd.listener->session->socket_fd, &rfds); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif if(fds[i].fd.listener->session->socket_fd > maxfd) maxfd = fds[i].fd.listener->session->socket_fd; if(!session) @@ -1771,7 +1859,11 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) } #elif defined(HAVE_SELECT) tv.tv_sec = timeout_remaining / 1000; +#ifdef libssh2_usec_t + tv.tv_usec = (libssh2_usec_t)((timeout_remaining % 1000) * 1000); +#else tv.tv_usec = (timeout_remaining % 1000) * 1000; +#endif { struct timeval tv_begin, tv_end; @@ -1788,6 +1880,10 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) for(i = 0; i < nfds; i++) { switch(fds[i].type) { case LIBSSH2_POLLFD_SOCKET: +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif if(FD_ISSET(fds[i].fd.socket, &rfds)) { fds[i].revents |= LIBSSH2_POLLFD_POLLIN; } @@ -1797,6 +1893,9 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) if(fds[i].revents) { active_fds++; } +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif break; case LIBSSH2_POLLFD_CHANNEL: diff --git a/libssh2/src/session.h b/libssh2/src/session.h index 6492ec001..d4fc5755e 100644 --- a/libssh2/src/session.h +++ b/libssh2/src/session.h @@ -1,8 +1,8 @@ -#ifndef __LIBSSH2_SESSION_H -#define __LIBSSH2_SESSION_H -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2010 Simon Josefsson +#ifndef LIBSSH2_SESSION_H +#define LIBSSH2_SESSION_H +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg + * Copyright (C) Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, @@ -37,6 +37,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ /* Conveniance-macros to allow code like this; @@ -89,4 +91,4 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t entry_time); /* this is the lib-internal set blocking function */ int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking); -#endif /* __LIBSSH2_SESSION_H */ +#endif /* LIBSSH2_SESSION_H */ diff --git a/libssh2/src/sftp.c b/libssh2/src/sftp.c index 46164ea36..6ede31110 100644 --- a/libssh2/src/sftp.c +++ b/libssh2/src/sftp.c @@ -1,6 +1,6 @@ -/* Copyright (c) 2004-2008, Sara Golemon - * Copyright (c) 2007 Eli Fant - * Copyright (c) 2009-2019 by Daniel Stenberg +/* Copyright (C) Sara Golemon + * Copyright (C) Eli Fant + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,6 +35,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -45,6 +47,7 @@ #include "sftp.h" #include +#include /* strtol() */ /* This release of libssh2 implements Version 5 with automatic downgrade * based on server's declaration @@ -100,26 +103,6 @@ static int sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type, size_t *data_len); static void sftp_packet_flush(LIBSSH2_SFTP *sftp); -/* _libssh2_store_u64 - */ -static void _libssh2_store_u64(unsigned char **ptr, libssh2_uint64_t value) -{ - uint32_t msl = (uint32_t)(value >> 32); - unsigned char *buf = *ptr; - - buf[0] = (unsigned char)((msl >> 24) & 0xFF); - buf[1] = (unsigned char)((msl >> 16) & 0xFF); - buf[2] = (unsigned char)((msl >> 8) & 0xFF); - buf[3] = (unsigned char)( msl & 0xFF); - - buf[4] = (unsigned char)((value >> 24) & 0xFF); - buf[5] = (unsigned char)((value >> 16) & 0xFF); - buf[6] = (unsigned char)((value >> 8) & 0xFF); - buf[7] = (unsigned char)( value & 0xFF); - - *ptr += 8; -} - /* * Search list of zombied FXP_READ request IDs. * @@ -150,7 +133,7 @@ remove_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) request_id); if(zombie) { _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Removing request ID %ld from the list of " + "Removing request ID %u from the list of " "zombie requests", request_id)); @@ -167,13 +150,13 @@ add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) struct sftp_zombie_requests *zombie; _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Marking request ID %ld as a zombie request", request_id)); + "Marking request ID %u as a zombie request", request_id)); zombie = LIBSSH2_ALLOC(sftp->channel->session, sizeof(struct sftp_zombie_requests)); if(!zombie) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "malloc fail for zombie request ID"); + "malloc fail for zombie request ID"); else { zombie->request_id = request_id; _libssh2_list_add(&sftp->zombie_requests, &zombie->node); @@ -197,8 +180,8 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data, } _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Received packet type %d (len %d)", - (int) data[0], data_len)); + "Received packet type %u (len %lu)", + (unsigned int)data[0], (unsigned long)data_len)); /* * Experience shows that if we mess up EAGAIN handling somewhere or @@ -304,11 +287,11 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) packet = sftp->partial_packet; _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "partial read cont, len: %lu", sftp->partial_len)); + "partial read cont, len: %u", sftp->partial_len)); _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "partial read cont, already recvd: %lu", - sftp->partial_received)); - /* fall-through */ + (unsigned long)sftp->partial_received)); + LIBSSH2_FALLTHROUGH(); default: if(!packet) { /* only do this if there's not already a packet buffer allocated @@ -357,7 +340,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Data begin - Packet Length: %lu", - sftp->partial_len)); + (unsigned long)sftp->partial_len)); packet = LIBSSH2_ALLOC(session, sftp->partial_len); if(!packet) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, @@ -379,8 +362,8 @@ window_adjust: 1, NULL); /* store the state so that we continue with the correct operation at next invoke */ - sftp->packet_state = (rc == LIBSSH2_ERROR_EAGAIN)? - libssh2_NB_state_sent: + sftp->packet_state = (rc == LIBSSH2_ERROR_EAGAIN) ? + libssh2_NB_state_sent : libssh2_NB_state_idle; if(rc == LIBSSH2_ERROR_EAGAIN) @@ -524,13 +507,13 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type, return LIBSSH2_ERROR_BAD_USE; } - _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld", - (int) packet_type, request_id)); + _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Requiring packet %u id %u", + (unsigned int) packet_type, request_id)); if(sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) { /* The right packet was available in the packet brigade */ - _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Got %d", - (int) packet_type)); + _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Got %u", + (unsigned int) packet_type)); if(*data_len < required_size) { return LIBSSH2_ERROR_BUFFER_TOO_SMALL; @@ -548,7 +531,7 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type, if(!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) { /* The right packet was available in the packet brigade */ _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Got %d", - (int) packet_type)); + (unsigned int) packet_type)); if(*data_len < required_size) { return LIBSSH2_ERROR_BUFFER_TOO_SMALL; @@ -977,29 +960,51 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) if(sftp_handle->version > LIBSSH2_SFTP_VERSION) { _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Truncating remote SFTP version from %lu", + "Truncating remote SFTP version from %u", sftp_handle->version)); sftp_handle->version = LIBSSH2_SFTP_VERSION; } _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "Enabling SFTP version %lu compatibility", + "Enabling SFTP version %u compatibility", sftp_handle->version)); while(buf.dataptr < endp) { unsigned char *extname, *extdata; + size_t extname_len, extdata_len; + uint32_t extversion = 0; - if(_libssh2_get_string(&buf, &extname, NULL)) { + if(_libssh2_get_string(&buf, &extname, &extname_len)) { LIBSSH2_FREE(session, data); _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, "Data too short when extracting extname"); goto sftp_init_error; } - if(_libssh2_get_string(&buf, &extdata, NULL)) { + if(_libssh2_get_string(&buf, &extdata, &extdata_len)) { LIBSSH2_FREE(session, data); _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, "Data too short when extracting extdata"); goto sftp_init_error; } + + if(extdata_len > 0) { + char *extversion_str; + extversion_str = (char *)LIBSSH2_ALLOC(session, extdata_len + 1); + if(!extversion_str) { + _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for SSH_FXP_VERSION " + "packet"); + goto sftp_init_error; + } + memcpy(extversion_str, extdata, extdata_len); + extversion_str[extdata_len] = '\0'; + extversion = (uint32_t)strtol(extversion_str, NULL, 10); + LIBSSH2_FREE(session, extversion_str); + } + if(extname_len == 24 + && strncmp("posix-rename@openssh.com", (char *)extname, 24) == 0) { + sftp_handle->posix_rename_version = extversion; + } + } LIBSSH2_FREE(session, data); @@ -1161,7 +1166,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) + flags(4) */ sftp->open_packet_len = (uint32_t)(filename_len + 13 + - (open_file? (4 + sftp_attrsize(attrs.flags)) : 0)); + (open_file ? (4 + sftp_attrsize(attrs.flags)) : 0)); /* surprise! this starts out with nothing sent */ sftp->open_packet_sent = 0; @@ -1178,7 +1183,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, LIBSSH2_SFTP_ATTR_PFILETYPE_DIR); _libssh2_store_u32(&s, sftp->open_packet_len - 4); - *(s++) = open_file? SSH_FXP_OPEN : SSH_FXP_OPENDIR; + *(s++) = open_file ? SSH_FXP_OPEN : SSH_FXP_OPENDIR; sftp->open_request_id = sftp->request_id++; _libssh2_store_u32(&s, sftp->open_request_id); _libssh2_store_str(&s, filename, filename_len); @@ -1189,7 +1194,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, } _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "Sending %s open request", - open_file? "file" : "directory")); + open_file ? "file" : "directory")); sftp->open_state = libssh2_NB_state_created; } @@ -1271,7 +1276,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, if(LIBSSH2_FX_OK == sftp->last_errno) { _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "got HANDLE FXOK!")); + "got HANDLE FXOK")); LIBSSH2_FREE(session, data); @@ -1565,10 +1570,11 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, more packets */ count -= LIBSSH2_MIN(size, count); _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "read request id %d sent (offset: %d, size: %d)", - request_id, (int)chunk->offset, (int)chunk->len)); + "read request id %d sent (offset: %lu, size: %lu)", + request_id, (unsigned long)chunk->offset, + (unsigned long)chunk->len)); } - /* FALL-THROUGH */ + LIBSSH2_FALLTHROUGH(); case libssh2_NB_state_sent: sftp->read_state = libssh2_NB_state_idle; @@ -1608,7 +1614,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, /* move on to the next chunk with data to send */ chunk = _libssh2_list_next(&chunk->node); } - /* FALL-THROUGH */ + LIBSSH2_FALLTHROUGH(); case libssh2_NB_state_sent2: @@ -1688,7 +1694,6 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP READ error"); } - break; case SSH_FXP_DATA: if(chunk->offset != filep->offset) { @@ -1920,8 +1925,8 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, end: _libssh2_debug((session, LIBSSH2_TRACE_SFTP, - "libssh2_sftp_readdir_ex() return %d", - filename_len)); + "libssh2_sftp_readdir_ex() return %lu", + (unsigned long)filename_len)); return (ssize_t)filename_len; } @@ -2001,7 +2006,7 @@ end: sftp->readdir_state = libssh2_NB_state_idle; num_names = _libssh2_ntohu32(data + 5); - _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "%lu entries returned", + _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "%u entries returned", num_names)); if(!num_names) { LIBSSH2_FREE(session, data); @@ -2183,7 +2188,8 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, chunk = _libssh2_list_next(&chunk->node); } - /* fall-through */ + LIBSSH2_FALLTHROUGH(); + case libssh2_NB_state_sent: sftp->write_state = libssh2_NB_state_idle; @@ -3012,6 +3018,136 @@ libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, const char *source_filename, return rc; } +static int +sftp_posix_rename(LIBSSH2_SFTP *sftp, const char *source_filename, + size_t source_filename_len, + const char *dest_filename, + size_t dest_filename_len) +{ + LIBSSH2_CHANNEL *channel = sftp->channel; + LIBSSH2_SESSION *session = channel->session; + uint32_t packet_len; + size_t data_len = 0; + unsigned char *packet, *s, *data = NULL; + ssize_t rc; + uint32_t retcode; + + if(sftp->posix_rename_version != 1) { + return _libssh2_error(session, LIBSSH2_FX_OP_UNSUPPORTED, + "Server does not support" + "posix-rename@openssh.com"); + } + + if(source_filename_len > UINT32_MAX || + dest_filename_len > UINT32_MAX || + 45 + source_filename_len + dest_filename_len > UINT32_MAX) { + return _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Input too large" + "posix-rename@openssh.com"); + } + + packet_len = (uint32_t)(45 + source_filename_len + dest_filename_len); + + /* 45 = packet_len(4) + packet_type(1) + request_id(4) + + string_len(4) + strlen("posix-rename@openssh.com")(24) + + oldpath_len(4) + source_filename_len + + newpath_len(4) + dest_filename_len */ + + if(sftp->posix_rename_state == libssh2_NB_state_idle) { + _libssh2_debug((session, LIBSSH2_TRACE_SFTP, + "Issuing posix_rename command")); + s = packet = LIBSSH2_ALLOC(session, packet_len); + if(!packet) { + return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for FXP_EXTENDED " + "packet"); + } + + _libssh2_store_u32(&s, packet_len - 4); + *(s++) = SSH_FXP_EXTENDED; + sftp->posix_rename_request_id = sftp->request_id++; + _libssh2_store_u32(&s, sftp->posix_rename_request_id); + _libssh2_store_str(&s, "posix-rename@openssh.com", 24); + _libssh2_store_str(&s, source_filename, source_filename_len); + _libssh2_store_str(&s, dest_filename, dest_filename_len); + + sftp->posix_rename_state = libssh2_NB_state_created; + } + else { + packet = sftp->posix_rename_packet; + } + + if(sftp->posix_rename_state == libssh2_NB_state_created) { + rc = _libssh2_channel_write(channel, 0, packet, packet_len); + if(rc == LIBSSH2_ERROR_EAGAIN || + (0 <= rc && rc < (ssize_t)packet_len)) { + sftp->posix_rename_packet = packet; + return LIBSSH2_ERROR_EAGAIN; + } + + LIBSSH2_FREE(session, packet); + sftp->posix_rename_packet = NULL; + + if(rc < 0) { + sftp->posix_rename_state = libssh2_NB_state_idle; + return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, + "_libssh2_channel_write() failed"); + } + sftp->posix_rename_state = libssh2_NB_state_sent; + } + + rc = sftp_packet_require(sftp, SSH_FXP_STATUS, + sftp->posix_rename_request_id, + &data, &data_len, 9); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return (int)rc; + } + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { + LIBSSH2_FREE(session, data); + } + return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, + "SFTP posix_rename packet too short"); + } + else if(rc) { + sftp->posix_rename_state = libssh2_NB_state_idle; + return (int)_libssh2_error(session, (int)rc, + "Error waiting for FXP EXTENDED REPLY"); + } + + sftp->posix_rename_state = libssh2_NB_state_idle; + + retcode = _libssh2_ntohu32(data + 5); + LIBSSH2_FREE(session, data); + + if(retcode != LIBSSH2_FX_OK) { + sftp->last_errno = retcode; + return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, + "posix_rename failed"); + } + + return 0; +} + +/* libssh2_sftp_posix_rename_ex + * Rename a file on the remote server using the posix-rename@openssh.com + * extension. + */ +LIBSSH2_API int +libssh2_sftp_posix_rename_ex(LIBSSH2_SFTP *sftp, const char *source_filename, + size_t source_filename_len, + const char *dest_filename, + size_t dest_filename_len) +{ + int rc; + if(!sftp) + return LIBSSH2_ERROR_BAD_USE; + BLOCK_ADJUST(rc, sftp->channel->session, + sftp_posix_rename(sftp, source_filename, source_filename_len, + dest_filename, dest_filename_len)); + return rc; +} + /* sftp_fstatvfs * Get file system statistics */ @@ -3379,7 +3515,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_FREE(session, data); if(retcode == LIBSSH2_FX_OK) { - _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "OK!")); + _libssh2_debug((session, LIBSSH2_TRACE_SFTP, "OK")); return 0; } else { diff --git a/libssh2/src/sftp.h b/libssh2/src/sftp.h index 267301f1b..264f823bc 100644 --- a/libssh2/src/sftp.h +++ b/libssh2/src/sftp.h @@ -1,8 +1,8 @@ -#ifndef __LIBSSH2_SFTP_H -#define __LIBSSH2_SFTP_H +#ifndef LIBSSH2_SFTP_PRIV_H +#define LIBSSH2_SFTP_PRIV_H /* - * Copyright (C) 2010 - 2012 by Daniel Stenberg - * Author: Daniel Stenberg + * Copyright (C) Daniel Stenberg + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -37,6 +37,7 @@ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * + * SPDX-License-Identifier: BSD-3-Clause */ /* @@ -77,7 +78,8 @@ struct _LIBSSH2_SFTP_PACKET typedef struct _LIBSSH2_SFTP_PACKET LIBSSH2_SFTP_PACKET; -#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */ +/* Increasing from 256 to 4092 since OpenSSH doesn't honor it. */ +#define SFTP_HANDLE_MAXLEN 4092 /* according to spec, this should be 256! */ struct _LIBSSH2_SFTP_HANDLE { @@ -136,7 +138,7 @@ struct _LIBSSH2_SFTP { LIBSSH2_CHANNEL *channel; - uint32_t request_id, version; + uint32_t request_id, version, posix_rename_version; struct list_head packets; @@ -201,6 +203,11 @@ struct _LIBSSH2_SFTP unsigned char *rename_s; uint32_t rename_request_id; + /* State variables used in libssh2_sftp_posix_rename_ex() */ + libssh2_nonblocking_states posix_rename_state; + unsigned char *posix_rename_packet; + uint32_t posix_rename_request_id; + /* State variables used in libssh2_sftp_fstatvfs() */ libssh2_nonblocking_states fstatvfs_state; unsigned char *fstatvfs_packet; @@ -232,4 +239,4 @@ struct _LIBSSH2_SFTP uint32_t symlink_request_id; }; -#endif /* __LIBSSH2_SFTP_H */ +#endif /* LIBSSH2_SFTP_PRIV_H */ diff --git a/libssh2/src/transport.c b/libssh2/src/transport.c index 6d902d337..e1120656c 100644 --- a/libssh2/src/transport.c +++ b/libssh2/src/transport.c @@ -1,6 +1,6 @@ -/* Copyright (C) 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2009-2010 by Daniel Stenberg - * Author: Daniel Stenberg +/* Copyright (C) The Written Word, Inc. + * Copyright (C) Daniel Stenberg + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ /* @@ -49,9 +51,6 @@ #include "transport.h" #include "mac.h" -#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */ -#define MAX_MACSIZE 64 /* MUST fit biggest MAC length we support */ - #ifdef LIBSSH2DEBUG #define UNPRINTABLE_CHAR '.' static void @@ -70,8 +69,8 @@ debugdump(LIBSSH2_SESSION * session, return; } - used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n", - desc, (int) size); + used = snprintf(buffer, sizeof(buffer), "=> %s (%lu bytes)\n", + desc, (unsigned long) size); if(session->tracehandler) (session->tracehandler)(session, session->tracehandler_context, buffer, used); @@ -157,7 +156,7 @@ decrypt(LIBSSH2_SESSION * session, unsigned char *source, lowerfirstlast = LAST_BLOCK; } - if(session->remote.crypt->crypt(session, source, decryptlen, + if(session->remote.crypt->crypt(session, 0, source, decryptlen, &session->remote.crypt_abstract, lowerfirstlast)) { LIBSSH2_FREE(session, p->payload); @@ -187,32 +186,39 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) struct transportpacket *p = &session->packet; int rc; int compressed; + const LIBSSH2_MAC_METHOD *remote_mac = NULL; + uint32_t seq = session->remote.seqno; + + if(!encrypted || (!CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET) && + !CRYPT_FLAG_R(session, INTEGRATED_MAC))) { + remote_mac = session->remote.mac; + } if(session->fullpacket_state == libssh2_NB_state_idle) { session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED; session->fullpacket_payload_len = p->packet_length - 1; - if(encrypted && !CRYPT_FLAG_L(session, INTEGRATED_MAC)) { + if(encrypted && remote_mac) { /* Calculate MAC hash */ - int etm = session->remote.mac->etm; - size_t mac_len = session->remote.mac->mac_len; + int etm = remote_mac->etm; + size_t mac_len = remote_mac->mac_len; if(etm) { /* store hash here */ - session->remote.mac->hash(session, macbuf, - session->remote.seqno, - p->payload, p->total_num - mac_len, - NULL, 0, - &session->remote.mac_abstract); + remote_mac->hash(session, macbuf, + session->remote.seqno, + p->payload, p->total_num - mac_len, + NULL, 0, + &session->remote.mac_abstract); } else { /* store hash here */ - session->remote.mac->hash(session, macbuf, - session->remote.seqno, - p->init, 5, - p->payload, - session->fullpacket_payload_len, - &session->remote.mac_abstract); + remote_mac->hash(session, macbuf, + session->remote.seqno, + p->init, 5, + p->payload, + session->fullpacket_payload_len, + &session->remote.mac_abstract); } /* Compare the calculated hash with the MAC we just read from @@ -272,6 +278,10 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) p->payload = decrypt_buffer; } } + else if(encrypted && CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET)) { + /* etm trim off padding byte from payload */ + memmove(p->payload, &p->payload[1], p->packet_length - 1); + } session->remote.seqno++; @@ -318,7 +328,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) if(session->fullpacket_state == libssh2_NB_state_created) { rc = _libssh2_packet_add(session, p->payload, session->fullpacket_payload_len, - session->fullpacket_macstate); + session->fullpacket_macstate, seq); if(rc == LIBSSH2_ERROR_EAGAIN) return rc; if(rc) { @@ -329,6 +339,11 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) session->fullpacket_state = libssh2_NB_state_idle; + if(session->kex_strict && + session->fullpacket_packet_type == SSH_MSG_NEWKEYS) { + session->remote.seqno = 0; + } + return session->fullpacket_packet_type; } @@ -365,6 +380,8 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) use them */ int encrypted = 1; /* whether the packet is encrypted or not */ int firstlast = FIRST_BLOCK; /* if the first or last block to decrypt */ + unsigned int auth_len = 0; /* length of the authentication tag */ + const LIBSSH2_MAC_METHOD *remote_mac = NULL; /* The remote MAC, if used */ /* default clear the bit */ session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; @@ -420,7 +437,16 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) make the checks below work fine still */ } - etm = encrypted && session->local.mac ? session->local.mac->etm : 0; + if(encrypted) { + if(CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET)) { + auth_len = session->remote.crypt->auth_len; + } + else { + remote_mac = session->remote.mac; + } + } + + etm = encrypted && remote_mac ? remote_mac->etm : 0; /* read/use a whole big chunk into a temporary area stored in the LIBSSH2_SESSION struct. We will decrypt data from that @@ -435,7 +461,9 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) /* if remainbuf turns negative we have a bad internal error */ assert(remainbuf >= 0); - if(remainbuf < blocksize) { + if(remainbuf < blocksize || + (CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET) + && ((ssize_t)p->total_num) > remainbuf)) { /* If we have less than a blocksize left, it is too little data to deal with, read more */ ssize_t nread; @@ -465,13 +493,15 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) return LIBSSH2_ERROR_EAGAIN; } _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Error recving %d bytes (got %d)", - PACKETBUFSIZE - remainbuf, -nread)); + "Error recving %ld bytes (got %ld)", + (long)(PACKETBUFSIZE - remainbuf), + (long)-nread)); return LIBSSH2_ERROR_SOCKET_RECV; } _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Recved %d/%d bytes to %p+%d", nread, - PACKETBUFSIZE - remainbuf, p->buf, remainbuf)); + "Recved %ld/%ld bytes to %p+%ld", (long)nread, + (long)(PACKETBUFSIZE - remainbuf), (void *)p->buf, + (long)remainbuf)); debugdump(session, "libssh2_transport_read() raw", &p->buf[remainbuf], nread); @@ -509,7 +539,35 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) } if(etm) { - p->packet_length = _libssh2_ntohu32(&p->buf[p->readidx]); + /* etm size field is not encrypted */ + memcpy(block, &p->buf[p->readidx], 4); + memcpy(p->init, &p->buf[p->readidx], 4); + } + else if(encrypted && session->remote.crypt->get_len) { + unsigned int len = 0; + unsigned char *ptr = NULL; + + rc = session->remote.crypt->get_len(session, + session->remote.seqno, + &p->buf[p->readidx], + numbytes, + &len, + &session->remote.crypt_abstract); + + if(rc != LIBSSH2_ERROR_NONE) { + p->total_num = 0; /* no packet buffer available */ + if(p->payload) + LIBSSH2_FREE(session, p->payload); + p->payload = NULL; + return rc; + } + + /* store size in buffers for use below */ + ptr = &block[0]; + _libssh2_store_u32(&ptr, len); + + ptr = &p->init[0]; + _libssh2_store_u32(&ptr, len); } else { if(encrypted) { @@ -539,33 +597,61 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) p->packet_length = _libssh2_ntohu32(block); } - if(p->packet_length < 1) { - return LIBSSH2_ERROR_DECRYPT; - } - else if(p->packet_length > LIBSSH2_PACKET_MAXPAYLOAD) { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; - } - - if(etm) { - /* we collect entire undecrypted packet including the - packet length field that we run MAC over */ - total_num = 4 + p->packet_length + - session->remote.mac->mac_len; - } - else { - /* padding_length has not been authenticated yet, but it won't - actually be used (except for the sanity check immediately - following) until after the entire packet is authenticated, - so this is safe. */ - p->padding_length = block[4]; - if(p->padding_length > p->packet_length - 1) { + if(!encrypted || !CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET)) { + if(p->packet_length < 1) { return LIBSSH2_ERROR_DECRYPT; } + else if(p->packet_length > LIBSSH2_PACKET_MAXPAYLOAD) { + return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + } - /* total_num is the number of bytes following the initial - (5 bytes) packet length and padding length fields */ - total_num = p->packet_length - 1 + - (encrypted ? session->remote.mac->mac_len : 0); + if(etm) { + /* we collect entire undecrypted packet including the + packet length field that we run MAC over */ + p->packet_length = _libssh2_ntohu32(block); + total_num = 4 + p->packet_length + + remote_mac->mac_len; + } + else { + /* padding_length has not been authenticated yet, but it + won't actually be used (except for the sanity check + immediately following) until after the entire packet is + authenticated, so this is safe. */ + p->padding_length = block[4]; + if(p->padding_length > p->packet_length - 1) { + return LIBSSH2_ERROR_DECRYPT; + } + + /* total_num is the number of bytes following the initial + (5 bytes) packet length and padding length fields */ + total_num = p->packet_length - 1 + + (encrypted ? remote_mac->mac_len : 0); + } + } + else { + /* advance the read pointer past size field if the packet + length is not required for decryption */ + + /* add size field to be included in total packet size + * calculation so it doesn't get dropped off on subsequent + * partial reads + */ + total_num = 4; + + p->packet_length = _libssh2_ntohu32(block); + if(p->packet_length < 1) + return LIBSSH2_ERROR_DECRYPT; + + /* total_num may include size field, however due to existing + * logic it needs to be removed after the entire packet is read + */ + + total_num += p->packet_length + + (remote_mac ? remote_mac->mac_len : 0) + auth_len; + + /* don't know what padding is until we decrypt the full + packet */ + p->padding_length = 0; } /* RFC4253 section 6.1 Maximum Packet Length says: @@ -590,32 +676,42 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) /* init write pointer to start of payload buffer */ p->wptr = p->payload; - if(!etm && blocksize > 5) { - /* copy the data from index 5 to the end of - the blocksize from the temporary buffer to - the start of the decrypted buffer */ - if(blocksize - 5 <= (int) total_num) { - memcpy(p->wptr, &block[5], blocksize - 5); - p->wptr += blocksize - 5; /* advance write pointer */ - if(etm) { - /* advance past unencrypted packet length */ - p->wptr += 4; + if(!encrypted || !CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET)) { + if(!etm && blocksize > 5) { + /* copy the data from index 5 to the end of + the blocksize from the temporary buffer to + the start of the decrypted buffer */ + if(blocksize - 5 <= (int) total_num) { + memcpy(p->wptr, &block[5], blocksize - 5); + p->wptr += blocksize - 5; /* advance write pointer */ + if(etm) { + /* advance past unencrypted packet length */ + p->wptr += 4; + } + } + else { + if(p->payload) + LIBSSH2_FREE(session, p->payload); + return LIBSSH2_ERROR_OUT_OF_BOUNDARY; } } - else { - if(p->payload) - LIBSSH2_FREE(session, p->payload); - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; - } + + /* init the data_num field to the number of bytes of + the package read so far */ + p->data_num = p->wptr - p->payload; + + /* we already dealt with a blocksize worth of data */ + if(!etm) + numbytes -= blocksize; } + else { + /* haven't started reading payload yet */ + p->data_num = 0; - /* init the data_num field to the number of bytes of - the package read so far */ - p->data_num = p->wptr - p->payload; - - /* we already dealt with a blocksize worth of data */ - if(!etm) - numbytes -= blocksize; + /* we already dealt with packet size worth of data */ + if(!encrypted) + numbytes -= 4; + } } /* how much there is left to add to the current payload @@ -628,12 +724,26 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) numbytes = remainpack; } + if(encrypted && CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET)) { + if(numbytes < remainpack) { + /* need a full packet before checking MAC */ + session->socket_block_directions |= + LIBSSH2_SESSION_BLOCK_INBOUND; + return LIBSSH2_ERROR_EAGAIN; + } + + /* we have a full packet, now remove the size field from numbytes + and total_num to process only the packet data */ + numbytes -= 4; + p->total_num -= 4; + } + if(encrypted && !etm) { /* At the end of the incoming stream, there is a MAC, and we don't want to decrypt that since we need it "raw". We MUST however decrypt the padding data since it is used for the hash later on. */ - int skip = session->remote.mac->mac_len; + int skip = (remote_mac ? remote_mac->mac_len : 0) + auth_len; if(CRYPT_FLAG_R(session, INTEGRATED_MAC)) /* This crypto method DOES need the MAC to go through @@ -680,11 +790,44 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) /* if there are bytes to decrypt, do that */ if(numdecrypt > 0) { /* now decrypt the lot */ - rc = decrypt(session, &p->buf[p->readidx], p->wptr, numdecrypt, - firstlast); - if(rc != LIBSSH2_ERROR_NONE) { - p->total_num = 0; /* no packet buffer available */ - return rc; + if(CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET)) { + rc = session->remote.crypt->crypt(session, + session->remote.seqno, + &p->buf[p->readidx], + numdecrypt, + &session->remote.crypt_abstract, + 0); + + if(rc != LIBSSH2_ERROR_NONE) { + p->total_num = 0; /* no packet buffer available */ + return rc; + } + + memcpy(p->wptr, &p->buf[p->readidx], numbytes); + + /* advance read index past size field now that we've decrypted + full packet */ + p->readidx += 4; + + /* include auth tag in bytes decrypted */ + numdecrypt += auth_len; + + /* set padding now that the packet has been verified and + decrypted */ + p->padding_length = p->wptr[0]; + + if(p->padding_length > p->packet_length - 1) { + return LIBSSH2_ERROR_DECRYPT; + } + } + else { + rc = decrypt(session, &p->buf[p->readidx], p->wptr, numdecrypt, + firstlast); + + if(rc != LIBSSH2_ERROR_NONE) { + p->total_num = 0; /* no packet buffer available */ + return rc; + } } /* advance the read pointer */ @@ -776,7 +919,8 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data, make the caller really notice his/hers flaw, we return error for this case */ _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Address is different, but will resume nonetheless")); + "Address is different, returning EAGAIN")); + return LIBSSH2_ERROR_EAGAIN; } *ret = 1; /* set to make our parent return */ @@ -788,11 +932,12 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data, LIBSSH2_SOCKET_SEND_FLAGS(session)); if(rc < 0) _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", length, -rc)); + "Error sending %ld bytes: %ld", + (long)length, (long)-rc)); else { _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p+%d", rc, length, p->outbuf, - p->osent)); + "Sent %ld/%ld bytes at %p+%lu", (long)rc, (long)length, + (void *)p->outbuf, (unsigned long)p->osent)); debugdump(session, "libssh2_transport_write send()", &p->outbuf[p->osent], rc); } @@ -861,6 +1006,8 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, ssize_t ret; int rc; const unsigned char *orgdata = data; + const LIBSSH2_MAC_METHOD *local_mac = NULL; + unsigned int auth_len = 0; size_t orgdata_len = data_len; size_t crypt_offset, etm_crypt_offset; @@ -887,7 +1034,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, debugdump(session, "libssh2_transport_write plain2", data2, data2_len); /* FIRST, check if we have a pending write to complete. send_existing - only sanity-check data and data_len and not data2 and data2_len!! */ + only sanity-check data and data_len and not data2 and data2_len! */ rc = send_existing(session, data, data_len, &ret); if(rc) return rc; @@ -900,7 +1047,15 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0; - etm = encrypted && session->local.mac ? session->local.mac->etm : 0; + if(encrypted && session->local.crypt && + CRYPT_FLAG_R(session, REQUIRES_FULL_PACKET)) { + auth_len = session->local.crypt->auth_len; + } + else { + local_mac = session->local.mac; + } + + etm = encrypted && local_mac ? local_mac->etm : 0; compressed = session->local.comp && session->local.comp->compress && @@ -965,7 +1120,8 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, 4 for the packet_length field */ /* subtract 4 bytes of the packet_length field when padding AES-GCM or with ETM */ - crypt_offset = (etm || (encrypted && CRYPT_FLAG_R(session, PKTLEN_AAD))) + crypt_offset = (etm || auth_len || + (encrypted && CRYPT_FLAG_R(session, PKTLEN_AAD))) ? 4 : 0; etm_crypt_offset = etm ? 4 : 0; @@ -996,7 +1152,9 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, /* append the MAC length to the total_length size */ total_length = - packet_length + (encrypted ? session->local.mac->mac_len : 0); + packet_length + (encrypted && local_mac ? local_mac->mac_len : 0); + + total_length += auth_len; /* store packet_length, which is the size of the whole packet except the MAC and the packet_length field itself */ @@ -1019,61 +1177,78 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, fields except the MAC field itself. This is skipped in the INTEGRATED_MAC case, where the crypto algorithm also does its own hash. */ - if(!etm && !CRYPT_FLAG_R(session, INTEGRATED_MAC)) { - session->local.mac->hash(session, p->outbuf + packet_length, - session->local.seqno, p->outbuf, - packet_length, NULL, 0, - &session->local.mac_abstract); + if(!etm && local_mac && !CRYPT_FLAG_L(session, INTEGRATED_MAC)) { + if(local_mac->hash(session, p->outbuf + packet_length, + session->local.seqno, p->outbuf, + packet_length, NULL, 0, + &session->local.mac_abstract)) + return _libssh2_error(session, LIBSSH2_ERROR_MAC_FAILURE, + "Failed to calculate MAC"); } - /* Encrypt the whole packet data, one block size at a time. - The MAC field is not encrypted unless INTEGRATED_MAC. */ - /* Some crypto back-ends could handle a single crypt() call for - encryption, but (presumably) others cannot, so break it up - into blocksize-sized chunks to satisfy them all. */ - for(i = etm_crypt_offset; i < packet_length; - i += session->local.crypt->blocksize) { - unsigned char *ptr = &p->outbuf[i]; - size_t bsize = LIBSSH2_MIN(session->local.crypt->blocksize, - (int)(packet_length-i)); - /* The INTEGRATED_MAC case always has an extra call below, so it - will never be LAST_BLOCK up here. */ - int firstlast = i == 0 ? FIRST_BLOCK : + if(CRYPT_FLAG_L(session, REQUIRES_FULL_PACKET)) { + if(session->local.crypt->crypt(session, + session->local.seqno, + p->outbuf, + packet_length, + &session->local.crypt_abstract, + 0)) { + return LIBSSH2_ERROR_ENCRYPT; + } + } + else { + /* Encrypt the whole packet data, one block size at a time. + The MAC field is not encrypted unless INTEGRATED_MAC. */ + /* Some crypto back-ends could handle a single crypt() call for + encryption, but (presumably) others cannot, so break it up + into blocksize-sized chunks to satisfy them all. */ + for(i = etm_crypt_offset; i < packet_length; + i += session->local.crypt->blocksize) { + unsigned char *ptr = &p->outbuf[i]; + size_t bsize = LIBSSH2_MIN(session->local.crypt->blocksize, + (int)(packet_length-i)); + /* The INTEGRATED_MAC case always has an extra call below, so + it will never be LAST_BLOCK up here. */ + int firstlast = i == 0 ? FIRST_BLOCK : (!CRYPT_FLAG_L(session, INTEGRATED_MAC) && (i == packet_length - session->local.crypt->blocksize) - ? LAST_BLOCK: MIDDLE_BLOCK); - /* In the AAD case, the last block would be only 4 bytes because - everything is offset by 4 since the initial packet_length isn't - encrypted. In this case, combine that last short packet with the - previous one since AES-GCM crypt() assumes that the entire MAC - is available in that packet so it can set that to the - authentication tag. */ - if(!CRYPT_FLAG_L(session, INTEGRATED_MAC)) - if(i > packet_length - 2*bsize) { - /* increase the final block size */ - bsize = packet_length - i; - /* advance the loop counter by the extra amount */ - i += bsize - session->local.crypt->blocksize; - } - _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "crypting bytes %d-%d", i, - i + session->local.crypt->blocksize - 1)); - if(session->local.crypt->crypt(session, ptr, - bsize, - &session->local.crypt_abstract, - firstlast)) - return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */ - } - /* Call crypt() one last time so it can be filled in with the MAC */ - if(CRYPT_FLAG_L(session, INTEGRATED_MAC)) { - int authlen = session->local.mac->mac_len; - assert((size_t)total_length <= - packet_length + session->local.crypt->blocksize); - if(session->local.crypt->crypt(session, &p->outbuf[packet_length], - authlen, - &session->local.crypt_abstract, - LAST_BLOCK)) - return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */ + ? LAST_BLOCK : MIDDLE_BLOCK); + /* In the AAD case, the last block would be only 4 bytes + because everything is offset by 4 since the initial + packet_length isn't encrypted. In this case, combine that last + short packet with the previous one since AES-GCM crypt() + assumes that the entire MAC is available in that packet so it + can set that to the authentication tag. */ + if(!CRYPT_FLAG_L(session, INTEGRATED_MAC)) + if(i > packet_length - 2*bsize) { + /* increase the final block size */ + bsize = packet_length - i; + /* advance the loop counter by the extra amount */ + i += bsize - session->local.crypt->blocksize; + } + _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, + "crypting bytes %lu-%lu", (unsigned long)i, + (unsigned long)(i + bsize - 1))); + if(session->local.crypt->crypt(session, 0, ptr, + bsize, + &session->local.crypt_abstract, + firstlast)) + return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */ + } + + /* Call crypt one last time so it can be filled in with the MAC */ + if(CRYPT_FLAG_L(session, INTEGRATED_MAC)) { + int authlen = local_mac->mac_len; + assert((size_t)total_length <= + packet_length + session->local.crypt->blocksize); + if(session->local.crypt->crypt(session, + 0, + &p->outbuf[packet_length], + authlen, + &session->local.crypt_abstract, + LAST_BLOCK)) + return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */ + } } if(etm) { @@ -1082,24 +1257,31 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, calculated on the entire packet (length plain the rest encrypted), including all fields except the MAC field itself. */ - session->local.mac->hash(session, p->outbuf + packet_length, - session->local.seqno, p->outbuf, - packet_length, NULL, 0, - &session->local.mac_abstract); + if(local_mac->hash(session, p->outbuf + packet_length, + session->local.seqno, p->outbuf, + packet_length, NULL, 0, + &session->local.mac_abstract)) + return _libssh2_error(session, LIBSSH2_ERROR_MAC_FAILURE, + "Failed to calculate MAC"); } } session->local.seqno++; + if(session->kex_strict && data[0] == SSH_MSG_NEWKEYS) { + session->local.seqno = 0; + } + ret = LIBSSH2_SEND(session, p->outbuf, total_length, LIBSSH2_SOCKET_SEND_FLAGS(session)); if(ret < 0) _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", total_length, -ret)); + "Error sending %ld bytes: %ld", + (long)total_length, (long)-ret)); else { _libssh2_debug((session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p", - ret, total_length, p->outbuf)); + "Sent %ld/%ld bytes at %p", + (long)ret, (long)total_length, (void *)p->outbuf)); debugdump(session, "libssh2_transport_write send()", p->outbuf, ret); } diff --git a/libssh2/src/transport.h b/libssh2/src/transport.h index 7128bda7a..4b824e209 100644 --- a/libssh2/src/transport.h +++ b/libssh2/src/transport.h @@ -1,8 +1,8 @@ -#ifndef __LIBSSH2_TRANSPORT_H -#define __LIBSSH2_TRANSPORT_H -/* Copyright (C) 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2009-2010 by Daniel Stenberg - * Author: Daniel Stenberg +#ifndef LIBSSH2_TRANSPORT_H +#define LIBSSH2_TRANSPORT_H +/* Copyright (C) The Written Word, Inc. + * Copyright (C) Daniel Stenberg + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -38,6 +38,8 @@ * OF SUCH DAMAGE. * * This file handles reading and writing to the SECSH transport layer. RFC4253. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -82,4 +84,4 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, */ int _libssh2_transport_read(LIBSSH2_SESSION * session); -#endif /* __LIBSSH2_TRANSPORT_H */ +#endif /* LIBSSH2_TRANSPORT_H */ diff --git a/libssh2/src/userauth.c b/libssh2/src/userauth.c index 7745199bc..0040c3fa3 100644 --- a/libssh2/src/userauth.c +++ b/libssh2/src/userauth.c @@ -1,6 +1,6 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2005 Mikhail Gusarov - * Copyright (c) 2009-2014 by Daniel Stenberg +/* Copyright (C) Sara Golemon + * Copyright (C) Mikhail Gusarov + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -35,6 +35,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" @@ -51,6 +53,8 @@ #include "userauth.h" #include "userauth_kbd_packet.h" +#include /* strtol() */ + /* userauth_list * * List authentication methods @@ -816,11 +820,17 @@ struct privkey_file { const char *passphrase; }; +struct privkey_mem { + const char *passphrase; + const char *data; + size_t data_len; +}; + static int sign_frommemory(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract) { - struct privkey_file *pk_file = (struct privkey_file *) (*abstract); + struct privkey_mem *pk_mem = (struct privkey_mem *) (*abstract); const LIBSSH2_HOSTKEY_METHOD *privkeyobj; void *hostkey_abstract; struct iovec datavec; @@ -829,9 +839,9 @@ sign_frommemory(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, rc = memory_read_privatekey(session, &privkeyobj, &hostkey_abstract, session->userauth_pblc_method, session->userauth_pblc_method_len, - pk_file->filename, - strlen(pk_file->filename), - pk_file->passphrase); + pk_mem->data, + pk_mem->data_len, + pk_mem->passphrase); if(rc) return rc; @@ -1254,6 +1264,15 @@ size_t plain_method(char *method, size_t method_len) return 7; } + if(!strncmp("rsa-sha2-256-cert-v01@openssh.com", + method, + method_len) || + !strncmp("rsa-sha2-512-cert-v01@openssh.com", + method, + method_len)) { + return 12; + } + if(!strncmp("ecdsa-sha2-nistp256-cert-v01@openssh.com", method, method_len) || @@ -1291,6 +1310,31 @@ size_t plain_method(char *method, size_t method_len) return method_len; } +/* Function to check if the given version is less than pattern (OpenSSH 7.8) + * This function expects the input version in x.y* format + * (x being openssh major and y being openssh minor version) + * Returns 1 if the version is less than OpenSSH_7.8, 0 otherwise + */ +static int is_version_less_than_78(const char *version) +{ + char *endptr = NULL; + long major = 0; + int minor = 0; + + if(!version) + return 0; + + major = strtol(version, &endptr, 10); + if(!endptr || *endptr != '.') + return 0; /* Not a valid number */ + minor = (endptr + 1)[0] - '0'; + if((major >= 1 && major <= 6) || + (major == 7 && minor >= 0 && minor <= 7)) { + return 1; /* Version is in the specified range */ + } + return 0; +} + /** * @function _libssh2_key_sign_algorithm * @abstract Upgrades the algorithm used for public key signing RFC 8332 @@ -1318,7 +1362,14 @@ _libssh2_key_sign_algorithm(LIBSSH2_SESSION *session, size_t f_len = 0; int rc = 0; size_t match_len = 0; + const size_t suffix_len = 21; char *filtered_algs = NULL; + const char * const certSuffix = "-cert-v01@openssh.com"; + const char *remote_banner = NULL; + const char * const remote_ver_pre = "OpenSSH_"; + const char *remote_ver_start = NULL; + const char *remote_ver = NULL; + int SSH_BUG_SIGTYPE = 0; const char *supported_algs = _libssh2_supported_key_sign_algorithms(session, @@ -1337,6 +1388,25 @@ _libssh2_key_sign_algorithm(LIBSSH2_SESSION *session, return rc; } + /* Set "SSH_BUG_SIGTYPE" flag when the remote server version is OpenSSH 7.7 + or lower and when the RSA key in question is a certificate to ignore + "server-sig-algs" and only offer ssh-rsa signature algorithm for + RSA certs */ + remote_banner = libssh2_session_banner_get(session); + /* Extract version information from the banner */ + if(remote_banner) { + remote_ver_start = strstr(remote_banner, remote_ver_pre); + if(remote_ver_start) { + remote_ver = remote_ver_start + strlen(remote_ver_pre); + SSH_BUG_SIGTYPE = is_version_less_than_78(remote_ver); + if(SSH_BUG_SIGTYPE && *key_method_len == 28 && + memcmp(key_method, "ssh-rsa-cert-v01@openssh.com", + *key_method_len)) { + return LIBSSH2_ERROR_NONE; + } + } + } + s = session->server_sign_algorithms; i = filtered_algs; @@ -1404,15 +1474,27 @@ _libssh2_key_sign_algorithm(LIBSSH2_SESSION *session, } if(match) { - if(*key_method) - LIBSSH2_FREE(session, *key_method); - - *key_method = LIBSSH2_ALLOC(session, match_len); - if(key_method) { - memcpy(*key_method, match, match_len); - *key_method_len = match_len; + if(*key_method_len == 28 && + memcmp(key_method, "ssh-rsa-cert-v01@openssh.com", *key_method_len)) { + if(*key_method) + LIBSSH2_FREE(session, *key_method); + *key_method = LIBSSH2_ALLOC(session, match_len + suffix_len); + if(*key_method) { + memcpy(*key_method, match, match_len); + memcpy(*key_method + match_len, certSuffix, suffix_len); + *key_method_len = match_len + suffix_len; + } } else { + if(*key_method) + LIBSSH2_FREE(session, *key_method); + *key_method = LIBSSH2_ALLOC(session, match_len); + if(*key_method) { + memcpy(*key_method, match, match_len); + *key_method_len = match_len; + } + } + if(!key_method) { *key_method_len = 0; rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate key method upgrade"); @@ -1509,7 +1591,7 @@ retry_auth: _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Signing using %.*s", - session->userauth_pblc_method_len, + (int)session->userauth_pblc_method_len, session->userauth_pblc_method)); } @@ -1833,12 +1915,13 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session, { unsigned char *pubkeydata = NULL; size_t pubkeydata_len = 0; - struct privkey_file privkey_file; - void *abstract = &privkey_file; + struct privkey_mem privkey_mem; + void *abstract = &privkey_mem; int rc; - privkey_file.filename = privatekeydata; - privkey_file.passphrase = passphrase; + privkey_mem.data = privatekeydata; + privkey_mem.data_len = privatekeydata_len; + privkey_mem.passphrase = passphrase; if(session->userauth_pblc_state == libssh2_NB_state_idle) { if(publickeydata_len && publickeydata) { @@ -2179,7 +2262,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, if(session->userauth_kybd_responses[i].length <= (SIZE_MAX - 4 - session->userauth_kybd_packet_len)) { session->userauth_kybd_packet_len += - 4 + session->userauth_kybd_responses[i].length; + 4 + (size_t)session->userauth_kybd_responses[i].length; } else { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, diff --git a/libssh2/src/userauth.h b/libssh2/src/userauth.h index 10ec5a0f0..2f53ac5be 100644 --- a/libssh2/src/userauth.h +++ b/libssh2/src/userauth.h @@ -1,7 +1,7 @@ -#ifndef __LIBSSH2_USERAUTH_H -#define __LIBSSH2_USERAUTH_H -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2009-2010 by Daniel Stenberg +#ifndef LIBSSH2_USERAUTH_H +#define LIBSSH2_USERAUTH_H +/* Copyright (C) Sara Golemon + * Copyright (C) Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -36,6 +36,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ int @@ -48,4 +50,4 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, ((*sign_callback)), void *abstract); -#endif /* __LIBSSH2_USERAUTH_H */ +#endif /* LIBSSH2_USERAUTH_H */ diff --git a/libssh2/src/userauth_kbd_packet.c b/libssh2/src/userauth_kbd_packet.c index 298683879..216048e2e 100644 --- a/libssh2/src/userauth_kbd_packet.c +++ b/libssh2/src/userauth_kbd_packet.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2022, Xaver Loppenstedt +/* Copyright (C) Xaver Loppenstedt * All rights reserved. * * Redistribution and use in source and binary forms, @@ -33,6 +33,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" diff --git a/libssh2/src/userauth_kbd_packet.h b/libssh2/src/userauth_kbd_packet.h index cce0a7316..56e88b3f3 100644 --- a/libssh2/src/userauth_kbd_packet.h +++ b/libssh2/src/userauth_kbd_packet.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2022, Xaver Loppenstedt +/* Copyright (C) Xaver Loppenstedt * All rights reserved. * * Redistribution and use in source and binary forms, @@ -33,11 +33,13 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __LIBSSH2_USERAUTH_KBD_PARSE_H -#define __LIBSSH2_USERAUTH_KBD_PARSE_H +#ifndef LIBSSH2_USERAUTH_KBD_PACKET_H +#define LIBSSH2_USERAUTH_KBD_PACKET_H int userauth_keyboard_interactive_decode_info_request(LIBSSH2_SESSION *); -#endif /* __LIBSSH2_USERAUTH_KBD_PARSE_H */ +#endif /* LIBSSH2_USERAUTH_KBD_PACKET_H */ diff --git a/libssh2/src/version.c b/libssh2/src/version.c index 404b31979..d32ae64ae 100644 --- a/libssh2/src/version.c +++ b/libssh2/src/version.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2009 Daniel Stenberg. All rights reserved. +/* Copyright (C) Daniel Stenberg + * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -33,6 +34,7 @@ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * + * SPDX-License-Identifier: BSD-3-Clause */ #include "libssh2_priv.h" diff --git a/libssh2/src/wincng.c b/libssh2/src/wincng.c index ae3c18894..5d4b36b70 100644 --- a/libssh2/src/wincng.c +++ b/libssh2/src/wincng.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2020 Marc Hoersken + * Copyright (C) Marc Hoersken * All rights reserved. * * Redistribution and use in source and binary forms, @@ -34,6 +34,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #ifdef LIBSSH2_CRYPTO_C /* Compile this via crypto.c */ @@ -72,14 +74,21 @@ #define PEM_RSA_FOOTER "-----END RSA PRIVATE KEY-----" #define PEM_DSA_HEADER "-----BEGIN DSA PRIVATE KEY-----" #define PEM_DSA_FOOTER "-----END DSA PRIVATE KEY-----" +#define PEM_ECDSA_HEADER "-----BEGIN OPENSSH PRIVATE KEY-----" +#define PEM_ECDSA_FOOTER "-----END OPENSSH PRIVATE KEY-----" +#define OPENSSL_PRIVATEKEY_AUTH_MAGIC "openssh-key-v1" -/* Define this manually to avoid including and thus +/* Define these manually to avoid including and thus clashing with symbols. */ #ifndef STATUS_NOT_SUPPORTED #define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BB) #endif +#ifndef STATUS_INVALID_SIGNATURE +#define STATUS_INVALID_SIGNATURE ((NTSTATUS)0xC000A000) +#endif + /*******************************************************************/ /* * Windows CNG backend: Missing definitions (for MinGW[-w64]) @@ -92,9 +101,11 @@ #define BCRYPT_RNG_ALGORITHM L"RNG" #endif +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #ifndef BCRYPT_MD5_ALGORITHM #define BCRYPT_MD5_ALGORITHM L"MD5" #endif +#endif #ifndef BCRYPT_SHA1_ALGORITHM #define BCRYPT_SHA1_ALGORITHM L"SHA1" @@ -232,6 +243,93 @@ #define PKCS_RSA_PRIVATE_KEY ((LPCSTR)(size_t)43) #endif +static int +_libssh2_wincng_bignum_resize(_libssh2_bn* bn, ULONG length); + +/*******************************************************************/ +/* + * Windows CNG backend: ECDSA-specific declarations. + */ +#if LIBSSH2_ECDSA + +typedef enum { + WINCNG_ECC_KEYTYPE_ECDSA = 0, + WINCNG_ECC_KEYTYPE_ECDH = 1, +} _libssh2_wincng_ecc_keytype; + +typedef struct __libssh2_wincng_ecdsa_algorithm { + /* Algorithm name */ + const char *name; + + /* Key length, in bits */ + ULONG key_length; + + /* Length of each point, in bytes */ + ULONG point_length; + + /* Name of CNG algorithm provider, */ + /* indexed by _libssh2_wincng_ecc_keytype */ + LPCWSTR provider[2]; + + /* Magic for public key import, indexed by _libssh2_wincng_ecc_keytype */ + ULONG public_import_magic[2]; + + /* Magic for private key import, indexed by _libssh2_wincng_ecc_keytype */ + ULONG private_import_magic[2]; +} _libssh2_wincng_ecdsa_algorithm; + +/* Supported algorithms, indexed by libssh2_curve_type */ +static _libssh2_wincng_ecdsa_algorithm _wincng_ecdsa_algorithms[] = { + { + "ecdsa-sha2-nistp256", + 256, + 256 / 8, + { BCRYPT_ECDSA_P256_ALGORITHM, BCRYPT_ECDH_P256_ALGORITHM }, + { BCRYPT_ECDSA_PUBLIC_P256_MAGIC, BCRYPT_ECDH_PUBLIC_P256_MAGIC }, + { BCRYPT_ECDSA_PRIVATE_P256_MAGIC, BCRYPT_ECDH_PRIVATE_P256_MAGIC } + }, + { + "ecdsa-sha2-nistp384", + 384, + 384 / 8, + { BCRYPT_ECDSA_P384_ALGORITHM, BCRYPT_ECDH_P384_ALGORITHM }, + { BCRYPT_ECDSA_PUBLIC_P384_MAGIC, BCRYPT_ECDH_PUBLIC_P384_MAGIC }, + { BCRYPT_ECDSA_PRIVATE_P384_MAGIC, BCRYPT_ECDH_PRIVATE_P384_MAGIC } + }, + { + "ecdsa-sha2-nistp521", + 521, + ((521 + 7) & ~7) / 8, + { BCRYPT_ECDSA_P521_ALGORITHM, BCRYPT_ECDH_P521_ALGORITHM }, + { BCRYPT_ECDSA_PUBLIC_P521_MAGIC, BCRYPT_ECDH_PUBLIC_P521_MAGIC }, + { BCRYPT_ECDSA_PRIVATE_P521_MAGIC, BCRYPT_ECDH_PRIVATE_P521_MAGIC } + }, +}; + +/* An encoded point */ +typedef struct __libssh2_ecdsa_point { + libssh2_curve_type curve; + + const unsigned char *x; + ULONG x_len; + + const unsigned char *y; + ULONG y_len; +} _libssh2_ecdsa_point; + +/* Lookup libssh2_curve_type by name */ +static int +_libssh2_wincng_ecdsa_curve_type_from_name(IN const char *name, + OUT libssh2_curve_type *out_curve); + +/* Parse an OpenSSL-formatted ECDSA private key */ +static int +_libssh2_wincng_parse_ecdsa_privatekey(OUT _libssh2_wincng_ecdsa_key **key, + IN unsigned char *privatekey, + IN size_t privatekey_len); + +#endif + /*******************************************************************/ /* * Windows CNG backend: Generic functions @@ -244,6 +342,10 @@ _libssh2_wincng_init(void) { int ret; +#if LIBSSH2_ECDSA + unsigned int curve; +#endif + memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng)); ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRNG, @@ -252,11 +354,13 @@ _libssh2_wincng_init(void) _libssh2_wincng.hAlgRNG = NULL; } +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashMD5, BCRYPT_MD5_ALGORITHM, NULL, 0); if(!BCRYPT_SUCCESS(ret)) { _libssh2_wincng.hAlgHashMD5 = NULL; } +#endif ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA1, BCRYPT_SHA1_ALGORITHM, NULL, 0); if(!BCRYPT_SUCCESS(ret)) { @@ -278,12 +382,14 @@ _libssh2_wincng_init(void) _libssh2_wincng.hAlgHashSHA512 = NULL; } +#if LIBSSH2_MD5 ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacMD5, BCRYPT_MD5_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG); if(!BCRYPT_SUCCESS(ret)) { _libssh2_wincng.hAlgHmacMD5 = NULL; } +#endif ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA1, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG); @@ -386,15 +492,46 @@ _libssh2_wincng_init(void) if(!BCRYPT_SUCCESS(ret)) { _libssh2_wincng.hAlgDH = NULL; } + +#if LIBSSH2_ECDSA + for(curve = 0; curve < ARRAY_SIZE(_wincng_ecdsa_algorithms); curve++) { + BCRYPT_ALG_HANDLE alg_handle_ecdsa; + BCRYPT_ALG_HANDLE alg_handle_ecdh; + + ret = BCryptOpenAlgorithmProvider( + &alg_handle_ecdsa, + _wincng_ecdsa_algorithms[curve].provider[WINCNG_ECC_KEYTYPE_ECDSA], + NULL, + 0); + if(BCRYPT_SUCCESS(ret)) { + _libssh2_wincng.hAlgECDSA[curve] = alg_handle_ecdsa; + } + + ret = BCryptOpenAlgorithmProvider( + &alg_handle_ecdh, + _wincng_ecdsa_algorithms[curve].provider[WINCNG_ECC_KEYTYPE_ECDH], + NULL, + 0); + if(BCRYPT_SUCCESS(ret)) { + _libssh2_wincng.hAlgECDH[curve] = alg_handle_ecdh; + } + } +#endif } void _libssh2_wincng_free(void) { +#if LIBSSH2_ECDSA + unsigned int curve; +#endif + if(_libssh2_wincng.hAlgRNG) (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRNG, 0); +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM if(_libssh2_wincng.hAlgHashMD5) (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashMD5, 0); +#endif if(_libssh2_wincng.hAlgHashSHA1) (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA1, 0); if(_libssh2_wincng.hAlgHashSHA256) @@ -403,8 +540,10 @@ _libssh2_wincng_free(void) (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA384, 0); if(_libssh2_wincng.hAlgHashSHA512) (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA512, 0); +#if LIBSSH2_MD5 if(_libssh2_wincng.hAlgHmacMD5) (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacMD5, 0); +#endif if(_libssh2_wincng.hAlgHmacSHA1) (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA1, 0); if(_libssh2_wincng.hAlgHmacSHA256) @@ -426,6 +565,15 @@ _libssh2_wincng_free(void) if(_libssh2_wincng.hAlgDH) (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgDH, 0); +#if LIBSSH2_ECDSA + for(curve = 0; curve < ARRAY_SIZE(_wincng_ecdsa_algorithms); curve++) { + (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgECDSA[curve], + 0); + (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgECDH[curve], + 0); + } +#endif + memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng)); } @@ -459,8 +607,8 @@ _libssh2_wincng_safe_free(void *buf, size_t len) * if the size of src is smaller than dest then pad the "left" (MSB) * end with zeroes and copy the bits into the "right" (LSB) end. */ static void -memcpy_with_be_padding(unsigned char *dest, unsigned long dest_len, - unsigned char *src, unsigned long src_len) +memcpy_with_be_padding(unsigned char *dest, ULONG dest_len, + unsigned char *src, ULONG src_len) { if(dest_len > src_len) { memset(dest, 0, dest_len - src_len); @@ -475,12 +623,12 @@ memcpy_with_be_padding(unsigned char *dest, unsigned long dest_len, int _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx, - BCRYPT_ALG_HANDLE hAlg, unsigned long hashlen, - unsigned char *key, unsigned long keylen) + BCRYPT_ALG_HANDLE hAlg, ULONG hashlen, + unsigned char *key, ULONG keylen) { BCRYPT_HASH_HANDLE hHash; unsigned char *pbHashObject; - unsigned long dwHashObject, dwHash, cbData; + ULONG dwHashObject, dwHash, cbData; int ret; ret = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, @@ -524,11 +672,11 @@ _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx, int _libssh2_wincng_hash_update(_libssh2_wincng_hash_ctx *ctx, - const unsigned char *data, unsigned long datalen) + const void *data, ULONG datalen) { int ret; - ret = BCryptHashData(ctx->hHash, (unsigned char *)data, datalen, 0); + ret = BCryptHashData(ctx->hHash, (PUCHAR)data, datalen, 0); return BCRYPT_SUCCESS(ret) ? 0 : -1; } @@ -552,9 +700,9 @@ _libssh2_wincng_hash_final(_libssh2_wincng_hash_ctx *ctx, } int -_libssh2_wincng_hash(const unsigned char *data, unsigned long datalen, +_libssh2_wincng_hash(const unsigned char *data, ULONG datalen, BCRYPT_ALG_HANDLE hAlg, - unsigned char *hash, unsigned long hashlen) + unsigned char *hash, ULONG hashlen) { _libssh2_wincng_hash_ctx ctx; int ret; @@ -574,19 +722,70 @@ _libssh2_wincng_hash(const unsigned char *data, unsigned long datalen, * Windows CNG backend: HMAC functions */ -int -_libssh2_wincng_hmac_final(_libssh2_wincng_hash_ctx *ctx, - unsigned char *hash) +int _libssh2_hmac_ctx_init(libssh2_hmac_ctx *ctx) { - int ret; - - ret = BCryptFinishHash(ctx->hHash, hash, ctx->cbHash, 0); - - return BCRYPT_SUCCESS(ret) ? 0 : -1; + memset(ctx, 0, sizeof(*ctx)); + return 1; } -void -_libssh2_wincng_hmac_cleanup(_libssh2_wincng_hash_ctx *ctx) +#if LIBSSH2_MD5 +int _libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + int ret = _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacMD5, + MD5_DIGEST_LENGTH, + key, (ULONG) keylen); + + return ret == 0 ? 1 : 0; +} +#endif + +int _libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + int ret = _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA1, + SHA_DIGEST_LENGTH, + key, (ULONG) keylen); + + return ret == 0 ? 1 : 0; +} + +int _libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + int ret = _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA256, + SHA256_DIGEST_LENGTH, + key, (ULONG) keylen); + + return ret == 0 ? 1 : 0; +} + +int _libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx, + void *key, size_t keylen) +{ + int ret = _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA512, + SHA512_DIGEST_LENGTH, + key, (ULONG) keylen); + + return ret == 0 ? 1 : 0; +} + +int _libssh2_hmac_update(libssh2_hmac_ctx *ctx, + const void *data, size_t datalen) +{ + int ret = _libssh2_wincng_hash_update(ctx, data, (ULONG) datalen); + + return ret == 0 ? 1 : 0; +} + +int _libssh2_hmac_final(libssh2_hmac_ctx *ctx, void *data) +{ + int ret = BCryptFinishHash(ctx->hHash, data, ctx->cbHash, 0); + + return BCRYPT_SUCCESS(ret) ? 1 : 0; +} + +void _libssh2_hmac_cleanup(libssh2_hmac_ctx *ctx) { BCryptDestroyHash(ctx->hHash); ctx->hHash = NULL; @@ -602,20 +801,20 @@ _libssh2_wincng_hmac_cleanup(_libssh2_wincng_hash_ctx *ctx) * Windows CNG backend: Key functions */ -int +static int _libssh2_wincng_key_sha_verify(_libssh2_wincng_key_ctx *ctx, - unsigned long hashlen, + ULONG hashlen, const unsigned char *sig, - unsigned long sig_len, + ULONG sig_len, const unsigned char *m, - unsigned long m_len, - unsigned long flags) + ULONG m_len, + ULONG flags) { BCRYPT_PKCS1_PADDING_INFO paddingInfoPKCS1; BCRYPT_ALG_HANDLE hAlgHash; void *pPaddingInfo; unsigned char *data, *hash; - unsigned long datalen; + ULONG datalen; int ret; if(hashlen == SHA_DIGEST_LENGTH) { @@ -783,13 +982,13 @@ _libssh2_wincng_load_private_memory(LIBSSH2_SESSION *session, static int _libssh2_wincng_asn_decode(unsigned char *pbEncoded, - unsigned long cbEncoded, + DWORD cbEncoded, LPCSTR lpszStructType, unsigned char **ppbDecoded, - unsigned long *pcbDecoded) + DWORD *pcbDecoded) { unsigned char *pbDecoded = NULL; - unsigned long cbDecoded = 0; + DWORD cbDecoded = 0; int ret; ret = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, @@ -823,12 +1022,12 @@ _libssh2_wincng_asn_decode(unsigned char *pbEncoded, static int _libssh2_wincng_bn_ltob(unsigned char *pbInput, - unsigned long cbInput, + DWORD cbInput, unsigned char **ppbOutput, - unsigned long *pcbOutput) + DWORD *pcbOutput) { unsigned char *pbOutput; - unsigned long cbOutput, index, offset, length; + DWORD cbOutput, index, offset, length; if(cbInput < 1) { return 0; @@ -862,16 +1061,16 @@ _libssh2_wincng_bn_ltob(unsigned char *pbInput, static int _libssh2_wincng_asn_decode_bn(unsigned char *pbEncoded, - size_t cbEncoded, + DWORD cbEncoded, unsigned char **ppbDecoded, - unsigned long *pcbDecoded) + DWORD *pcbDecoded) { unsigned char *pbDecoded = NULL; PCRYPT_DATA_BLOB pbInteger; - unsigned long cbDecoded = 0, cbInteger; + DWORD cbDecoded = 0, cbInteger; int ret; - ret = _libssh2_wincng_asn_decode(pbEncoded, (unsigned long)cbEncoded, + ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded, X509_MULTI_BYTE_UINT, (void *)&pbInteger, &cbInteger); if(!ret) { @@ -890,18 +1089,18 @@ _libssh2_wincng_asn_decode_bn(unsigned char *pbEncoded, static int _libssh2_wincng_asn_decode_bns(unsigned char *pbEncoded, - size_t cbEncoded, + DWORD cbEncoded, unsigned char ***prpbDecoded, - unsigned long **prcbDecoded, - unsigned long *pcbCount) + DWORD **prcbDecoded, + DWORD *pcbCount) { PCRYPT_DER_BLOB pBlob; unsigned char **rpbDecoded; PCRYPT_SEQUENCE_OF_ANY pbDecoded; - unsigned long cbDecoded, *rcbDecoded, index, length; + DWORD cbDecoded, *rcbDecoded, index, length; int ret; - ret = _libssh2_wincng_asn_decode(pbEncoded, (unsigned long)cbEncoded, + ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded, X509_SEQUENCE_OF_ANY, (void *)&pbDecoded, &cbDecoded); if(!ret) { @@ -954,11 +1153,10 @@ _libssh2_wincng_asn_decode_bns(unsigned char *pbEncoded, #endif /* HAVE_LIBCRYPT32 */ #if LIBSSH2_RSA || LIBSSH2_DSA -static unsigned long -_libssh2_wincng_bn_size(const unsigned char *bignum, - unsigned long length) +static ULONG +_libssh2_wincng_bn_size(const unsigned char *bignum, ULONG length) { - unsigned long offset; + ULONG offset; if(!bignum) return 0; @@ -1004,7 +1202,7 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa, BCRYPT_KEY_HANDLE hKey; BCRYPT_RSAKEY_BLOB *rsakey; LPCWSTR lpszBlobType; - unsigned long keylen, offset, mlen, p1len = 0, p2len = 0; + ULONG keylen, offset, mlen, p1len = 0, p2len = 0; int ret; mlen = max(_libssh2_wincng_bn_size(ndata, nlen), @@ -1134,12 +1332,12 @@ _libssh2_wincng_rsa_new_private_parse(libssh2_rsa_ctx **rsa, { BCRYPT_KEY_HANDLE hKey; unsigned char *pbStructInfo; - unsigned long cbStructInfo; + DWORD cbStructInfo; int ret; (void)session; - ret = _libssh2_wincng_asn_decode(pbEncoded, (unsigned long)cbEncoded, + ret = _libssh2_wincng_asn_decode(pbEncoded, (DWORD)cbEncoded, PKCS_RSA_PRIVATE_KEY, &pbStructInfo, &cbStructInfo); @@ -1250,8 +1448,8 @@ _libssh2_wincng_rsa_sha1_verify(libssh2_rsa_ctx *rsa, size_t m_len) { return _libssh2_wincng_key_sha_verify(rsa, SHA_DIGEST_LENGTH, - sig, (unsigned long)sig_len, - m, (unsigned long)m_len, + sig, (ULONG)sig_len, + m, (ULONG)m_len, BCRYPT_PAD_PKCS1); } #endif @@ -1265,14 +1463,14 @@ _libssh2_wincng_rsa_sha2_verify(libssh2_rsa_ctx *rsa, const unsigned char *m, size_t m_len) { - return _libssh2_wincng_key_sha_verify(rsa, (unsigned long)hash_len, - sig, (unsigned long)sig_len, - m, (unsigned long)m_len, + return _libssh2_wincng_key_sha_verify(rsa, (ULONG)hash_len, + sig, (ULONG)sig_len, + m, (ULONG)m_len, BCRYPT_PAD_PKCS1); } #endif -int +static int _libssh2_wincng_rsa_sha_sign(LIBSSH2_SESSION *session, libssh2_rsa_ctx *rsa, const unsigned char *hash, @@ -1282,8 +1480,8 @@ _libssh2_wincng_rsa_sha_sign(LIBSSH2_SESSION *session, { BCRYPT_PKCS1_PADDING_INFO paddingInfo; unsigned char *data, *sig; - unsigned long cbData, datalen, siglen; - int ret; + ULONG cbData, datalen, siglen; + NTSTATUS ret; if(hash_len == SHA_DIGEST_LENGTH) paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM; @@ -1299,7 +1497,7 @@ _libssh2_wincng_rsa_sha_sign(LIBSSH2_SESSION *session, return -1; } - datalen = (unsigned long)hash_len; + datalen = (ULONG)hash_len; data = malloc(datalen); if(!data) { return -1; @@ -1325,7 +1523,7 @@ _libssh2_wincng_rsa_sha_sign(LIBSSH2_SESSION *session, } } else - ret = STATUS_NO_MEMORY; + ret = (NTSTATUS)STATUS_NO_MEMORY; } _libssh2_wincng_safe_free(data, datalen); @@ -1333,6 +1531,32 @@ _libssh2_wincng_rsa_sha_sign(LIBSSH2_SESSION *session, return BCRYPT_SUCCESS(ret) ? 0 : -1; } +int +_libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session, + libssh2_rsa_ctx *rsa, + const unsigned char *hash, + size_t hash_len, + unsigned char **signature, + size_t *signature_len) +{ + return _libssh2_wincng_rsa_sha_sign(session, rsa, + hash, hash_len, + signature, signature_len); +} + +int +_libssh2_wincng_rsa_sha2_sign(LIBSSH2_SESSION *session, + libssh2_rsa_ctx *rsa, + const unsigned char *hash, + size_t hash_len, + unsigned char **signature, + size_t *signature_len) +{ + return _libssh2_wincng_rsa_sha_sign(session, rsa, + hash, hash_len, + signature, signature_len); +} + void _libssh2_wincng_rsa_free(libssh2_rsa_ctx *rsa) { @@ -1369,7 +1593,7 @@ _libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa, BCRYPT_KEY_HANDLE hKey; BCRYPT_DSA_KEY_BLOB *dsakey; LPCWSTR lpszBlobType; - unsigned long keylen, offset, length; + ULONG keylen, offset, length; int ret; length = max(max(_libssh2_wincng_bn_size(pdata, plen), @@ -1469,12 +1693,12 @@ _libssh2_wincng_dsa_new_private_parse(libssh2_dsa_ctx **dsa, size_t cbEncoded) { unsigned char **rpbDecoded; - unsigned long *rcbDecoded, index, length; + DWORD *rcbDecoded, index, length; int ret; (void)session; - ret = _libssh2_wincng_asn_decode_bns(pbEncoded, cbEncoded, + ret = _libssh2_wincng_asn_decode_bns(pbEncoded, (DWORD)cbEncoded, &rpbDecoded, &rcbDecoded, &length); _libssh2_wincng_safe_free(pbEncoded, cbEncoded); @@ -1579,20 +1803,20 @@ _libssh2_wincng_dsa_sha1_verify(libssh2_dsa_ctx *dsa, size_t m_len) { return _libssh2_wincng_key_sha_verify(dsa, SHA_DIGEST_LENGTH, sig_fixed, - 40, m, (unsigned long)m_len, 0); + 40, m, (ULONG)m_len, 0); } int _libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa, const unsigned char *hash, - unsigned long hash_len, + size_t hash_len, unsigned char *sig_fixed) { unsigned char *data, *sig; - unsigned long cbData, datalen, siglen; - int ret; + ULONG cbData, datalen, siglen; + NTSTATUS ret; - datalen = hash_len; + datalen = (ULONG)hash_len; data = malloc(datalen); if(!data) { return -1; @@ -1616,10 +1840,10 @@ _libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa, _libssh2_wincng_safe_free(sig, siglen); } else - ret = STATUS_NO_MEMORY; + ret = (NTSTATUS)STATUS_NO_MEMORY; } else - ret = STATUS_NO_MEMORY; + ret = (NTSTATUS)STATUS_NO_MEMORY; } _libssh2_wincng_safe_free(data, datalen); @@ -1642,17 +1866,1227 @@ _libssh2_wincng_dsa_free(libssh2_dsa_ctx *dsa) #endif +/*******************************************************************/ +/* + * Windows CNG backend: ECDSA helper functions + */ + +#if LIBSSH2_ECDSA + +/* + * Decode an uncompressed point. + */ +static int +_libssh2_wincng_ecdsa_decode_uncompressed_point( + IN const unsigned char *encoded_point, + IN size_t encoded_point_len, + OUT _libssh2_ecdsa_point *point) +{ + unsigned int curve; + + if(!point) { + return LIBSSH2_ERROR_INVAL; + } + + /* Verify that the point uses uncompressed format */ + if(encoded_point_len == 0 || encoded_point[0] != 4) { + return LIBSSH2_ERROR_INVAL; + } + + for(curve = 0; curve < ARRAY_SIZE(_wincng_ecdsa_algorithms); curve++) { + if(_wincng_ecdsa_algorithms[curve].point_length == + (encoded_point_len - 1) / 2) { + + point->curve = curve; + + point->x = encoded_point + 1; + point->x_len = _wincng_ecdsa_algorithms[curve].point_length; + + point->y = point->x + point->x_len; + point->y_len = _wincng_ecdsa_algorithms[curve].point_length; + + return LIBSSH2_ERROR_NONE; + } + } + + return LIBSSH2_ERROR_INVAL; +} + +/* + * Create a IEEE P-1363 signature from a point. + * + * The IEEE P-1363 format is defined as r || s, + * where r and s are of the same length. + */ +static int +_libssh2_wincng_p1363signature_from_point(IN const unsigned char *r, + IN size_t r_len, + IN const unsigned char *s, + IN size_t s_len, + IN libssh2_curve_type curve, + OUT PUCHAR *signature, + OUT size_t *signature_length) +{ + const unsigned char *r_trimmed; + const unsigned char *s_trimmed; + size_t r_trimmed_len; + size_t s_trimmed_len; + + /* Validate parameters */ + if(curve >= ARRAY_SIZE(_wincng_ecdsa_algorithms)) { + return LIBSSH2_ERROR_INVAL; + } + + *signature = NULL; + *signature_length = (size_t) + _wincng_ecdsa_algorithms[curve].point_length * 2; + + /* Trim leading zero, if any */ + r_trimmed = r; + r_trimmed_len = r_len; + if(r_len > 0 && r[0] == '\0') { + r_trimmed++; + r_trimmed_len--; + } + + s_trimmed = s; + s_trimmed_len = s_len; + if(s_len > 0 && s[0] == '\0') { + s_trimmed++; + s_trimmed_len--; + } + + /* Concatenate into zero-filled buffer and zero-pad if necessary */ + *signature = calloc(1, *signature_length); + if(!*signature) { + return LIBSSH2_ERROR_ALLOC; + } + + memcpy( + *signature + (*signature_length / 2) - r_trimmed_len, + r_trimmed, + r_trimmed_len); + memcpy( + *signature + (*signature_length) - s_trimmed_len, + s_trimmed, + s_trimmed_len); + + return LIBSSH2_ERROR_NONE; +} + +/* + * Create a CNG public key from an ECC point. + */ +static int +_libssh2_wincng_publickey_from_point(IN _libssh2_wincng_ecc_keytype keytype, + IN _libssh2_ecdsa_point *point, + OUT BCRYPT_KEY_HANDLE *key) +{ + + int result = LIBSSH2_ERROR_NONE; + NTSTATUS status; + + PBCRYPT_ECCKEY_BLOB ecc_blob; + size_t ecc_blob_len; + + /* Validate parameters */ + if(!key) { + return LIBSSH2_ERROR_INVAL; + } + + if(point->x_len != point->y_len) { + return LIBSSH2_ERROR_INVAL; + } + + *key = NULL; + + /* Initialize a blob to import */ + ecc_blob_len = sizeof(BCRYPT_ECCKEY_BLOB) + point->x_len + point->y_len; + ecc_blob = malloc(ecc_blob_len); + if(!ecc_blob) { + return LIBSSH2_ERROR_ALLOC; + } + + ecc_blob->cbKey = point->x_len; + ecc_blob->dwMagic = + _wincng_ecdsa_algorithms[point->curve].public_import_magic[keytype]; + + /** Copy x, y */ + memcpy( + (PUCHAR)ecc_blob + sizeof(BCRYPT_ECCKEY_BLOB), + point->x, + point->x_len); + memcpy( + (PUCHAR)ecc_blob + sizeof(BCRYPT_ECCKEY_BLOB) + point->x_len, + point->y, + point->y_len); + + status = BCryptImportKeyPair( + keytype == WINCNG_ECC_KEYTYPE_ECDSA + ? _libssh2_wincng.hAlgECDSA[point->curve] + : _libssh2_wincng.hAlgECDH[point->curve], + NULL, + BCRYPT_ECCPUBLIC_BLOB, + key, + (PUCHAR)ecc_blob, + (ULONG)ecc_blob_len, + 0); + if(!BCRYPT_SUCCESS(status)) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + + result = LIBSSH2_ERROR_NONE; + +cleanup: + free(ecc_blob); + return result; +} + +/* + * Create a CNG private key from an ECC point. + */ +static int +_libssh2_wincng_privatekey_from_point(IN _libssh2_wincng_ecc_keytype keytype, + IN _libssh2_ecdsa_point *q, + IN unsigned char *d, + IN size_t d_len, + OUT BCRYPT_KEY_HANDLE *key) +{ + int result = LIBSSH2_ERROR_NONE; + NTSTATUS status; + + PBCRYPT_ECCKEY_BLOB ecc_blob; + size_t ecc_blob_len; + + /* Validate parameters */ + if(!key) { + return LIBSSH2_ERROR_INVAL; + } + + if(q->x_len != q->y_len) { + return LIBSSH2_ERROR_INVAL; + } + + *key = NULL; + + /* Initialize a blob to import */ + ecc_blob_len = + sizeof(BCRYPT_ECCPRIVATE_BLOB) + q->x_len + q->y_len + d_len; + ecc_blob = malloc(ecc_blob_len); + if(!ecc_blob) { + return LIBSSH2_ERROR_ALLOC; + } + + ecc_blob->cbKey = q->x_len; + ecc_blob->dwMagic = + _wincng_ecdsa_algorithms[q->curve].private_import_magic[keytype]; + + /* Copy x, y, d */ + memcpy( + (PUCHAR)ecc_blob + sizeof(BCRYPT_ECCKEY_BLOB), + q->x, + q->x_len); + memcpy( + (PUCHAR)ecc_blob + sizeof(BCRYPT_ECCKEY_BLOB) + q->x_len, + q->y, + q->y_len); + memcpy( + (PUCHAR)ecc_blob + sizeof(BCRYPT_ECCKEY_BLOB) + q->x_len + q->y_len, + d, + d_len); + + status = BCryptImportKeyPair( + keytype == WINCNG_ECC_KEYTYPE_ECDSA + ? _libssh2_wincng.hAlgECDSA[q->curve] + : _libssh2_wincng.hAlgECDH[q->curve], + NULL, + BCRYPT_ECCPRIVATE_BLOB, + key, + (PUCHAR)ecc_blob, + (ULONG)ecc_blob_len, + 0); + if(!BCRYPT_SUCCESS(status)) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + + result = LIBSSH2_ERROR_NONE; + +cleanup: + free(ecc_blob); + return result; +} + +/* + * Get the uncompressed point encoding for a CNG key. + */ +static int +_libssh2_wincng_uncompressed_point_from_publickey( + IN LIBSSH2_SESSION *session, + IN libssh2_curve_type curve, + IN BCRYPT_KEY_HANDLE key, + OUT PUCHAR *encoded_point, + OUT size_t *encoded_point_len) +{ + int result = LIBSSH2_ERROR_NONE; + NTSTATUS status; + + PBCRYPT_ECCKEY_BLOB ecc_blob = NULL; + ULONG ecc_blob_len; + PUCHAR point_x; + PUCHAR point_y; + + /* Validate parameters */ + if(curve >= ARRAY_SIZE(_wincng_ecdsa_algorithms)) { + return LIBSSH2_ERROR_INVAL; + } + + if(!encoded_point || !encoded_point_len) { + return LIBSSH2_ERROR_INVAL; + } + + *encoded_point = NULL; + *encoded_point_len = 0; + + /* + * Export point as BCRYPT_ECCKEY_BLOB, a dynamically-sized structure. + */ + status = BCryptExportKey(key, + NULL, + BCRYPT_ECCPUBLIC_BLOB, + NULL, + 0, + &ecc_blob_len, + 0); + if(BCRYPT_SUCCESS(status) && ecc_blob_len > 0) { + ecc_blob = LIBSSH2_ALLOC(session, ecc_blob_len); + if(!ecc_blob) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + status = BCryptExportKey(key, + NULL, + BCRYPT_ECCPUBLIC_BLOB, + (PUCHAR)ecc_blob, + ecc_blob_len, + &ecc_blob_len, + 0); + } + + if(!BCRYPT_SUCCESS(status)) { + result = _libssh2_error(session, + LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, + "Decoding the ECC public key failed"); + goto cleanup; + } + + point_x = (PUCHAR)ecc_blob + sizeof(BCRYPT_ECCKEY_BLOB); + point_y = (PUCHAR)ecc_blob + ecc_blob->cbKey + sizeof(BCRYPT_ECCKEY_BLOB); + + /* + * Create uncompressed point, which needs to look like the following: + * + * struct uncompressed_point { + * UCHAR tag = 4; // uncompressed + * PUCHAR[size] x; + * PUCHAR[size] y; + * } + */ + + *encoded_point_len = (size_t)ecc_blob->cbKey * 2 + 1; + *encoded_point = LIBSSH2_ALLOC(session, *encoded_point_len); + if(!*encoded_point) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + **encoded_point = 4; /* Uncompressed tag */ + memcpy((*encoded_point) + 1, point_x, ecc_blob->cbKey); + memcpy((*encoded_point) + 1 + ecc_blob->cbKey, point_y, ecc_blob->cbKey); + +cleanup: + if(ecc_blob) { + LIBSSH2_FREE(session, ecc_blob); + } + + return result; +} + +static void +_libssh_wincng_reverse_bytes(IN PUCHAR buffer, + IN size_t buffer_len) +{ + PUCHAR start = buffer; + PUCHAR end = buffer + buffer_len - 1; + while(start < end) { + unsigned char tmp = *end; + *end = *start; + *start = tmp; + start++; + end--; + } +} + +/*******************************************************************/ +/* + * Windows CNG backend: ECDSA functions + */ + +void +_libssh2_wincng_ecdsa_free(IN _libssh2_wincng_ecdsa_key *key) +{ + if(!key) { + return; + } + + (void)BCryptDestroyKey(key->handle); + free(key); +} + + +/* + * _libssh2_ecdsa_create_key + * + * Creates a local private ECDH key based on input curve + * and returns the public key in uncompressed point encoding. + */ + +int +_libssh2_wincng_ecdh_create_key(IN LIBSSH2_SESSION *session, + OUT _libssh2_wincng_ecdsa_key **privatekey, + OUT unsigned char **encoded_publickey, + OUT size_t *encoded_publickey_len, + IN libssh2_curve_type curve) +{ + int result = LIBSSH2_ERROR_NONE; + NTSTATUS status; + + BCRYPT_KEY_HANDLE key_handle = NULL; + + /* Validate parameters */ + if(curve >= ARRAY_SIZE(_wincng_ecdsa_algorithms)) { + return LIBSSH2_ERROR_INVAL; + } + + if(!_libssh2_wincng.hAlgECDH[curve]) { + return LIBSSH2_ERROR_INVAL; + } + + if(!privatekey || !encoded_publickey || !encoded_publickey_len) { + return LIBSSH2_ERROR_INVAL; + } + + *privatekey = NULL; + *encoded_publickey = NULL; + *encoded_publickey_len = 0; + + /* Create an ECDH key pair using the requested curve */ + status = BCryptGenerateKeyPair( + _libssh2_wincng.hAlgECDH[curve], + &key_handle, + _wincng_ecdsa_algorithms[curve].key_length, + 0); + if(!BCRYPT_SUCCESS(status)) { + result = _libssh2_error( + session, + LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, + "Creating ECC key pair failed"); + goto cleanup; + } + + status = BCryptFinalizeKeyPair(key_handle, 0); + if(!BCRYPT_SUCCESS(status)) { + result = _libssh2_error( + session, + LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, + "Creating ECDH key pair failed"); + goto cleanup; + } + + result = _libssh2_wincng_uncompressed_point_from_publickey( + session, + curve, + key_handle, + encoded_publickey, + encoded_publickey_len); + if(result != LIBSSH2_ERROR_NONE) { + result = _libssh2_error( + session, + LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, + "Exporting ECDH key pair failed"); + } + + *privatekey = malloc(sizeof(_libssh2_wincng_ecdsa_key)); + if(!*privatekey) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + (*privatekey)->curve = curve; + (*privatekey)->handle = key_handle; + +cleanup: + if(result != LIBSSH2_ERROR_NONE && key_handle) { + (void)BCryptDestroyKey(key_handle); + } + + if(result != LIBSSH2_ERROR_NONE && *privatekey) { + free(*privatekey); + } + + return result; +} + +/* + * _libssh2_ecdsa_curve_name_with_octal_new + * + * Creates an ECDSA public key from an uncompressed point. + */ + +int +_libssh2_wincng_ecdsa_curve_name_with_octal_new( + OUT _libssh2_wincng_ecdsa_key **key, + IN const unsigned char *publickey_encoded, + IN size_t publickey_encoded_len, + IN libssh2_curve_type curve) +{ + int result = LIBSSH2_ERROR_NONE; + + BCRYPT_KEY_HANDLE publickey_handle; + _libssh2_ecdsa_point publickey; + + /* Validate parameters */ + if(curve >= ARRAY_SIZE(_wincng_ecdsa_algorithms)) { + return LIBSSH2_ERROR_INVAL; + } + + if(!key) { + return LIBSSH2_ERROR_INVAL; + } + + *key = NULL; + + result = _libssh2_wincng_ecdsa_decode_uncompressed_point( + publickey_encoded, + publickey_encoded_len, + &publickey); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + result = _libssh2_wincng_publickey_from_point( + WINCNG_ECC_KEYTYPE_ECDSA, + &publickey, + &publickey_handle); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + *key = malloc(sizeof(_libssh2_wincng_ecdsa_key)); + if(!*key) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + (*key)->handle = publickey_handle; + (*key)->curve = curve; + +cleanup: + + return result; +} + +/* + * _libssh2_ecdh_gen_k + * + * Computes the shared secret K given a local private key, + * remote public key and length + */ + +int +_libssh2_wincng_ecdh_gen_k(OUT _libssh2_bn **secret, + IN _libssh2_wincng_ecdsa_key *privatekey, + IN const unsigned char *server_publickey_encoded, + IN size_t server_publickey_encoded_len) +{ + int result = LIBSSH2_ERROR_NONE; + NTSTATUS status; + + BCRYPT_KEY_HANDLE publickey_handle; + BCRYPT_SECRET_HANDLE agreed_secret_handle = NULL; + ULONG secret_len; + _libssh2_ecdsa_point server_publickey; + + /* Validate parameters */ + if(!secret) { + return LIBSSH2_ERROR_INVAL; + } + + *secret = NULL; + + /* Decode the public key */ + result = _libssh2_wincng_ecdsa_decode_uncompressed_point( + server_publickey_encoded, + server_publickey_encoded_len, + &server_publickey); + if(result != LIBSSH2_ERROR_NONE) { + return result; + } + + result = _libssh2_wincng_publickey_from_point( + WINCNG_ECC_KEYTYPE_ECDH, + &server_publickey, + &publickey_handle); + if(result != LIBSSH2_ERROR_NONE) { + return result; + } + + /* Establish the shared secret between ourselves and the peer */ + status = BCryptSecretAgreement( + privatekey->handle, + publickey_handle, + &agreed_secret_handle, + 0); + if(!BCRYPT_SUCCESS(status)) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + + /* Compute the size of the buffer that is needed to hold the derived + * shared secret. + * + * NB. The use of BCRYPT_KDF_RAW_SECRET requires Windows 10 or newer. + * On older versions, the BCryptDeriveKey returns STATUS_NOT_SUPPORTED. + */ + status = BCryptDeriveKey( + agreed_secret_handle, + BCRYPT_KDF_RAW_SECRET, + NULL, + NULL, + 0, + &secret_len, + 0); + if(!BCRYPT_SUCCESS(status)) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + + /* Allocate a secret bignum to be ready to receive the derived secret */ + *secret = _libssh2_wincng_bignum_init(); + if(!*secret) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + if(_libssh2_wincng_bignum_resize(*secret, secret_len)) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + /* And populate the secret bignum */ + status = BCryptDeriveKey( + agreed_secret_handle, + BCRYPT_KDF_RAW_SECRET, + NULL, + (*secret)->bignum, + secret_len, + &secret_len, + 0); + if(!BCRYPT_SUCCESS(status)) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + + /* BCRYPT_KDF_RAW_SECRET returns the little-endian representation of the + * raw secret, so we need to swap it to big endian order. + */ + + _libssh_wincng_reverse_bytes((*secret)->bignum, secret_len); + + result = LIBSSH2_ERROR_NONE; + +cleanup: + if(result != LIBSSH2_ERROR_NONE && agreed_secret_handle) { + _libssh2_wincng_bignum_free(*secret); + } + + if(result != LIBSSH2_ERROR_NONE && agreed_secret_handle) { + BCryptDestroySecret(agreed_secret_handle); + } + + return result; +} + +/* + * _libssh2_ecdsa_curve_type_from_name + * + */ +int +_libssh2_wincng_ecdsa_curve_type_from_name(IN const char *name, + OUT libssh2_curve_type *out_curve) +{ + unsigned int curve; + + /* Validate parameters */ + if(!out_curve) { + return LIBSSH2_ERROR_INVAL; + } + + for(curve = 0; curve < ARRAY_SIZE(_wincng_ecdsa_algorithms); curve++) { + if(strcmp(name, _wincng_ecdsa_algorithms[curve].name) == 0) { + *out_curve = curve; + return LIBSSH2_ERROR_NONE; + } + } + + return LIBSSH2_ERROR_INVAL; +} + +/* + * _libssh2_ecdsa_verify + * + * Verifies the ECDSA signature of a hashed message + * + */ + +int +_libssh2_wincng_ecdsa_verify(IN _libssh2_wincng_ecdsa_key *key, + IN const unsigned char *r, + IN size_t r_len, + IN const unsigned char *s, + IN size_t s_len, + IN const unsigned char *m, + IN size_t m_len) +{ + int result = LIBSSH2_ERROR_NONE; + NTSTATUS status; + + PUCHAR signature_p1363 = NULL; + size_t signature_p1363_len; + ULONG hash_len; + PUCHAR hash = NULL; + BCRYPT_ALG_HANDLE hash_alg; + + /* CNG expects signatures in IEEE P-1363 format. */ + result = _libssh2_wincng_p1363signature_from_point( + r, + r_len, + s, + s_len, + _libssh2_wincng_ecdsa_get_curve_type(key), + &signature_p1363, + &signature_p1363_len); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + /* Create hash over m */ + switch(_libssh2_wincng_ecdsa_get_curve_type(key)) { + case LIBSSH2_EC_CURVE_NISTP256: + hash_len = 256/8; + hash_alg = _libssh2_wincng.hAlgHashSHA256; + break; + + case LIBSSH2_EC_CURVE_NISTP384: + hash_len = 384/8; + hash_alg = _libssh2_wincng.hAlgHashSHA384; + break; + + case LIBSSH2_EC_CURVE_NISTP521: + hash_len = 512/8; + hash_alg = _libssh2_wincng.hAlgHashSHA512; + break; + + default: + return LIBSSH2_ERROR_INVAL; + } + + hash = malloc(hash_len); + result = _libssh2_wincng_hash( + m, + (ULONG)m_len, + hash_alg, + hash, + hash_len); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + /* Verify signature over hash */ + status = BCryptVerifySignature( + key->handle, + NULL, + hash, + hash_len, + signature_p1363, + (ULONG)signature_p1363_len, + 0); + + if(status == STATUS_INVALID_SIGNATURE) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + else if(!BCRYPT_SUCCESS(status)) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + + result = LIBSSH2_ERROR_NONE; + +cleanup: + if(hash) { + free(hash); + } + + if(signature_p1363) { + free(signature_p1363); + } + + return result; +} + +/* + *_libssh2_ecdsa_new_private + * + * Creates a new private key given a file path and password + * + */ + +int +_libssh2_wincng_ecdsa_new_private(OUT _libssh2_wincng_ecdsa_key **key, + IN LIBSSH2_SESSION *session, + IN const char *filename, + IN const unsigned char *passphrase) +{ + int result; + + FILE *file_handle = NULL; + unsigned char *data = NULL; + size_t datalen = 0; + + /* Validate parameters */ + if(!key || !session || !filename) { + return LIBSSH2_ERROR_INVAL; + } + + *key = NULL; + + if(passphrase && strlen((const char *)passphrase) > 0) { + return _libssh2_error( + session, + LIBSSH2_ERROR_INVAL, + "Passphrase-protected ECDSA private key files are unsupported"); + } + + file_handle = fopen(filename, FOPEN_READTEXT); + if(!file_handle) { + result = _libssh2_error( + session, + LIBSSH2_ERROR_INVAL, + "Opening the private key file failed"); + goto cleanup; + } + + result = _libssh2_pem_parse(session, + PEM_ECDSA_HEADER, + PEM_ECDSA_FOOTER, + passphrase, + file_handle, + &data, + &datalen); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + result = _libssh2_wincng_ecdsa_new_private_frommemory( + key, + session, + (const char *)data, + datalen, + passphrase); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + +cleanup: + if(file_handle) { + fclose(file_handle); + } + + if(data) { + LIBSSH2_FREE(session, data); + } + + return result; +} + +int +_libssh2_wincng_parse_ecdsa_privatekey(OUT _libssh2_wincng_ecdsa_key **key, + IN unsigned char *privatekey, + IN size_t privatekey_len) +{ + char *keytype = NULL; + size_t keytype_len; + + unsigned char *ignore; + size_t ignore_len; + + unsigned char *publickey; + size_t publickey_len; + + libssh2_curve_type curve_type; + int result; + uint32_t check1, check2; + struct string_buf data_buffer; + + _libssh2_ecdsa_point q; + unsigned char *d; + size_t d_len; + + BCRYPT_KEY_HANDLE key_handle = NULL; + + *key = NULL; + + data_buffer.data = privatekey; + data_buffer.dataptr = privatekey; + data_buffer.len = privatekey_len; + + /* Read the 2 checkints and check that they match */ + result = _libssh2_get_u32(&data_buffer, &check1); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + result = _libssh2_get_u32(&data_buffer, &check2); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + if(check1 != check2) { + result = LIBSSH2_ERROR_FILE; + goto cleanup; + } + + /* What follows is a key as defined in */ + /* draft-miller-ssh-agent, section-3.2.2 */ + + /* Read the key type */ + result = _libssh2_get_string(&data_buffer, + (unsigned char **)&keytype, + &keytype_len); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + result = _libssh2_wincng_ecdsa_curve_type_from_name(keytype, &curve_type); + if(result < 0) { + goto cleanup; + } + + /* Read the curve */ + result = _libssh2_get_string(&data_buffer, &ignore, &ignore_len); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + /* Read Q */ + result = _libssh2_get_string(&data_buffer, &publickey, &publickey_len); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + result = _libssh2_wincng_ecdsa_decode_uncompressed_point( + publickey, + publickey_len, + &q); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + /* Read d */ + result = _libssh2_get_bignum_bytes(&data_buffer, &d, &d_len); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + /* Ignore the rest (comment, etc) */ + + /* Use Q and d to create a key handle */ + result = _libssh2_wincng_privatekey_from_point( + WINCNG_ECC_KEYTYPE_ECDSA, + &q, + d, + d_len, + &key_handle); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + *key = malloc(sizeof(_libssh2_wincng_ecdsa_key)); + if(!*key) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + (*key)->curve = q.curve; + (*key)->handle = key_handle; + + result = LIBSSH2_ERROR_NONE; + +cleanup: + if(result != LIBSSH2_ERROR_NONE && key_handle) { + (void)BCryptDestroyKey(key_handle); + } + + return result; +} + +/* + * _libssh2_ecdsa_new_private + * + * Creates a new private key given a file data and password. + * ECDSA private key files use the decoding defined in PROTOCOL.key + * in the OpenSSL source tree. + */ +int +_libssh2_wincng_ecdsa_new_private_frommemory( + OUT _libssh2_wincng_ecdsa_key **key, + IN LIBSSH2_SESSION *session, + IN const char *data, + IN size_t data_len, + IN const unsigned char *passphrase) +{ + int result; + + struct string_buf data_buffer; + uint32_t index; + uint32_t key_count; + unsigned char *privatekey; + size_t privatekey_len; + + /* Validate parameters */ + if(!key || !session || !data) { + return LIBSSH2_ERROR_INVAL; + } + + *key = NULL; + + if(passphrase && strlen((const char *)passphrase) > 0) { + return _libssh2_error( + session, + LIBSSH2_ERROR_INVAL, + "Passphrase-protected ECDSA private key files are unsupported"); + } + + /* Read OPENSSL_PRIVATEKEY_AUTH_MAGIC */ + if(strncmp(data, OPENSSL_PRIVATEKEY_AUTH_MAGIC, data_len) != 0) { + result = -1; + goto cleanup; + } + + data_buffer.len = data_len; + data_buffer.data = (unsigned char *)data; + data_buffer.dataptr = + (unsigned char *)data + strlen(OPENSSL_PRIVATEKEY_AUTH_MAGIC) + 1; + + /* Read ciphername, should be 'none' as we don't support passphrases */ + result = _libssh2_match_string(&data_buffer, "none"); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + /* Read kdfname, should be 'none' as we don't support passphrases */ + result = _libssh2_match_string(&data_buffer, "none"); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + /* Read kdfoptions, should be empty */ + result = _libssh2_match_string(&data_buffer, ""); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + /* Read number of keys N */ + result = _libssh2_get_u32(&data_buffer, &key_count); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + if(key_count == 0) { + result = LIBSSH2_ERROR_FILE; + goto cleanup; + } + + /* Skip all public keys */ + for(index = 0; index < key_count; index++) { + unsigned char *publickey; + size_t publickey_len; + + result = _libssh2_get_string(&data_buffer, &publickey, &publickey_len); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + } + + /* Read first private key */ + result = _libssh2_get_string(&data_buffer, &privatekey, &privatekey_len); + if(result != LIBSSH2_ERROR_NONE) { + goto cleanup; + } + + result = _libssh2_wincng_parse_ecdsa_privatekey( + key, + privatekey, + privatekey_len); + +cleanup: + if(result != LIBSSH2_ERROR_NONE) { + return _libssh2_error( + session, + result, + "The key is malformed"); + } + + return result; +} + +/* + * _libssh2_ecdsa_sign + * + * Computes the ECDSA signature of a previously-hashed message + * + */ + +int +_libssh2_wincng_ecdsa_sign(IN LIBSSH2_SESSION *session, + IN _libssh2_wincng_ecdsa_key *key, + IN const unsigned char *hash, + IN size_t hash_len, + OUT unsigned char **signature, + OUT size_t *signature_len) +{ + NTSTATUS status; + int result = LIBSSH2_ERROR_NONE; + + unsigned char *hash_buffer; + + unsigned char *cng_signature = NULL; + ULONG cng_signature_len; + + ULONG signature_maxlen; + unsigned char *signature_ptr; + + *signature = NULL; + *signature_len = 0; + + /* CNG expects a mutable buffer */ + hash_buffer = malloc(hash_len); + if(!hash_buffer) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + memcpy(hash_buffer, hash, hash_len); + + status = BCryptSignHash( + key->handle, + NULL, + hash_buffer, + (ULONG)hash_len, + NULL, + 0, + &cng_signature_len, + 0); + if(!BCRYPT_SUCCESS(status)) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + + cng_signature = malloc(cng_signature_len); + if(!cng_signature) { + result = LIBSSH2_ERROR_ALLOC; + goto cleanup; + } + + status = BCryptSignHash( + key->handle, + NULL, + hash_buffer, + (ULONG)hash_len, + cng_signature, + cng_signature_len, + &cng_signature_len, + 0); + if(!BCRYPT_SUCCESS(status)) { + result = LIBSSH2_ERROR_PUBLICKEY_PROTOCOL; + goto cleanup; + } + + /* + cng_signature is in IEEE P-1163 format: r || s. + Convert to ecdsa_signature_blob: mpint(r) || mpint(s) + */ + + signature_maxlen = + cng_signature_len / 2 + 5 + /* mpint(r) */ + cng_signature_len / 2 + 5; /* mpint(s) */ + + *signature = LIBSSH2_ALLOC(session, signature_maxlen); + signature_ptr = *signature; + + _libssh2_store_bignum2_bytes( + &signature_ptr, + cng_signature, + cng_signature_len / 2); + + _libssh2_store_bignum2_bytes( + &signature_ptr, + cng_signature + (cng_signature_len / 2), + cng_signature_len / 2); + + *signature_len = signature_ptr - *signature; + +cleanup: + if(cng_signature) { + free(cng_signature); + } + + if(hash_buffer) { + free(hash_buffer); + } + + return result; +} + +/* + * _libssh2_ecdsa_get_curve_type + * + * returns key curve type that maps to libssh2_curve_type + * + */ + +libssh2_curve_type +_libssh2_wincng_ecdsa_get_curve_type(IN _libssh2_wincng_ecdsa_key *key) +{ + return key->curve; +} + +#endif + /*******************************************************************/ /* * Windows CNG backend: Key functions */ #ifdef HAVE_LIBCRYPT32 -static unsigned long +static DWORD _libssh2_wincng_pub_priv_write(unsigned char *key, - unsigned long offset, + DWORD offset, const unsigned char *bignum, - const unsigned long length) + const DWORD length) { _libssh2_htonu32(key + offset, length); offset += 4; @@ -1673,13 +3107,13 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session, size_t cbEncoded) { unsigned char **rpbDecoded = NULL; - unsigned long *rcbDecoded = NULL; + DWORD *rcbDecoded = NULL; unsigned char *key = NULL, *mth = NULL; - unsigned long keylen = 0, mthlen = 0; - unsigned long index, offset, length = 0; + DWORD keylen = 0, mthlen = 0; + DWORD index, offset, length = 0; int ret; - ret = _libssh2_wincng_asn_decode_bns(pbEncoded, cbEncoded, + ret = _libssh2_wincng_asn_decode_bns(pbEncoded, (DWORD)cbEncoded, &rpbDecoded, &rcbDecoded, &length); _libssh2_wincng_safe_free(pbEncoded, cbEncoded); @@ -1915,8 +3349,7 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, BCRYPT_KEY_HANDLE hKey; BCRYPT_KEY_DATA_BLOB_HEADER *header; unsigned char *pbKeyObject, *pbIV, *pbCtr, *pbIVCopy; - unsigned long dwKeyObject, dwIV, dwCtrLength, dwBlockLength, - cbData, keylen; + ULONG dwKeyObject, dwIV, dwCtrLength, dwBlockLength, cbData, keylen; int ret; (void)encrypt; @@ -1943,7 +3376,7 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, } - keylen = (unsigned long)sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + + keylen = (ULONG)sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + type.dwKeyLength; header = (BCRYPT_KEY_DATA_BLOB_HEADER *)malloc(keylen); if(!header) { @@ -2005,6 +3438,7 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, return 0; } + int _libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx, _libssh2_cipher_type(type), @@ -2013,13 +3447,13 @@ _libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx, size_t blocklen, int firstlast) { unsigned char *pbOutput, *pbInput; - unsigned long cbOutput, cbInput; - int ret; + ULONG cbOutput, cbInput; + NTSTATUS ret; (void)type; (void)firstlast; - cbInput = (unsigned long)blocklen; + cbInput = (ULONG)blocklen; if(type.ctrMode) { pbInput = ctx->pbCtr; @@ -2062,7 +3496,7 @@ _libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx, _libssh2_wincng_safe_free(pbOutput, cbOutput); } else - ret = STATUS_NO_MEMORY; + ret = (NTSTATUS)STATUS_NO_MEMORY; } return BCRYPT_SUCCESS(ret) ? 0 : -1; @@ -2108,7 +3542,7 @@ _libssh2_wincng_bignum_init(void) } static int -_libssh2_wincng_bignum_resize(_libssh2_bn *bn, unsigned long length) +_libssh2_wincng_bignum_resize(_libssh2_bn *bn, ULONG length) { unsigned char *bignum; @@ -2136,13 +3570,12 @@ static int _libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom) { unsigned char *bignum; - unsigned long length; + ULONG length; if(!rnd) return -1; - length = (unsigned long) (ceil(((double)bits) / 8.0) * - sizeof(unsigned char)); + length = (ULONG) (ceil(((double)bits) / 8.0) * sizeof(unsigned char)); if(_libssh2_wincng_bignum_resize(rnd, length)) return -1; @@ -2181,8 +3614,8 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r, BCRYPT_KEY_HANDLE hKey; BCRYPT_RSAKEY_BLOB *rsakey; unsigned char *bignum; - unsigned long keylen, offset, length; - int ret; + ULONG keylen, offset, length; + NTSTATUS ret; if(!r || !a || !p || !m) return -1; @@ -2234,10 +3667,10 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r, } } else - ret = STATUS_NO_MEMORY; + ret = (NTSTATUS)STATUS_NO_MEMORY; } else - ret = STATUS_NO_MEMORY; + ret = (NTSTATUS)STATUS_NO_MEMORY; } BCryptDestroyKey(hKey); @@ -2249,9 +3682,9 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r, } int -_libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word) +_libssh2_wincng_bignum_set_word(_libssh2_bn *bn, ULONG word) { - unsigned long offset, number, bits, length; + ULONG offset, number, bits, length; if(!bn) return -1; @@ -2262,8 +3695,7 @@ _libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word) bits++; bits++; - length = (unsigned long) (ceil(((double)bits) / 8.0) * - sizeof(unsigned char)); + length = (ULONG) (ceil(((double)bits) / 8.0) * sizeof(unsigned char)); if(_libssh2_wincng_bignum_resize(bn, length)) return -1; @@ -2273,11 +3705,11 @@ _libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word) return 0; } -unsigned long +ULONG _libssh2_wincng_bignum_bits(const _libssh2_bn *bn) { unsigned char number; - unsigned long offset, length, bits; + ULONG offset, length, bits; if(!bn || !bn->bignum || !bn->length) return 0; @@ -2296,24 +3728,23 @@ _libssh2_wincng_bignum_bits(const _libssh2_bn *bn) return bits; } -void -_libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len, +int +_libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, ULONG len, const unsigned char *bin) { unsigned char *bignum; - unsigned long offset, length, bits; + ULONG offset, length, bits; if(!bn || !bin || !len) - return; + return -1; if(_libssh2_wincng_bignum_resize(bn, len)) - return; + return -1; memcpy(bn->bignum, bin, len); bits = _libssh2_wincng_bignum_bits(bn); - length = (unsigned long) (ceil(((double)bits) / 8.0) * - sizeof(unsigned char)); + length = (ULONG) (ceil(((double)bits) / 8.0) * sizeof(unsigned char)); offset = bn->length - length; if(offset > 0) { @@ -2326,15 +3757,23 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len, bn->bignum = bignum; bn->length = length; } + else { + return -1; + } } + + return 0; } -void +int _libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin) { if(bin && bn && bn->bignum && bn->length > 0) { memcpy(bin, bn->bignum, bn->length); + return 0; } + + return -1; } void @@ -2406,13 +3845,13 @@ _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, while(_libssh2_wincng.hAlgDH && hasAlgDHwithKDF != -1) { BCRYPT_DH_PARAMETER_HEADER *dh_params; - unsigned long dh_params_len; + ULONG dh_params_len; int status; /* Note that the DH provider requires that keys be multiples of 64 bits * in length. At the time of writing a practical observed group_order * value is 257, so we need to round down to 8 bytes of length (64/8) * in order for kex to succeed */ - DWORD key_length_bytes = max((unsigned long)round_down(group_order, 8), + ULONG key_length_bytes = max((ULONG)round_down(group_order, 8), max(g->length, p->length)); BCRYPT_DH_KEY_BLOB *dh_key_blob; LPCWSTR key_type; @@ -2426,7 +3865,7 @@ _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, return -1; } - dh_params_len = (unsigned long)sizeof(*dh_params) + + dh_params_len = (ULONG)sizeof(*dh_params) + 2 * key_length_bytes; dh_params = (BCRYPT_DH_PARAMETER_HEADER *)malloc(dh_params_len); if(!dh_params) { @@ -2594,11 +4033,11 @@ _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, BCRYPT_KEY_HANDLE peer_public = NULL; BCRYPT_SECRET_HANDLE agreement = NULL; ULONG secret_len_bytes = 0; - int status; + NTSTATUS status; unsigned char *start, *end; BCRYPT_DH_KEY_BLOB *public_blob; - DWORD key_length_bytes = max(f->length, dhctx->dh_params->cbKeyLength); - DWORD public_blob_len = (DWORD)(sizeof(*public_blob) + + ULONG key_length_bytes = max(f->length, dhctx->dh_params->cbKeyLength); + ULONG public_blob_len = (ULONG)(sizeof(*public_blob) + 3 * key_length_bytes); { @@ -2660,7 +4099,7 @@ _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, /* Expand the secret bignum to be ready to receive the derived secret * */ if(_libssh2_wincng_bignum_resize(secret, secret_len_bytes)) { - status = STATUS_NO_MEMORY; + status = (NTSTATUS)STATUS_NO_MEMORY; goto out; } @@ -2729,7 +4168,11 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, #if LIBSSH2_RSA_SHA2 if(key_method_len == 7 && memcmp(key_method, "ssh-rsa", key_method_len) == 0) { - return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; + return "rsa-sha2-512,rsa-sha2-256" +#if LIBSSH2_RSA_SHA1 + ",ssh-rsa" +#endif + ; } #else (void)key_method; diff --git a/libssh2/src/wincng.h b/libssh2/src/wincng.h index 21b25605e..a8d0d8057 100644 --- a/libssh2/src/wincng.h +++ b/libssh2/src/wincng.h @@ -1,7 +1,7 @@ -#ifndef __LIBSSH2_WINCNG_H -#define __LIBSSH2_WINCNG_H +#ifndef LIBSSH2_WINCNG_H +#define LIBSSH2_WINCNG_H /* - * Copyright (C) 2013-2020 Marc Hoersken + * Copyright (C) Marc Hoersken * All rights reserved. * * Redistribution and use in source and binary forms, @@ -36,6 +36,8 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause */ #define LIBSSH2_CRYPTO_ENGINE libssh2_wincng @@ -69,10 +71,31 @@ #define LIBSSH2_RSA_SHA1 1 #define LIBSSH2_RSA_SHA2 1 #define LIBSSH2_DSA 1 -#define LIBSSH2_ECDSA 0 #define LIBSSH2_ED25519 0 +/* + * Conditionally enable ECDSA support. + * + * ECDSA support requires the use of + * + * BCryptDeriveKey(..., BCRYPT_KDF_RAW_SECRET, ... ) + * + * This functionality is only available as of Windows 10. To maintain + * backward compatibility, ECDSA support is therefore disabled + * by default and needs to be explicitly enabled using a build + * flag. + */ +#ifdef LIBSSH2_ECDSA_WINCNG +#define LIBSSH2_ECDSA 1 +#else +#define LIBSSH2_ECDSA 0 +#endif + +#include "crypto_config.h" + +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #define MD5_DIGEST_LENGTH 16 +#endif #define SHA_DIGEST_LENGTH 20 #define SHA256_DIGEST_LENGTH 32 #define SHA384_DIGEST_LENGTH 48 @@ -109,6 +132,11 @@ struct _libssh2_wincng_ctx { BCRYPT_ALG_HANDLE hAlgRC4_NA; BCRYPT_ALG_HANDLE hAlg3DES_CBC; BCRYPT_ALG_HANDLE hAlgDH; + BCRYPT_ALG_HANDLE hAlgChacha20; +#if LIBSSH2_ECDSA + BCRYPT_ALG_HANDLE hAlgECDH[3]; /* indexed by libssh2_curve_type */ + BCRYPT_ALG_HANDLE hAlgECDSA[3]; /* indexed by libssh2_curve_type */ +#endif volatile int hasAlgDHwithKDF; /* -1=no, 0=maybe, 1=yes */ }; @@ -120,9 +148,6 @@ extern struct _libssh2_wincng_ctx _libssh2_wincng; * Windows CNG backend: Generic functions */ -void _libssh2_wincng_init(void); -void _libssh2_wincng_free(void); - #define libssh2_crypto_init() \ _libssh2_wincng_init() #define libssh2_crypto_exit() \ @@ -142,8 +167,8 @@ void _libssh2_wincng_free(void); typedef struct __libssh2_wincng_hash_ctx { BCRYPT_HASH_HANDLE hHash; unsigned char *pbHashObject; - unsigned long dwHashObject; - unsigned long cbHash; + ULONG dwHashObject; + ULONG cbHash; } _libssh2_wincng_hash_ctx; /* @@ -155,11 +180,9 @@ typedef struct __libssh2_wincng_hash_ctx { (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA1, \ SHA_DIGEST_LENGTH, NULL, 0) == 0) #define libssh2_sha1_update(ctx, data, datalen) \ - _libssh2_wincng_hash_update(&ctx, \ - (const unsigned char *) data, \ - (unsigned long) datalen) + (_libssh2_wincng_hash_update(&ctx, data, (ULONG) datalen) == 0) #define libssh2_sha1_final(ctx, hash) \ - _libssh2_wincng_hash_final(&ctx, hash) + (_libssh2_wincng_hash_final(&ctx, hash) == 0) #define libssh2_sha1(data, datalen, hash) \ _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA1, \ hash, SHA_DIGEST_LENGTH) @@ -169,11 +192,9 @@ typedef struct __libssh2_wincng_hash_ctx { (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA256, \ SHA256_DIGEST_LENGTH, NULL, 0) == 0) #define libssh2_sha256_update(ctx, data, datalen) \ - _libssh2_wincng_hash_update(&ctx, \ - (const unsigned char *) data, \ - (unsigned long) datalen) + (_libssh2_wincng_hash_update(&ctx, data, (ULONG) datalen) == 0) #define libssh2_sha256_final(ctx, hash) \ - _libssh2_wincng_hash_final(&ctx, hash) + (_libssh2_wincng_hash_final(&ctx, hash) == 0) #define libssh2_sha256(data, datalen, hash) \ _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA256, \ hash, SHA256_DIGEST_LENGTH) @@ -183,11 +204,9 @@ typedef struct __libssh2_wincng_hash_ctx { (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA384, \ SHA384_DIGEST_LENGTH, NULL, 0) == 0) #define libssh2_sha384_update(ctx, data, datalen) \ - _libssh2_wincng_hash_update(&ctx, \ - (const unsigned char *) data, \ - (unsigned long) datalen) + (_libssh2_wincng_hash_update(&ctx, data, (ULONG) datalen) == 0) #define libssh2_sha384_final(ctx, hash) \ - _libssh2_wincng_hash_final(&ctx, hash) + (_libssh2_wincng_hash_final(&ctx, hash) == 0) #define libssh2_sha384(data, datalen, hash) \ _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA384, \ hash, SHA384_DIGEST_LENGTH) @@ -197,61 +216,29 @@ typedef struct __libssh2_wincng_hash_ctx { (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA512, \ SHA512_DIGEST_LENGTH, NULL, 0) == 0) #define libssh2_sha512_update(ctx, data, datalen) \ - _libssh2_wincng_hash_update(&ctx, \ - (const unsigned char *) data, \ - (unsigned long) datalen) + (_libssh2_wincng_hash_update(&ctx, data, (ULONG) datalen) == 0) #define libssh2_sha512_final(ctx, hash) \ - _libssh2_wincng_hash_final(&ctx, hash) + (_libssh2_wincng_hash_final(&ctx, hash) == 0) #define libssh2_sha512(data, datalen, hash) \ _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA512, \ hash, SHA512_DIGEST_LENGTH) +#if LIBSSH2_MD5 || LIBSSH2_MD5_PEM #define libssh2_md5_ctx _libssh2_wincng_hash_ctx #define libssh2_md5_init(ctx) \ (_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashMD5, \ MD5_DIGEST_LENGTH, NULL, 0) == 0) #define libssh2_md5_update(ctx, data, datalen) \ - _libssh2_wincng_hash_update(&ctx, \ - (const unsigned char *) data, \ - (unsigned long) datalen) + (_libssh2_wincng_hash_update(&ctx, data, (ULONG) datalen) == 0) #define libssh2_md5_final(ctx, hash) \ - _libssh2_wincng_hash_final(&ctx, hash) -#define libssh2_md5(data, datalen, hash) \ - _libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashMD5, \ - hash, MD5_DIGEST_LENGTH) + (_libssh2_wincng_hash_final(&ctx, hash) == 0) +#endif /* * Windows CNG backend: HMAC functions */ #define libssh2_hmac_ctx _libssh2_wincng_hash_ctx -#define libssh2_hmac_ctx_init(ctx) -#define libssh2_hmac_sha1_init(ctx, key, keylen) \ - _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA1, \ - SHA_DIGEST_LENGTH, \ - key, (unsigned long) keylen) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacMD5, \ - MD5_DIGEST_LENGTH, \ - key, (unsigned long) keylen) -#define libssh2_hmac_ripemd160_init(ctx, key, keylen) - /* not implemented */ -#define libssh2_hmac_sha256_init(ctx, key, keylen) \ - _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA256, \ - SHA256_DIGEST_LENGTH, \ - key, (unsigned long) keylen) -#define libssh2_hmac_sha512_init(ctx, key, keylen) \ - _libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHmacSHA512, \ - SHA512_DIGEST_LENGTH, \ - key, (unsigned long) keylen) -#define libssh2_hmac_update(ctx, data, datalen) \ - _libssh2_wincng_hash_update(&ctx, \ - (const unsigned char *) data, \ - (unsigned long) datalen) -#define libssh2_hmac_final(ctx, hash) \ - _libssh2_wincng_hmac_final(&ctx, hash) -#define libssh2_hmac_cleanup(ctx) \ - _libssh2_wincng_hmac_cleanup(ctx) /*******************************************************************/ @@ -262,7 +249,7 @@ typedef struct __libssh2_wincng_hash_ctx { typedef struct __libssh2_wincng_key_ctx { BCRYPT_KEY_HANDLE hKey; void *pbKeyObject; - unsigned long cbKeyObject; + DWORD cbKeyObject; } _libssh2_wincng_key_ctx; @@ -284,9 +271,9 @@ typedef struct __libssh2_wincng_key_ctx { _libssh2_wincng_rsa_new_private_frommemory(rsactx, s, filedata, \ filedata_len, passphrase) #define _libssh2_rsa_sha1_sign(s, rsactx, hash, hash_len, sig, sig_len) \ - _libssh2_wincng_rsa_sha_sign(s, rsactx, hash, hash_len, sig, sig_len) + _libssh2_wincng_rsa_sha1_sign(s, rsactx, hash, hash_len, sig, sig_len) #define _libssh2_rsa_sha2_sign(s, rsactx, hash, hash_len, sig, sig_len) \ - _libssh2_wincng_rsa_sha_sign(s, rsactx, hash, hash_len, sig, sig_len) + _libssh2_wincng_rsa_sha2_sign(s, rsactx, hash, hash_len, sig, sig_len) #define _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len) \ _libssh2_wincng_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len) #define _libssh2_rsa_sha2_verify(rsactx, hash_len, sig, sig_len, m, m_len) \ @@ -316,6 +303,63 @@ typedef struct __libssh2_wincng_key_ctx { #define _libssh2_dsa_free(dsactx) \ _libssh2_wincng_dsa_free(dsactx) + +/* + * Windows CNG backend: ECDSA functions + */ + +typedef enum { + LIBSSH2_EC_CURVE_NISTP256 = 0, + LIBSSH2_EC_CURVE_NISTP384 = 1, + LIBSSH2_EC_CURVE_NISTP521 = 2, +} libssh2_curve_type; + +typedef struct __libssh2_wincng_ecdsa_ctx { + BCRYPT_KEY_HANDLE handle; + libssh2_curve_type curve; +} _libssh2_wincng_ecdsa_key; + +#define libssh2_ecdsa_ctx _libssh2_wincng_ecdsa_key + +#if LIBSSH2_ECDSA +#define _libssh2_ec_key _libssh2_wincng_ecdsa_key +#endif + +void +_libssh2_wincng_ecdsa_free(libssh2_ecdsa_ctx* ctx); + +#define _libssh2_ecdsa_create_key(session, privkey, pubkey_octal, \ + pubkey_octal_len, curve) \ + _libssh2_wincng_ecdh_create_key(session, privkey, pubkey_octal, \ + pubkey_octal_len, curve) + +#define _libssh2_ecdsa_curve_name_with_octal_new(ctx, k, k_len, curve) \ + _libssh2_wincng_ecdsa_curve_name_with_octal_new(ctx, k, k_len, curve) + +#define _libssh2_ecdh_gen_k(k, privkey, server_pubkey, server_pubkey_len) \ + _libssh2_wincng_ecdh_gen_k(k, privkey, server_pubkey, server_pubkey_len) + +#define _libssh2_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len) \ + _libssh2_wincng_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len) + +#define _libssh2_ecdsa_new_private(ctx, session, filename, passphrase) \ + _libssh2_wincng_ecdsa_new_private(ctx, session, filename, passphrase) + +#define _libssh2_ecdsa_new_private_frommemory(ctx, session, filedata, \ + filedata_len, passphrase) \ + _libssh2_wincng_ecdsa_new_private_frommemory(ctx, session, filedata, \ + filedata_len, passphrase) + +#define _libssh2_ecdsa_sign(session, ctx, hash, hash_len, sign, sign_len) \ + _libssh2_wincng_ecdsa_sign(session, ctx, hash, hash_len, sign, sign_len) + +#define _libssh2_ecdsa_get_curve_type(ctx) \ + _libssh2_wincng_ecdsa_get_curve_type(ctx) + +#define _libssh2_ecdsa_free(ecdsactx) \ + _libssh2_wincng_ecdsa_free(ecdsactx) + + /* * Windows CNG backend: Key functions */ @@ -341,10 +385,10 @@ struct _libssh2_wincng_cipher_ctx { unsigned char *pbKeyObject; unsigned char *pbIV; unsigned char *pbCtr; - unsigned long dwKeyObject; - unsigned long dwIV; - unsigned long dwBlockLength; - unsigned long dwCtrLength; + ULONG dwKeyObject; + ULONG dwIV; + ULONG dwBlockLength; + ULONG dwCtrLength; }; #define _libssh2_cipher_ctx struct _libssh2_wincng_cipher_ctx @@ -355,7 +399,7 @@ struct _libssh2_wincng_cipher_ctx { struct _libssh2_wincng_cipher_type { BCRYPT_ALG_HANDLE *phAlg; - unsigned long dwKeyLength; + ULONG dwKeyLength; int useIV; /* TODO: Convert to bool when a C89 compatible bool type is defined */ int ctrMode; @@ -371,6 +415,7 @@ struct _libssh2_wincng_cipher_type { #define _libssh2_cipher_aes128 { &_libssh2_wincng.hAlgAES_CBC, 16, 1, 0 } #define _libssh2_cipher_arcfour { &_libssh2_wincng.hAlgRC4_NA, 16, 0, 0 } #define _libssh2_cipher_3des { &_libssh2_wincng.hAlg3DES_CBC, 24, 1, 0 } +#define _libssh2_cipher_chacha20 { &_libssh2_wincng.hAlgChacha20, 24, 1, 0 } /* * Windows CNG backend: Cipher functions @@ -400,7 +445,7 @@ struct _libssh2_wincng_cipher_type { struct _libssh2_wincng_bignum { unsigned char *bignum; - unsigned long length; + ULONG length; }; #define _libssh2_bn struct _libssh2_wincng_bignum @@ -409,8 +454,6 @@ struct _libssh2_wincng_bignum { * Windows CNG backend: BigNumber functions */ -_libssh2_bn *_libssh2_wincng_bignum_init(void); - #define _libssh2_bn_init() \ _libssh2_wincng_bignum_init() #define _libssh2_bn_init_from_bin() \ @@ -418,7 +461,7 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void); #define _libssh2_bn_set_word(bn, word) \ _libssh2_wincng_bignum_set_word(bn, word) #define _libssh2_bn_from_bin(bn, len, bin) \ - _libssh2_wincng_bignum_from_bin(bn, (unsigned long) len, bin) + _libssh2_wincng_bignum_from_bin(bn, (ULONG) len, bin) #define _libssh2_bn_to_bin(bn, bin) \ _libssh2_wincng_bignum_to_bin(bn, bin) #define _libssh2_bn_bytes(bn) bn->length @@ -435,7 +478,7 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void); diffie-hellman-group-exchange-sha1 */ #define LIBSSH2_DH_GEX_MINGROUP 2048 #define LIBSSH2_DH_GEX_OPTGROUP 4096 -#define LIBSSH2_DH_GEX_MAXGROUP 8192 +#define LIBSSH2_DH_GEX_MAXGROUP 4096 #define LIBSSH2_DH_MAX_MODULUS_BITS 16384 @@ -467,160 +510,40 @@ int _libssh2_wincng_random(void *buf, size_t len); int _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx, - BCRYPT_ALG_HANDLE hAlg, unsigned long hashlen, - unsigned char *key, unsigned long keylen); + BCRYPT_ALG_HANDLE hAlg, ULONG hashlen, + unsigned char *key, ULONG keylen); int _libssh2_wincng_hash_update(_libssh2_wincng_hash_ctx *ctx, - const unsigned char *data, unsigned long datalen); + const void *data, ULONG datalen); int _libssh2_wincng_hash_final(_libssh2_wincng_hash_ctx *ctx, unsigned char *hash); int -_libssh2_wincng_hash(const unsigned char *data, unsigned long datalen, +_libssh2_wincng_hash(const unsigned char *data, ULONG datalen, BCRYPT_ALG_HANDLE hAlg, - unsigned char *hash, unsigned long hashlen); + unsigned char *hash, ULONG hashlen); -int -_libssh2_wincng_hmac_final(_libssh2_wincng_hash_ctx *ctx, - unsigned char *hash); -void -_libssh2_wincng_hmac_cleanup(_libssh2_wincng_hash_ctx *ctx); - -int -_libssh2_wincng_key_sha_verify(_libssh2_wincng_key_ctx *ctx, - unsigned long hashlen, - const unsigned char *sig, - unsigned long sig_len, - const unsigned char *m, - unsigned long m_len, - unsigned long flags); - -int -_libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa, - const unsigned char *edata, - unsigned long elen, - const unsigned char *ndata, - unsigned long nlen, - const unsigned char *ddata, - unsigned long dlen, - const unsigned char *pdata, - unsigned long plen, - const unsigned char *qdata, - unsigned long qlen, - const unsigned char *e1data, - unsigned long e1len, - const unsigned char *e2data, - unsigned long e2len, - const unsigned char *coeffdata, - unsigned long coefflen); -int -_libssh2_wincng_rsa_new_private(libssh2_rsa_ctx **rsa, - LIBSSH2_SESSION *session, - const char *filename, - const unsigned char *passphrase); -int -_libssh2_wincng_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, - LIBSSH2_SESSION *session, - const char *filedata, - size_t filedata_len, - unsigned const char *passphrase); -int -_libssh2_wincng_rsa_sha1_verify(libssh2_rsa_ctx *rsa, - const unsigned char *sig, - size_t sig_len, - const unsigned char *m, - size_t m_len); -int -_libssh2_wincng_rsa_sha_sign(LIBSSH2_SESSION *session, - libssh2_rsa_ctx *rsa, - const unsigned char *hash, - size_t hash_len, - unsigned char **signature, - size_t *signature_len); void _libssh2_wincng_rsa_free(libssh2_rsa_ctx *rsa); #if LIBSSH2_DSA -int -_libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa, - const unsigned char *pdata, - unsigned long plen, - const unsigned char *qdata, - unsigned long qlen, - const unsigned char *gdata, - unsigned long glen, - const unsigned char *ydata, - unsigned long ylen, - const unsigned char *xdata, - unsigned long xlen); -int -_libssh2_wincng_dsa_new_private(libssh2_dsa_ctx **dsa, - LIBSSH2_SESSION *session, - const char *filename, - const unsigned char *passphrase); -int -_libssh2_wincng_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa, - LIBSSH2_SESSION *session, - const char *filedata, - size_t filedata_len, - unsigned const char *passphrase); -int -_libssh2_wincng_dsa_sha1_verify(libssh2_dsa_ctx *dsa, - const unsigned char *sig_fixed, - const unsigned char *m, - size_t m_len); -int -_libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa, - const unsigned char *hash, - unsigned long hash_len, - unsigned char *sig_fixed); void _libssh2_wincng_dsa_free(libssh2_dsa_ctx *dsa); #endif -int -_libssh2_wincng_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekey, - const char *passphrase); -int -_libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekeydata, - size_t privatekeydata_len, - const char *passphrase); - -int -_libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, - _libssh2_cipher_type(type), - unsigned char *iv, - unsigned char *secret, - int encrypt); -int -_libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx, - _libssh2_cipher_type(type), - int encrypt, - unsigned char *block, - size_t blocklen, int firstlast); void _libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx); _libssh2_bn * _libssh2_wincng_bignum_init(void); int -_libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word); -unsigned long +_libssh2_wincng_bignum_set_word(_libssh2_bn *bn, ULONG word); +ULONG _libssh2_wincng_bignum_bits(const _libssh2_bn *bn); -void -_libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len, +int +_libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, ULONG len, const unsigned char *bin); -void +int _libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin); void _libssh2_wincng_bignum_free(_libssh2_bn *bn); @@ -635,4 +558,4 @@ _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx); -#endif /* __LIBSSH2_WINCNG_H */ +#endif /* LIBSSH2_WINCNG_H */ diff --git a/libssh2/vms/libssh2_config.h b/libssh2/vms/libssh2_config.h index 34d66c3b4..2cbe78a71 100644 --- a/libssh2/vms/libssh2_config.h +++ b/libssh2/vms/libssh2_config.h @@ -1,3 +1,8 @@ +/* Copyright (C) The libssh2 project and its contributors. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #ifndef LIBSSH2_CONFIG_H #ifdef __VMS diff --git a/libssh2/vms/libssh2_make_kit.dcl b/libssh2/vms/libssh2_make_kit.dcl index 738187e1b..f96c0abf3 100644 --- a/libssh2/vms/libssh2_make_kit.dcl +++ b/libssh2/vms/libssh2_make_kit.dcl @@ -194,7 +194,7 @@ $ write pt "=prompt JCB LIBSSH2 for OpenVMS" $ write pt "" $ write pt "libssh2 is an open source client side library that aims to implement" $ write pt "the SSH protocol. This is the OpenVMS port of that library." -$ write pt "Further information at https://www.libssh2.org." +$ write pt "Further information at https://libssh2.org/." $ write pt "" $ write pt "1 NEED_VMS83" $ write pt "=prompt OpenVMS 8.3 or later is not installed on your system." diff --git a/libssh2/vms/man2help.c b/libssh2/vms/man2help.c index 49ef10d2b..2cdad29d5 100644 --- a/libssh2/vms/man2help.c +++ b/libssh2/vms/man2help.c @@ -1,3 +1,8 @@ +/* Copyright (C) The libssh2 project and its contributors. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #include #include #include @@ -10,12 +15,12 @@ #include #include -typedef struct manl{ +typedef struct manl { struct manl *next; char *filename; -}man, *manPtr; +} man, *manPtr; -typedef struct pf_fabnam{ +typedef struct pf_fabnam { struct FAB dfab; struct RAB drab; struct namldef dnam; @@ -24,491 +29,536 @@ typedef struct pf_fabnam{ /*----------------------------------------------------------*/ -fpcopy( char *output, char *input, int len ) +fpcopy(char *output, char *input, int len) { -char *is, *os; -int i; + char *is, *os; + int i; -if ( len ){ - for ( is = input, os = output, i = 0; i < len ; ++i, ++is, ++os){ + if(len) { + for(is = input, os = output, i = 0; i < len; ++i, ++is, ++os) { *os = *is; + } + *os = 0; + } + else { + output[0] = 0; } - *os = 0; -}else{ - output[0] = 0; -} } /*----------------------------------------------------------*/ /* give part of ilename in partname. See code for proper - value of i ( 0 = node, 1 = dev, 2 = dir,3 = name etc. + value of i ( 0 = node, 1 = dev, 2 = dir, 3 = name etc. */ -int fnamepart( char *inputfile, char *part, int whatpart ) +int fnamepart(char *inputfile, char *part, int whatpart) { -pfnPtr pf; -int status; -char ipart[6][256], *i, *p; + pfnPtr pf; + int status; + char ipart[6][256], *i, *p; -pf = calloc( 1, sizeof( pfn ) ); + pf = calloc(1, sizeof(pfn)); -pf->dfab = cc$rms_fab; -pf->drab = cc$rms_rab; -pf->dnam = cc$rms_naml; + pf->dfab = cc$rms_fab; + pf->drab = cc$rms_rab; + pf->dnam = cc$rms_naml; -pf->dfab.fab$l_naml = &pf->dnam; + pf->dfab.fab$l_naml = &pf->dnam; -pf->dfab.fab$l_fna = (char *) -1; -pf->dfab.fab$l_dna = (char *) -1; -pf->dfab.fab$b_fns = 0; -pf->dfab.fab$w_ifi = 0; + pf->dfab.fab$l_fna = (char *) -1; + pf->dfab.fab$l_dna = (char *) -1; + pf->dfab.fab$b_fns = 0; + pf->dfab.fab$w_ifi = 0; -pf->dnam.naml$l_long_defname = NULL; //inputfile; -pf->dnam.naml$l_long_defname_size = 0;//strlen( inputfile ); + pf->dnam.naml$l_long_defname = NULL; /* inputfile; */ + pf->dnam.naml$l_long_defname_size = 0; /* strlen(inputfile); */ -pf->dnam.naml$l_long_filename = inputfile; -pf->dnam.naml$l_long_filename_size = strlen( inputfile ); + pf->dnam.naml$l_long_filename = inputfile; + pf->dnam.naml$l_long_filename_size = strlen(inputfile); -pf->dnam.naml$l_long_expand = pf->expanded_filename; -pf->dnam.naml$l_long_expand_alloc = NAM$C_MAXRSS ; + pf->dnam.naml$l_long_expand = pf->expanded_filename; + pf->dnam.naml$l_long_expand_alloc = NAM$C_MAXRSS; -pf->dnam.naml$b_nop |= NAML$M_SYNCHK | NAML$M_PWD; + pf->dnam.naml$b_nop |= NAML$M_SYNCHK | NAML$M_PWD; -status = sys$parse( &pf->dfab, 0, 0 ); -if ( !(status&1) ){ - free( pf ); - return( status ); -} + status = sys$parse(&pf->dfab, 0, 0); + if(!(status&1)) { + free(pf); + return status; + } -fpcopy ( ipart[0], pf->dnam.naml$l_long_node , pf->dnam.naml$l_long_node_size); -fpcopy ( ipart[1], pf->dnam.naml$l_long_dev , pf->dnam.naml$l_long_dev_size); -fpcopy ( ipart[2], pf->dnam.naml$l_long_dir , pf->dnam.naml$l_long_dir_size); -fpcopy ( ipart[3], pf->dnam.naml$l_long_name , pf->dnam.naml$l_long_name_size); -fpcopy ( ipart[4], pf->dnam.naml$l_long_type , pf->dnam.naml$l_long_type_size); -fpcopy ( ipart[5], pf->dnam.naml$l_long_ver , pf->dnam.naml$l_long_ver_size); + fpcopy(ipart[0], pf->dnam.naml$l_long_node, + pf->dnam.naml$l_long_node_size); + fpcopy(ipart[1], pf->dnam.naml$l_long_dev, + pf->dnam.naml$l_long_dev_size); + fpcopy(ipart[2], pf->dnam.naml$l_long_dir, + pf->dnam.naml$l_long_dir_size); + fpcopy(ipart[3], pf->dnam.naml$l_long_name, + pf->dnam.naml$l_long_name_size); + fpcopy(ipart[4], pf->dnam.naml$l_long_type, + pf->dnam.naml$l_long_type_size); + fpcopy(ipart[5], pf->dnam.naml$l_long_ver, + pf->dnam.naml$l_long_ver_size); -for( i = ipart[ whatpart ], p = part; *i; ++i, ++p){ - if ( p == part ){ - *p = toupper( *i ); - }else{ - *p = tolower( *i ); - } -} -*p = 0; + for(i = ipart[whatpart], p = part; *i; ++i, ++p) { + if(p == part) { + *p = toupper(*i); + } + else { + *p = tolower(*i); + } + } + *p = 0; -free( pf ); -return(1); + free(pf); + return 1; } /*----------------------------------------------------------*/ -int find_file(char *filename,char *gevonden,int *findex) +int find_file(char *filename, char *gevonden, int *findex) { -int status; -struct dsc$descriptor gevondend; -struct dsc$descriptor filespec; -char gevonden_file[NAM$C_MAXRSS + 1]; + int status; + struct dsc$descriptor gevondend; + struct dsc$descriptor filespec; + char gevonden_file[NAM$C_MAXRSS + 1]; -filespec.dsc$w_length = strlen(filename); -filespec.dsc$b_dtype = DSC$K_DTYPE_T; -filespec.dsc$b_class = DSC$K_CLASS_S; -filespec.dsc$a_pointer = filename; + filespec.dsc$w_length = strlen(filename); + filespec.dsc$b_dtype = DSC$K_DTYPE_T; + filespec.dsc$b_class = DSC$K_CLASS_S; + filespec.dsc$a_pointer = filename; -gevondend.dsc$w_length = NAM$C_MAXRSS; -gevondend.dsc$b_dtype = DSC$K_DTYPE_T; -gevondend.dsc$b_class = DSC$K_CLASS_S; -gevondend.dsc$a_pointer = gevonden_file; + gevondend.dsc$w_length = NAM$C_MAXRSS; + gevondend.dsc$b_dtype = DSC$K_DTYPE_T; + gevondend.dsc$b_class = DSC$K_CLASS_S; + gevondend.dsc$a_pointer = gevonden_file; -status=lib$find_file(&filespec,&gevondend,findex,0,0,0,0); + status = lib$find_file(&filespec, &gevondend, findex, 0, 0, 0, 0); -if ( (status & 1) == 1 ){ - strcpy(gevonden,strtok(gevonden_file," ")); -}else{ - gevonden[0] = 0; -} - -return(status); -} - - -/*--------------------------------------------*/ - -manPtr addman( manPtr *manroot,char *filename ) -{ -manPtr m,f; - -m = calloc( 1, sizeof( man ) ); -if ( !m ) return( NULL ); - -m->filename = strdup( filename ); - -if ( *manroot == NULL ){ - *manroot = m; -}else{ - for( f = *manroot; f->next ; f = f->next ); - f->next = m; -} -return(m); -} - -/*--------------------------------------------*/ -void freeman( manPtr *manroot ) -{ -manPtr m,n; - -for( m = *manroot; m ; m = n ){ - free( m->filename ); - n = m->next; - free( m ); -} -*manroot = NULL; -} - -/*--------------------------------------------*/ - -int listofmans( char *filespec, manPtr *manroot ) -{ -manPtr r; -int status; -int ffindex=0; -char gevonden[NAM$C_MAXRSS + 1]; - -while(1){ - status = find_file( filespec, gevonden, &ffindex ); - - if ( (status&1) ){ - r = addman( manroot, gevonden ); - if ( r == NULL ) return(2); - }else{ - if ( !( status&1 ) ) break; + if((status & 1) == 1) { + /* !checksrc! disable BANNEDFUNC 1 */ /* FIXME */ + strcpy(gevonden, strtok(gevonden_file, " ")); } + else { + gevonden[0] = 0; + } + + return status; } -lib$find_file_end( &ffindex ); -if ( status == RMS$_NMF) status = 1; +/*--------------------------------------------*/ -return( status ); +manPtr addman(manPtr *manroot, char *filename) +{ + manPtr m, f; + + m = calloc(1, sizeof(man)); + if(!m) + return NULL; + + m->filename = strdup(filename); + + if(!*manroot) { + *manroot = m; + } + else { + for(f = *manroot; f->next; f = f->next) + ; + f->next = m; + } + return m; +} + +/*--------------------------------------------*/ +void freeman(manPtr *manroot) +{ + manPtr m, n; + + for(m = *manroot; m; m = n) { + free(m->filename); + n = m->next; + free(m); + } + *manroot = NULL; } /*--------------------------------------------*/ -int convertman ( char *filespec, FILE *hlp , int base_level, int add_parentheses ) +int listofmans(char *filespec, manPtr *manroot) { -FILE *man; -char *in, *uit; -char *m,*h; -size_t len, thislen, maxlen= 50000; -int bol,mode, return_status=1; -char subjectname[ NAM$C_MAXRSS + 1 ]; + manPtr r; + int status; + int ffindex = 0; + char gevonden[NAM$C_MAXRSS + 1]; -in = calloc( 1, maxlen + 1 ); -uit = calloc( 1, maxlen + 1 ); + for(;;) { + status = find_file(filespec, gevonden, &ffindex); -if ( in == NULL || uit == NULL ) return(2); + if((status&1)) { + r = addman(manroot, gevonden); + if(!r) + return 2; + } + else { + if(!(status&1)) + break; + } + } -man = fopen( filespec, "r" ); -if ( man == NULL ) return(vaxc$errno); + lib$find_file_end(&ffindex); + if(status == RMS$_NMF) + status = 1; -for( len = 0; !feof( man ) && len < maxlen ; len += thislen ){ - thislen = fread( in + len, 1, maxlen - len, man ); + return status; } -fclose(man); +/*--------------------------------------------*/ -m = in; -h = uit; +int convertman(char *filespec, FILE *hlp, int base_level, int add_parentheses) +{ + FILE *man; + char *in, *uit; + char *m, *h; + size_t len, thislen, maxlen = 50000; + int bol, mode, return_status = 1; + char subjectname[NAM$C_MAXRSS + 1]; -*(m + len ) = 0; + in = calloc(1, maxlen + 1); + uit = calloc(1, maxlen + 1); -for ( mode = 0, bol = 1 ; *m; ++m ){ + if(!in || !uit) + return 2; - switch ( mode ){ + man = fopen(filespec, "r"); + if(!man) + return vaxc$errno; + + for(len = 0; !feof(man) && len < maxlen; len += thislen) { + thislen = fread(in + len, 1, maxlen - len, man); + } + + fclose(man); + + m = in; + h = uit; + + *(m + len) = 0; + + for(mode = 0, bol = 1; *m; ++m) { + + switch(mode) { case 0: - switch(*m){ + switch(*m) { case '.': - if ( bol ){ + if(bol) { mode = 1; - }else{ + } + else { *h = *m; ++h; } break; case '\\': - if ( bol ){ - *h = ' ';++h; - *h = ' ';++h; + if(bol) { + *h = ' '; ++h; + *h = ' '; ++h; } mode = 2; break; default: - if ( bol ){ - *h = ' ';++h; - *h = ' ';++h; + if(bol) { + *h = ' '; ++h; + *h = ' '; ++h; } *h = *m; ++h; break; - } - break; - case 1: /* after . at bol */ + } + break; - switch(*m){ + case 1: /* after . at bol */ + switch(*m) { case '\\': - while( *m != '\n' && *m != '\r' && *m )++m; + while(*m != '\n' && *m != '\r' && *m) + ++m; mode = 0; break; case 'B': - ++m; - *h = ' ';++h; - mode = 0; - break; + ++m; + *h = ' '; ++h; + mode = 0; + break; case 'I': - /* remove preceding eol */ - if ( *(m+1) != 'P' ){ + /* remove preceding eol */ + if(*(m + 1) != 'P') { + --h; + while((*h == '\n' || *h == '\r') && h > uit) --h; - while ( (*h == '\n' || *h == '\r') && h > uit )--h; - ++h; - } + ++h; + } - /* skip .Ix */ - for(;*m != ' ' && *m != '\n' && *m != '\r'; ++m); + /* skip .Ix */ + for(; *m != ' ' && *m != '\n' && *m != '\r'; ++m) + ; - /* copy line up to EOL */ + /* copy line up to EOL */ - for(;*m != '\n' && *m != '\r' && *m; ++m, ++h)*h = *m; + for(; *m != '\n' && *m != '\r' && *m; ++m, ++h) + *h = *m; - /* if line ends in ., this is an EOL */ + /* if line ends in ., this is an EOL */ - if ( *(h-1) == '.'){ - --h; - --m; - }else{ - /* if line does not end in ., skip EOL in source */ + if(*(h-1) == '.') { + --h; + --m; + } + else { + /* if line does not end in ., skip EOL in source */ - if ( *(m+1) == '\n' || *(m+1) == '\r')++m; - } - mode = 0; - break; + if(*(m + 1) == '\n' || *(m + 1) == '\r') + ++m; + } + mode = 0; + break; case 'S': - if ( *(m+1) == 'H' ){ + if(*(m + 1) == 'H') { *h = '\n';++h; - if ( strncmp( m+3 ,"NAME",4) == 0 || - strncmp( m+3 ,"SYNOPSIS",8) == 0 || - strncmp( m+3 ,"DESCRIPTION",11) == 0 ){ - while( *m != '\n' && *m != '\r')++m; + if(strncmp(m + 3, "NAME", 4) == 0 || + strncmp(m + 3, "SYNOPSIS", 8) == 0 || + strncmp(m + 3, "DESCRIPTION", 11) == 0) { + while(*m != '\n' && *m != '\r') + ++m; mode = 0; - }else{ + } + else { ++m; /* write help level, and flag it */ - *h = '0' + base_level + 1;++h; + *h = '0' + base_level + 1; ++h; return_status |= 2; - *h = ' ';++h; + *h = ' '; ++h; /* skip H (or whatever after S) and blank */ - ++m;++m; + ++m; ++m; - for(;*m != '\n' && *m != '\r' && *m; ++m, ++h){ + for(; *m != '\n' && *m != '\r' && *m; ++m, ++h) { /* write help label in lowercase, skip quotes */ /* fill blanks with underscores */ - if ( *m != '\"' ){ - *h = tolower( *m ); - if (*h == ' ') *h = '_'; - }else{ - --h; + if(*m != '\"') { + *h = tolower(*m); + if(*h == ' ') + *h = '_'; + } + else { + --h; } } /* Add a linefeed or two */ - *h = *m;++h; - *h = *m;++h; + *h = *m; ++h; + *h = *m; ++h; mode = 0; } - } - break; + } + break; case 'T': - if ( *(m+1) == 'H' ){ + if(*(m + 1) == 'H') { *h = '0' + base_level; ++h; return_status |= 2; - *h = ' ';++h; - for ( m = m + 3; *m != ' ' && *m ; ++m, ++h ){ - *h = *m; + *h = ' '; ++h; + for(m = m + 3; *m != ' ' && *m; ++m, ++h) { + *h = *m; } - if ( add_parentheses ){ - *h = '(';++h; - *h = ')';++h; + if(add_parentheses) { + *h = '('; ++h; + *h = ')'; ++h; } - while( *m != '\n' && *m != '\r' && *m )++m; + while(*m != '\n' && *m != '\r' && *m) + ++m; mode = 0; - } - break; + } + break; default: ++m; mode = 0; break; - } - break; + } + break; case 2: /* after \ skip two characters or print the backslash */ - switch(*m){ - case '\\': - *h = *m; - ++h; - mode = 0; - break; - default: - ++m; - mode = 0; - break; - } - break; - } /*end switch mode */ - - bol = 0; - if ( *m == '\n' || *m == '\r') bol = 1; - -}/* end for mode */ - -*h = 0; - - -if ( (return_status&2) ){ - fprintf( hlp, "%s\n\n", uit); -}else{ - fnamepart( filespec, subjectname,3); - if ( *subjectname ){ - fprintf( hlp, "%d %s\n\n%s\n\n", base_level, subjectname, uit); - }else{ - /* No filename (as is the case with a logical), use first word as subject name */ - char *n,*s; - - for(n = in; isspace( *n );++n); - for(s = subjectname; !(isspace( *n )); ++n,++s)*s = *n; - *s = 0; - - fprintf( hlp, "%d %s\n\n%s\n\n", base_level, subjectname, uit); - } -} - -/* - printf( "read %d from %s, written %d to helpfile, return_status = %d\n", - len, filespec, strlen(uit), return_status ); -*/ - -free( m ); -free( h ); - -return ( 1 ); -} - -/*--------------------------------------------*/ - -int convertmans( char *filespec, char *hlpfilename, int base_level, int append, int add_parentheses ) -{ -int status=1; -manPtr manroot=NULL, m; -FILE *hlp; - -if ( append ){ - hlp = fopen( hlpfilename,"a+"); -}else{ - hlp = fopen( hlpfilename,"w"); -} - -if ( hlp == NULL ) return( vaxc$errno ); - -status = listofmans( filespec, &manroot ); -if ( !(status&1) ) return( status ); - -for ( m = manroot ; m ; m = m->next ){ - status = convertman( m->filename, hlp , base_level, add_parentheses ); - if ( !(status&1) ){ - fprintf(stderr,"Convertman of %s went wrong\n", m->filename); - break; - } -} -freeman( &manroot ); -return( status ); -} - -/*--------------------------------------------*/ -void print_help() -{ - fprintf( stderr, "Usage: [-a] [-b x] convertman \n" ); - fprintf( stderr, " -a append to \n" ); - fprintf( stderr, " -b if no headers found create one with level \n" ); - fprintf( stderr, " and the filename as title.\n" ); - fprintf( stderr, " -p add parentheses() to baselevel help items.\n" ); - -} -/*--------------------------------------------*/ - -main ( int argc, char **argv ) -{ -int status; -int i,j; -int append, base_level, basechange, add_parentheses; -char *manfile=NULL; -char *helpfile=NULL; - -if ( argc < 3 ){ - print_help(); - return( 1 ) ; -} - -append = 0; -base_level = 1; -basechange = 0; -add_parentheses = 0; - -for ( i = 1; i < argc; ++i){ - if ( argv[i][0] == '-' ){ - for( j = 1; argv[i][j] ; ++j ){ - switch( argv[i][j] ){ - case 'a': - append = 1; + switch(*m) { + case '\\': + *h = *m; + ++h; + mode = 0; break; - case 'b': - if ( (i+1) < argc ){ - base_level = atoi( argv[ i + 1 ] ); - basechange = 1; - } - break; - case 'p': - add_parentheses = 1; + default: + ++m; + mode = 0; break; } + break; + } /* end switch mode */ + + bol = 0; + if(*m == '\n' || *m == '\r') + bol = 1; + + } /* end for mode */ + + *h = 0; + + + if(return_status & 2) { + fprintf(hlp, "%s\n\n", uit); + } + else { + fnamepart(filespec, subjectname, 3); + if(*subjectname) { + fprintf(hlp, "%d %s\n\n%s\n\n", base_level, subjectname, uit); } - if ( basechange){ - basechange = 0; - i = i + 1; - } - }else{ - if ( manfile == NULL ){ - manfile = strdup( argv[i]); - } else if ( helpfile == NULL ){ - helpfile = strdup( argv[i]); - } else { - fprintf( stderr, "Unrecognized parameter : %s\n", argv[i]); + else { + /* No filename (as is the case with a logical), + use first word as subject name */ + char *n, *s; + + for(n = in; isspace(*n); ++n) + ; + for(s = subjectname; !(isspace(*n)); ++n, ++s) + *s = *n; + *s = 0; + + fprintf(hlp, "%d %s\n\n%s\n\n", base_level, subjectname, uit); } } + + /* + printf("read %d from %s, written %d to helpfile, return_status = %d\n", + len, filespec, strlen(uit), return_status); + */ + + free(m); + free(h); + + return 1; } +/*--------------------------------------------*/ -/* fprintf( stderr,"manfile: %s, helpfile: %s, append: %d, base_level : %d\n", - manfile, helpfile, append, base_level); -*/ +int convertmans(char *filespec, char *hlpfilename, int base_level, int append, + int add_parentheses) +{ + int status = 1; + manPtr manroot = NULL, m; + FILE *hlp; -status = convertmans( manfile, helpfile, base_level, append, add_parentheses ); + if(append) { + hlp = fopen(hlpfilename, "a+"); + } + else { + hlp = fopen(hlpfilename, "w"); + } -free( manfile ); -free( helpfile ); + if(!hlp) + return vaxc$errno; -return( status ); + status = listofmans(filespec, &manroot); + if(!(status&1)) + return status; + + for(m = manroot; m; m = m->next) { + status = convertman(m->filename, hlp, base_level, add_parentheses); + if(!(status&1)) { + fprintf(stderr, "Convertman of %s went wrong\n", m->filename); + break; + } + } + freeman(&manroot); + return status; +} + +/*--------------------------------------------*/ +void print_help(void) +{ + fprintf(stderr, + "Usage: [-a] [-b x] convertman \n" + " -a append to \n" + " -b if no headers found create one " + "with level \n" + " and the filename as title.\n" + " -p add parentheses() to baselevel help items.\n"); +} +/*--------------------------------------------*/ + +main(int argc, char **argv) +{ + int status; + int i, j; + int append, base_level, basechange, add_parentheses; + char *manfile = NULL; + char *helpfile = NULL; + + if(argc < 3) { + print_help(); + return 1; + } + + append = 0; + base_level = 1; + basechange = 0; + add_parentheses = 0; + + for(i = 1; i < argc; ++i) { + if(argv[i][0] == '-') { + for(j = 1; argv[i][j]; ++j) { + switch(argv[i][j]) { + case 'a': + append = 1; + break; + case 'b': + if((i + 1) < argc) { + base_level = atoi(argv[i + 1]); + basechange = 1; + } + break; + case 'p': + add_parentheses = 1; + break; + } + } + if(basechange) { + basechange = 0; + i = i + 1; + } + } + else { + if(!manfile) { + manfile = strdup(argv[i]); + } + else if(!helpfile) { + helpfile = strdup(argv[i]); + } + else { + fprintf(stderr, "Unrecognized parameter : %s\n", argv[i]); + } + } + } + + /* + fprintf(stderr,"manfile: %s, helpfile: %s, append: %d, base_level : %d\n", + manfile, helpfile, append, base_level); + */ + + status = convertmans(manfile, helpfile, base_level, append, + add_parentheses); + + free(manfile); + free(helpfile); + + return status; } diff --git a/libssh2/vms/readme.vms b/libssh2/vms/readme.vms index c3d10d2a2..6356ac625 100644 --- a/libssh2/vms/readme.vms +++ b/libssh2/vms/readme.vms @@ -290,7 +290,7 @@ the procedure like so: @libssh2_make_example.dcl sftp "SHARED" -The procdure defines a process logical gnv$libssh2 pointing to the shared +The procedure defines a process logical gnv$libssh2 pointing to the shared image library in the directory, which obviously will not survive a logout.