summaryrefslogtreecommitdiff
path: root/libs/libssh2/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libssh2/src')
-rw-r--r--libs/libssh2/src/CMakeLists.txt18
-rw-r--r--libs/libssh2/src/Makefile.am7
-rw-r--r--libs/libssh2/src/Makefile.in71
-rw-r--r--libs/libssh2/src/agent.c193
-rw-r--r--libs/libssh2/src/bcrypt_pbkdf.c180
-rw-r--r--libs/libssh2/src/blf.h90
-rw-r--r--libs/libssh2/src/blowfish.c697
-rw-r--r--libs/libssh2/src/channel.c559
-rw-r--r--libs/libssh2/src/comp.c51
-rw-r--r--libs/libssh2/src/crypt.c35
-rw-r--r--libs/libssh2/src/crypto.h108
-rw-r--r--libs/libssh2/src/global.c9
-rw-r--r--libs/libssh2/src/hostkey.c708
-rw-r--r--libs/libssh2/src/keepalive.c19
-rw-r--r--libs/libssh2/src/kex.c2518
-rw-r--r--libs/libssh2/src/knownhost.c116
-rw-r--r--libs/libssh2/src/libgcrypt.c184
-rw-r--r--libs/libssh2/src/libgcrypt.h113
-rw-r--r--libs/libssh2/src/libssh2_config.h.in11
-rw-r--r--libs/libssh2/src/libssh2_priv.h119
-rw-r--r--libs/libssh2/src/mac.c12
-rw-r--r--libs/libssh2/src/mbedtls.c283
-rw-r--r--libs/libssh2/src/mbedtls.h104
-rw-r--r--libs/libssh2/src/misc.c431
-rw-r--r--libs/libssh2/src/misc.h39
-rw-r--r--libs/libssh2/src/openssl.c2620
-rw-r--r--libs/libssh2/src/openssl.h140
-rw-r--r--libs/libssh2/src/packet.c208
-rw-r--r--libs/libssh2/src/pem.c658
-rw-r--r--libs/libssh2/src/publickey.c523
-rw-r--r--libs/libssh2/src/scp.c277
-rw-r--r--libs/libssh2/src/session.c435
-rw-r--r--libs/libssh2/src/session.h8
-rw-r--r--libs/libssh2/src/sftp.c846
-rw-r--r--libs/libssh2/src/sftp.h1
-rw-r--r--libs/libssh2/src/transport.c178
-rw-r--r--libs/libssh2/src/userauth.c600
-rw-r--r--libs/libssh2/src/userauth.h3
-rw-r--r--libs/libssh2/src/wincng.c492
-rw-r--r--libs/libssh2/src/wincng.h70
40 files changed, 10583 insertions, 3151 deletions
diff --git a/libs/libssh2/src/CMakeLists.txt b/libs/libssh2/src/CMakeLists.txt
index 6401acff24..2eaf4cc2cf 100644
--- a/libs/libssh2/src/CMakeLists.txt
+++ b/libs/libssh2/src/CMakeLists.txt
@@ -77,21 +77,21 @@ if(CRYPTO_BACKEND STREQUAL "OpenSSL" OR NOT CRYPTO_BACKEND)
list(APPEND PC_LIBS -lcrypt32)
find_file(DLL_LIBEAY32
- NAMES libeay32.dll crypto.dll
+ NAMES libeay32.dll crypto.dll libcrypto-1_1.dll libcrypto-1_1-x64.dll
HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS}
PATH_SUFFIXES bin)
if (NOT DLL_LIBEAY32)
message(WARNING
- "Unable to find OpenSSL libeay32 DLL, executables may not run")
+ "Unable to find OpenSSL crypto (aka libeay32) DLL, executables may not run")
endif()
find_file(DLL_SSLEAY32
- NAMES ssleay32.dll ssl.dll
+ NAMES ssleay32.dll ssl.dll libssl-1_1.dll libssl-1_1-x64.dll
HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS}
PATH_SUFFIXES bin)
if (NOT DLL_SSLEAY32)
message(WARNING
- "Unable to find OpenSSL ssleay32 DLL, executables may not run")
+ "Unable to find OpenSSL ssl (aka ssleay32) DLL, executables may not run")
endif()
if(DLL_LIBEAY32 AND DLL_SSLEAY32)
@@ -176,6 +176,9 @@ include(GNUInstallDirs)
set(SOURCES
${CRYPTO_SOURCES}
agent.c
+ blf.h
+ bcrypt_pbkdf.c
+ blowfish.c
channel.c
channel.h
comp.c
@@ -217,7 +220,7 @@ set_target_properties(libssh2 PROPERTIES PREFIX "")
target_compile_definitions(libssh2 PRIVATE ${PRIVATE_COMPILE_DEFINITIONS})
target_include_directories(libssh2
- PRIVATE ${PRIVATE_INCLUDE_DIRECTORIES}
+ PRIVATE "${PROJECT_SOURCE_DIR}/include/" ${PRIVATE_INCLUDE_DIRECTORIES}
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>)
@@ -312,6 +315,7 @@ if (NOT HAVE_STRTOLL)
check_symbol_exists(_strtoi64 stdlib.h HAVE_STRTOI64)
endif()
check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF)
+check_symbol_exists(memset_s string.h HAVE_MEMSET_S)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR
${CMAKE_SYSTEM_NAME} STREQUAL "Interix")
@@ -322,7 +326,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR
# filesystem here"
#
# Mac OS X's poll has funny behaviors, like:
- # not being able to do poll on no fildescriptors (10.3?)
+ # not being able to do poll on no filedescriptors (10.3?)
# 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
@@ -333,7 +337,7 @@ endif()
append_needed_socket_libraries(LIBRARIES)
-# Non-blocking socket support tests. Must be after after library tests to
+# Non-blocking socket support tests. Must be after library tests to
# link correctly
set(SAVE_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES})
diff --git a/libs/libssh2/src/Makefile.am b/libs/libssh2/src/Makefile.am
index c14dc7cb3d..31d58ed573 100644
--- a/libs/libssh2/src/Makefile.am
+++ b/libs/libssh2/src/Makefile.am
@@ -1,7 +1,7 @@
# $Id: Makefile.am,v 1.21 2009/05/07 17:21:56 bagder Exp $
AUTOMAKE_OPTIONS = foreign nostdinc
-# Get the CRYPTO_CSOURCES and CRYPTO_HHEADERS defines
+# Get the CRYPTO_CSOURCES, CRYPTO_HHEADERS and CRYPTO_LTLIBS defines
if OPENSSL
include ../Makefile.OpenSSL.inc
endif
@@ -11,9 +11,6 @@ endif
if WINCNG
include ../Makefile.WinCNG.inc
endif
-if OS400QC3
-include ../Makefile.os400qc3.inc
-endif
if MBEDTLS
include ../Makefile.mbedTLS.inc
endif
@@ -65,4 +62,4 @@ VERSION=-version-info 1:1:0
libssh2_la_LDFLAGS = $(VERSION) -no-undefined \
-export-symbols-regex '^libssh2_.*' \
- $(LTLIBGCRYPT) $(LTLIBSSL) $(LTLIBZ)
+ $(CRYPTO_LTLIBS) $(LTLIBZ)
diff --git a/libs/libssh2/src/Makefile.in b/libs/libssh2/src/Makefile.in
index 44533bdede..c00d9dbaec 100644
--- a/libs/libssh2/src/Makefile.in
+++ b/libs/libssh2/src/Makefile.in
@@ -137,12 +137,12 @@ libssh2_la_LIBADD =
am__libssh2_la_SOURCES_DIST = channel.c comp.c crypt.c hostkey.c kex.c \
mac.c misc.c packet.c publickey.c scp.c session.c sftp.c \
userauth.c transport.c version.c knownhost.c agent.c \
- libgcrypt.c mbedtls.c openssl.c os400qc3.c wincng.c pem.c \
- keepalive.c global.c libssh2_priv.h libgcrypt.h mbedtls.h \
- openssl.h os400qc3.h wincng.h transport.h channel.h comp.h \
- mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h
-@LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_FALSE@@OS400QC3_FALSE@@WINCNG_TRUE@am__objects_1 = wincng.lo
-@LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_FALSE@@OS400QC3_TRUE@am__objects_1 = os400qc3.lo
+ libgcrypt.c mbedtls.c openssl.c wincng.c pem.c keepalive.c \
+ global.c blowfish.c bcrypt_pbkdf.c libssh2_priv.h libgcrypt.h \
+ mbedtls.h openssl.h wincng.h transport.h channel.h comp.h \
+ mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h \
+ blf.h
+@LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_FALSE@@WINCNG_TRUE@am__objects_1 = wincng.lo
@LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_TRUE@am__objects_1 = \
@LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_TRUE@ openssl.lo
@LIBGCRYPT_FALSE@@MBEDTLS_TRUE@am__objects_1 = mbedtls.lo
@@ -150,7 +150,8 @@ am__libssh2_la_SOURCES_DIST = channel.c comp.c crypt.c hostkey.c kex.c \
am__objects_2 = channel.lo comp.lo crypt.lo hostkey.lo kex.lo mac.lo \
misc.lo packet.lo publickey.lo scp.lo session.lo sftp.lo \
userauth.lo transport.lo version.lo knownhost.lo agent.lo \
- $(am__objects_1) pem.lo keepalive.lo global.lo
+ $(am__objects_1) pem.lo keepalive.lo global.lo blowfish.lo \
+ bcrypt_pbkdf.lo
am__objects_3 =
am__objects_4 = $(am__objects_3)
am_libssh2_la_OBJECTS = $(am__objects_2) $(am__objects_4)
@@ -177,14 +178,15 @@ am__v_at_1 =
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/agent.Plo ./$(DEPDIR)/channel.Plo \
- ./$(DEPDIR)/comp.Plo ./$(DEPDIR)/crypt.Plo \
- ./$(DEPDIR)/global.Plo ./$(DEPDIR)/hostkey.Plo \
- ./$(DEPDIR)/keepalive.Plo ./$(DEPDIR)/kex.Plo \
- ./$(DEPDIR)/knownhost.Plo ./$(DEPDIR)/libgcrypt.Plo \
- ./$(DEPDIR)/mac.Plo ./$(DEPDIR)/mbedtls.Plo \
- ./$(DEPDIR)/misc.Plo ./$(DEPDIR)/openssl.Plo \
- ./$(DEPDIR)/os400qc3.Plo ./$(DEPDIR)/packet.Plo \
+am__depfiles_remade = ./$(DEPDIR)/agent.Plo \
+ ./$(DEPDIR)/bcrypt_pbkdf.Plo ./$(DEPDIR)/blowfish.Plo \
+ ./$(DEPDIR)/channel.Plo ./$(DEPDIR)/comp.Plo \
+ ./$(DEPDIR)/crypt.Plo ./$(DEPDIR)/global.Plo \
+ ./$(DEPDIR)/hostkey.Plo ./$(DEPDIR)/keepalive.Plo \
+ ./$(DEPDIR)/kex.Plo ./$(DEPDIR)/knownhost.Plo \
+ ./$(DEPDIR)/libgcrypt.Plo ./$(DEPDIR)/mac.Plo \
+ ./$(DEPDIR)/mbedtls.Plo ./$(DEPDIR)/misc.Plo \
+ ./$(DEPDIR)/openssl.Plo ./$(DEPDIR)/packet.Plo \
./$(DEPDIR)/pem.Plo ./$(DEPDIR)/publickey.Plo \
./$(DEPDIR)/scp.Plo ./$(DEPDIR)/session.Plo \
./$(DEPDIR)/sftp.Plo ./$(DEPDIR)/transport.Plo \
@@ -239,8 +241,7 @@ CTAGS = ctags
am__DIST_COMMON = $(srcdir)/../Makefile.OpenSSL.inc \
$(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.inc \
$(srcdir)/../Makefile.libgcrypt.inc \
- $(srcdir)/../Makefile.mbedTLS.inc \
- $(srcdir)/../Makefile.os400qc3.inc $(srcdir)/Makefile.in \
+ $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/Makefile.in \
$(srcdir)/libssh2_config.h.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
@@ -274,7 +275,7 @@ GREP = @GREP@
HAVE_LIBBCRYPT = @HAVE_LIBBCRYPT@
HAVE_LIBCRYPT32 = @HAVE_LIBCRYPT32@
HAVE_LIBGCRYPT = @HAVE_LIBGCRYPT@
-HAVE_LIBMBEDTLS = @HAVE_LIBMBEDTLS@
+HAVE_LIBMBEDCRYPTO = @HAVE_LIBMBEDCRYPTO@
HAVE_LIBSSL = @HAVE_LIBSSL@
HAVE_LIBZ = @HAVE_LIBZ@
INSTALL = @INSTALL@
@@ -290,8 +291,8 @@ LIBCRYPT32 = @LIBCRYPT32@
LIBCRYPT32_PREFIX = @LIBCRYPT32_PREFIX@
LIBGCRYPT = @LIBGCRYPT@
LIBGCRYPT_PREFIX = @LIBGCRYPT_PREFIX@
-LIBMBEDTLS = @LIBMBEDTLS@
-LIBMBEDTLS_PREFIX = @LIBMBEDTLS_PREFIX@
+LIBMBEDCRYPTO = @LIBMBEDCRYPTO@
+LIBMBEDCRYPTO_PREFIX = @LIBMBEDCRYPTO_PREFIX@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBSREQUIRED = @LIBSREQUIRED@
@@ -306,7 +307,7 @@ LN_S = @LN_S@
LTLIBBCRYPT = @LTLIBBCRYPT@
LTLIBCRYPT32 = @LTLIBCRYPT32@
LTLIBGCRYPT = @LTLIBGCRYPT@
-LTLIBMBEDTLS = @LTLIBMBEDTLS@
+LTLIBMBEDCRYPTO = @LTLIBMBEDCRYPTO@
LTLIBOBJS = @LTLIBOBJS@
LTLIBSSL = @LTLIBSSL@
LTLIBZ = @LTLIBZ@
@@ -395,22 +396,25 @@ AUTOMAKE_OPTIONS = foreign nostdinc
@LIBGCRYPT_TRUE@CRYPTO_CSOURCES = libgcrypt.c
@MBEDTLS_TRUE@CRYPTO_CSOURCES = mbedtls.c
@OPENSSL_TRUE@CRYPTO_CSOURCES = openssl.c
-@OS400QC3_TRUE@CRYPTO_CSOURCES = os400qc3.c
@WINCNG_TRUE@CRYPTO_CSOURCES = wincng.c
@LIBGCRYPT_TRUE@CRYPTO_HHEADERS = libgcrypt.h
@MBEDTLS_TRUE@CRYPTO_HHEADERS = mbedtls.h
@OPENSSL_TRUE@CRYPTO_HHEADERS = openssl.h
-@OS400QC3_TRUE@CRYPTO_HHEADERS = os400qc3.h
@WINCNG_TRUE@CRYPTO_HHEADERS = wincng.h
+@LIBGCRYPT_TRUE@CRYPTO_LTLIBS = $(LTLIBGCRYPT)
+@MBEDTLS_TRUE@CRYPTO_LTLIBS = $(LTLIBMBEDCRYPTO)
+@OPENSSL_TRUE@CRYPTO_LTLIBS = $(LTLIBSSL)
+@WINCNG_TRUE@CRYPTO_LTLIBS = $(LTLIBBCRYPT) $(LTLIBCRYPT32)
CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \
packet.c publickey.c scp.c session.c sftp.c userauth.c transport.c \
- version.c knownhost.c agent.c $(CRYPTO_CSOURCES) pem.c keepalive.c global.c
+ version.c knownhost.c agent.c $(CRYPTO_CSOURCES) pem.c keepalive.c global.c \
+ blowfish.c bcrypt_pbkdf.c
HHEADERS = libssh2_priv.h $(CRYPTO_HHEADERS) transport.h channel.h comp.h \
- mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h
+ mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h
-# Get the CRYPTO_CSOURCES and CRYPTO_HHEADERS defines
+# Get the CRYPTO_CSOURCES, CRYPTO_HHEADERS and CRYPTO_LTLIBS defines
# Makefile.inc provides the CSOURCES and HHEADERS defines
libssh2_la_SOURCES = $(CSOURCES) $(HHEADERS)
@@ -452,14 +456,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/src
#
libssh2_la_LDFLAGS = $(VERSION) -no-undefined \
-export-symbols-regex '^libssh2_.*' \
- $(LTLIBGCRYPT) $(LTLIBSSL) $(LTLIBZ)
+ $(CRYPTO_LTLIBS) $(LTLIBZ)
all: libssh2_config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../Makefile.OpenSSL.inc $(srcdir)/../Makefile.libgcrypt.inc $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.os400qc3.inc $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/../Makefile.inc $(am__configure_deps)
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../Makefile.OpenSSL.inc $(srcdir)/../Makefile.libgcrypt.inc $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/../Makefile.inc $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@@ -479,7 +483,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
-$(srcdir)/../Makefile.OpenSSL.inc $(srcdir)/../Makefile.libgcrypt.inc $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.os400qc3.inc $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/../Makefile.inc $(am__empty):
+$(srcdir)/../Makefile.OpenSSL.inc $(srcdir)/../Makefile.libgcrypt.inc $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/../Makefile.inc $(am__empty):
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
@@ -550,6 +554,8 @@ distclean-compile:
-rm -f *.tab.c
@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)/blowfish.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)/comp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypt.Plo@am__quote@ # am--include-marker
@@ -563,7 +569,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbedtls.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os400qc3.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)/publickey.Plo@am__quote@ # am--include-marker
@@ -737,6 +742,8 @@ 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)/blowfish.Plo
-rm -f ./$(DEPDIR)/channel.Plo
-rm -f ./$(DEPDIR)/comp.Plo
-rm -f ./$(DEPDIR)/crypt.Plo
@@ -750,7 +757,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/mbedtls.Plo
-rm -f ./$(DEPDIR)/misc.Plo
-rm -f ./$(DEPDIR)/openssl.Plo
- -rm -f ./$(DEPDIR)/os400qc3.Plo
-rm -f ./$(DEPDIR)/packet.Plo
-rm -f ./$(DEPDIR)/pem.Plo
-rm -f ./$(DEPDIR)/publickey.Plo
@@ -807,6 +813,8 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/agent.Plo
+ -rm -f ./$(DEPDIR)/bcrypt_pbkdf.Plo
+ -rm -f ./$(DEPDIR)/blowfish.Plo
-rm -f ./$(DEPDIR)/channel.Plo
-rm -f ./$(DEPDIR)/comp.Plo
-rm -f ./$(DEPDIR)/crypt.Plo
@@ -820,7 +828,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/mbedtls.Plo
-rm -f ./$(DEPDIR)/misc.Plo
-rm -f ./$(DEPDIR)/openssl.Plo
- -rm -f ./$(DEPDIR)/os400qc3.Plo
-rm -f ./$(DEPDIR)/packet.Plo
-rm -f ./$(DEPDIR)/pem.Plo
-rm -f ./$(DEPDIR)/publickey.Plo
diff --git a/libs/libssh2/src/agent.c b/libs/libssh2/src/agent.c
index c2ba422b65..0c8d881665 100644
--- a/libs/libssh2/src/agent.c
+++ b/libs/libssh2/src/agent.c
@@ -138,6 +138,8 @@ struct _LIBSSH2_AGENT
struct agent_transaction_ctx transctx;
struct agent_publickey *identity;
struct list_head head; /* list of public keys */
+
+ char *identity_agent_path; /* Path to a custom identity agent socket */
};
#ifdef PF_UNIX
@@ -147,22 +149,25 @@ agent_connect_unix(LIBSSH2_AGENT *agent)
const char *path;
struct sockaddr_un s_un;
- path = getenv("SSH_AUTH_SOCK");
- if (!path)
- return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
- "no auth sock variable");
+ path = agent->identity_agent_path;
+ if(!path) {
+ path = getenv("SSH_AUTH_SOCK");
+ if(!path)
+ return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
+ "no auth sock variable");
+ }
agent->fd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (agent->fd < 0)
+ if(agent->fd < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_SOCKET,
"failed creating socket");
s_un.sun_family = AF_UNIX;
- strncpy (s_un.sun_path, path, sizeof s_un.sun_path);
- s_un.sun_path[sizeof(s_un.sun_path)-1]=0; /* make sure there's a trailing
- zero */
- if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) {
- close (agent->fd);
+ strncpy(s_un.sun_path, path, sizeof s_un.sun_path);
+ s_un.sun_path[sizeof(s_un.sun_path)-1] = 0; /* make sure there's a trailing
+ zero */
+ if(connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) {
+ close(agent->fd);
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting with agent");
}
@@ -177,34 +182,34 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
int rc;
/* Send the length of the request */
- if (transctx->state == agent_NB_state_request_created) {
+ if(transctx->state == agent_NB_state_request_created) {
_libssh2_htonu32(buf, transctx->request_len);
rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0);
- if (rc == -EAGAIN)
+ if(rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
- else if (rc < 0)
+ else if(rc < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent send failed");
transctx->state = agent_NB_state_request_length_sent;
}
/* Send the request body */
- if (transctx->state == agent_NB_state_request_length_sent) {
+ if(transctx->state == agent_NB_state_request_length_sent) {
rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request,
transctx->request_len, 0);
- if (rc == -EAGAIN)
+ if(rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
- else if (rc < 0)
+ else if(rc < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent send failed");
transctx->state = agent_NB_state_request_sent;
}
/* Receive the length of a response */
- if (transctx->state == agent_NB_state_request_sent) {
+ if(transctx->state == agent_NB_state_request_sent) {
rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0);
- if (rc < 0) {
- if (rc == -EAGAIN)
+ if(rc < 0) {
+ if(rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
"agent recv failed");
@@ -212,18 +217,18 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
transctx->response_len = _libssh2_ntohu32(buf);
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
- if (!transctx->response)
+ if(!transctx->response)
return LIBSSH2_ERROR_ALLOC;
transctx->state = agent_NB_state_response_length_received;
}
/* Receive the response body */
- if (transctx->state == agent_NB_state_response_length_received) {
+ if(transctx->state == agent_NB_state_response_length_received) {
rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response,
transctx->response_len, 0);
- if (rc < 0) {
- if (rc == -EAGAIN)
+ if(rc < 0) {
+ if(rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
"agent recv failed");
@@ -270,7 +275,7 @@ agent_connect_pageant(LIBSSH2_AGENT *agent)
{
HWND hwnd;
hwnd = FindWindow("Pageant", "Pageant");
- if (!hwnd)
+ if(!hwnd)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting agent");
agent->fd = 0; /* Mark as the connection has been established */
@@ -288,25 +293,26 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
int id;
COPYDATASTRUCT cds;
- if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN)
+ if(!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN)
return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL,
"illegal input");
hwnd = FindWindow("Pageant", "Pageant");
- if (!hwnd)
+ if(!hwnd)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"found no pageant");
- sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId());
+ snprintf(mapname, sizeof(mapname),
+ "PageantRequest%08x%c", (unsigned)GetCurrentThreadId(), '\0');
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, PAGEANT_MAX_MSGLEN, mapname);
- if (filemap == NULL || filemap == INVALID_HANDLE_VALUE)
+ if(filemap == NULL || filemap == INVALID_HANDLE_VALUE)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed setting up pageant filemap");
p2 = p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
- if (p == NULL || p2 == NULL) {
+ if(p == NULL || p2 == NULL) {
CloseHandle(filemap);
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed to open pageant filemap for writing");
@@ -320,9 +326,9 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
cds.lpData = mapname;
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
- if (id > 0) {
+ if(id > 0) {
transctx->response_len = _libssh2_ntohu32(p);
- if (transctx->response_len > PAGEANT_MAX_MSGLEN) {
+ if(transctx->response_len > PAGEANT_MAX_MSGLEN) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
@@ -330,7 +336,7 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
}
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
- if (!transctx->response) {
+ if(!transctx->response) {
UnmapViewOfFile(p);
CloseHandle(filemap);
return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC,
@@ -384,9 +390,9 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
int rc;
/* Create a request to sign the data */
- if (transctx->state == agent_NB_state_init) {
+ if(transctx->state == agent_NB_state_init) {
s = transctx->request = LIBSSH2_ALLOC(session, len);
- if (!transctx->request)
+ if(!transctx->request)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"out of memory");
@@ -405,17 +411,17 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
}
/* Make sure to be re-called as a result of EAGAIN. */
- if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST)
+ if(*transctx->request != SSH2_AGENTC_SIGN_REQUEST)
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"illegal request");
- if (!agent->ops)
+ if(!agent->ops)
/* if no agent has been connected, bail out */
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"agent not connected");
rc = agent->ops->transact(agent, transctx);
- if (rc) {
+ if(rc) {
goto error;
}
LIBSSH2_FREE(session, transctx->request);
@@ -424,11 +430,11 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
len = transctx->response_len;
s = transctx->response;
len--;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
- if (*s != SSH2_AGENT_SIGN_RESPONSE) {
+ if(*s != SSH2_AGENT_SIGN_RESPONSE) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
@@ -436,7 +442,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
/* Skip the entire length of the signature */
len -= 4;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
@@ -444,14 +450,14 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
/* Skip signing method */
len -= 4;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
method_len = _libssh2_ntohu32(s);
s += 4;
len -= method_len;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
@@ -459,20 +465,20 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
/* Read the signature */
len -= 4;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
*sig_len = _libssh2_ntohu32(s);
s += 4;
len -= *sig_len;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
*sig = LIBSSH2_ALLOC(session, *sig_len);
- if (!*sig) {
+ if(!*sig) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
@@ -498,24 +504,24 @@ agent_list_identities(LIBSSH2_AGENT *agent)
unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES;
/* Create a request to list identities */
- if (transctx->state == agent_NB_state_init) {
+ if(transctx->state == agent_NB_state_init) {
transctx->request = &c;
transctx->request_len = 1;
transctx->state = agent_NB_state_request_created;
}
/* Make sure to be re-called as a result of EAGAIN. */
- if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES)
+ if(*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES)
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
"illegal agent request");
- if (!agent->ops)
+ if(!agent->ops)
/* if no agent has been connected, bail out */
return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE,
"agent not connected");
rc = agent->ops->transact(agent, transctx);
- if (rc) {
+ if(rc) {
goto error;
}
transctx->request = NULL;
@@ -523,11 +529,11 @@ agent_list_identities(LIBSSH2_AGENT *agent)
len = transctx->response_len;
s = transctx->response;
len--;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
- if (*s != SSH2_AGENT_IDENTITIES_ANSWER) {
+ if(*s != SSH2_AGENT_IDENTITIES_ANSWER) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
@@ -535,25 +541,25 @@ agent_list_identities(LIBSSH2_AGENT *agent)
/* Read the length of identities */
len -= 4;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
num_identities = _libssh2_ntohu32(s);
s += 4;
- while (num_identities--) {
+ while(num_identities--) {
struct agent_publickey *identity;
ssize_t comment_len;
/* Read the length of the blob */
len -= 4;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
identity = LIBSSH2_ALLOC(agent->session, sizeof *identity);
- if (!identity) {
+ if(!identity) {
rc = LIBSSH2_ERROR_ALLOC;
goto error;
}
@@ -562,7 +568,7 @@ agent_list_identities(LIBSSH2_AGENT *agent)
/* Read the blob */
len -= identity->external.blob_len;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
LIBSSH2_FREE(agent->session, identity);
goto error;
@@ -570,7 +576,7 @@ agent_list_identities(LIBSSH2_AGENT *agent)
identity->external.blob = LIBSSH2_ALLOC(agent->session,
identity->external.blob_len);
- if (!identity->external.blob) {
+ if(!identity->external.blob) {
rc = LIBSSH2_ERROR_ALLOC;
LIBSSH2_FREE(agent->session, identity);
goto error;
@@ -580,7 +586,7 @@ agent_list_identities(LIBSSH2_AGENT *agent)
/* Read the length of the comment */
len -= 4;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
LIBSSH2_FREE(agent->session, identity->external.blob);
LIBSSH2_FREE(agent->session, identity);
@@ -591,7 +597,7 @@ agent_list_identities(LIBSSH2_AGENT *agent)
/* Read the comment */
len -= comment_len;
- if (len < 0) {
+ if(len < 0) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
LIBSSH2_FREE(agent->session, identity->external.blob);
LIBSSH2_FREE(agent->session, identity);
@@ -600,7 +606,7 @@ agent_list_identities(LIBSSH2_AGENT *agent)
identity->external.comment = LIBSSH2_ALLOC(agent->session,
comment_len + 1);
- if (!identity->external.comment) {
+ if(!identity->external.comment) {
rc = LIBSSH2_ERROR_ALLOC;
LIBSSH2_FREE(agent->session, identity->external.blob);
LIBSSH2_FREE(agent->session, identity);
@@ -621,11 +627,12 @@ agent_list_identities(LIBSSH2_AGENT *agent)
}
static void
-agent_free_identities(LIBSSH2_AGENT *agent) {
+agent_free_identities(LIBSSH2_AGENT *agent)
+{
struct agent_publickey *node;
struct agent_publickey *next;
- for (node = _libssh2_list_first(&agent->head); node; node = next) {
+ for(node = _libssh2_list_first(&agent->head); node; node = next) {
next = _libssh2_list_next(&node->node);
LIBSSH2_FREE(agent->session, node->external.blob);
LIBSSH2_FREE(agent->session, node->external.comment);
@@ -664,13 +671,14 @@ libssh2_agent_init(LIBSSH2_SESSION *session)
LIBSSH2_AGENT *agent;
agent = LIBSSH2_CALLOC(session, sizeof *agent);
- if (!agent) {
+ if(!agent) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate space for agent connection");
return NULL;
}
agent->fd = LIBSSH2_INVALID_SOCKET;
agent->session = session;
+ agent->identity_agent_path = NULL;
_libssh2_list_init(&agent->head);
return agent;
@@ -687,10 +695,10 @@ LIBSSH2_API int
libssh2_agent_connect(LIBSSH2_AGENT *agent)
{
int i, rc = -1;
- for (i = 0; supported_backends[i].name; i++) {
+ for(i = 0; supported_backends[i].name; i++) {
agent->ops = supported_backends[i].ops;
rc = (agent->ops->connect)(agent);
- if (!rc)
+ if(!rc)
return 0;
}
return rc;
@@ -707,7 +715,7 @@ LIBSSH2_API int
libssh2_agent_list_identities(LIBSSH2_AGENT *agent)
{
memset(&agent->transctx, 0, sizeof agent->transctx);
- /* Abondon the last fetched identities */
+ /* Abandon the last fetched identities */
agent_free_identities(agent);
return agent_list_identities(agent);
}
@@ -730,7 +738,7 @@ libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
struct libssh2_agent_publickey *oprev)
{
struct agent_publickey *node;
- if (oprev && oprev->node) {
+ if(oprev && oprev->node) {
/* we have a starting point */
struct agent_publickey *prev = oprev->node;
@@ -740,7 +748,7 @@ libssh2_agent_get_identity(LIBSSH2_AGENT *agent,
else
node = _libssh2_list_first(&agent->head);
- if (!node)
+ if(!node)
/* no (more) node */
return 1;
@@ -764,7 +772,7 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent,
void *abstract = agent;
int rc;
- if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) {
+ if(agent->session->userauth_pblc_state == libssh2_NB_state_idle) {
memset(&agent->transctx, 0, sizeof agent->transctx);
agent->identity = identity->node;
}
@@ -789,7 +797,7 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent,
LIBSSH2_API int
libssh2_agent_disconnect(LIBSSH2_AGENT *agent)
{
- if (agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET)
+ if(agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET)
return agent->ops->disconnect(agent);
return 0;
}
@@ -801,11 +809,52 @@ libssh2_agent_disconnect(LIBSSH2_AGENT *agent)
* collection of public keys.
*/
LIBSSH2_API void
-libssh2_agent_free(LIBSSH2_AGENT *agent) {
+libssh2_agent_free(LIBSSH2_AGENT *agent)
+{
/* Allow connection freeing when the socket has lost its connection */
- if (agent->fd != LIBSSH2_INVALID_SOCKET) {
+ if(agent->fd != LIBSSH2_INVALID_SOCKET) {
libssh2_agent_disconnect(agent);
}
+
+ if(agent->identity_agent_path != NULL)
+ LIBSSH2_FREE(agent->session, agent->identity_agent_path);
+
agent_free_identities(agent);
LIBSSH2_FREE(agent->session, agent);
}
+
+/*
+ * libssh2_agent_set_identity_path()
+ *
+ * Allows a custom agent socket path beyond SSH_AUTH_SOCK env
+ *
+ */
+LIBSSH2_API void
+libssh2_agent_set_identity_path(LIBSSH2_AGENT *agent, const char *path)
+{
+ if(agent->identity_agent_path) {
+ LIBSSH2_FREE(agent->session, agent->identity_agent_path);
+ agent->identity_agent_path = NULL;
+ }
+
+ if(path) {
+ size_t path_len = strlen(path);
+ if(path_len < SIZE_MAX - 1) {
+ char *path_buf = LIBSSH2_ALLOC(agent->session, path_len + 1);
+ memcpy(path_buf, path, path_len);
+ path_buf[path_len] = '\0';
+ agent->identity_agent_path = path_buf;
+ }
+ }
+}
+
+/*
+ * libssh2_agent_get_identity_path()
+ *
+ * Returns the custom agent socket path if set
+ *
+ */
+LIBSSH2_API const char *libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent)
+{
+ return agent->identity_agent_path;
+}
diff --git a/libs/libssh2/src/bcrypt_pbkdf.c b/libs/libssh2/src/bcrypt_pbkdf.c
new file mode 100644
index 0000000000..e92969a00c
--- /dev/null
+++ b/libs/libssh2/src/bcrypt_pbkdf.c
@@ -0,0 +1,180 @@
+/* $OpenBSD: bcrypt_pbkdf.c,v 1.4 2013/07/29 00:55:53 tedu Exp $ */
+/*
+ * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
+ *
+ * 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.
+ */
+
+
+#ifndef HAVE_BCRYPT_PBKDF
+
+#include "libssh2_priv.h"
+#include <stdlib.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "blf.h"
+
+#define MINIMUM(a,b) (((a) < (b)) ? (a) : (b))
+
+/*
+ * pkcs #5 pbkdf2 implementation using the "bcrypt" hash
+ *
+ * The bcrypt hash function is derived from the bcrypt password hashing
+ * function with the following modifications:
+ * 1. The input password and salt are preprocessed with SHA512.
+ * 2. The output length is expanded to 256 bits.
+ * 3. Subsequently the magic string to be encrypted is lengthened and modifed
+ * to "OxychromaticBlowfishSwatDynamite"
+ * 4. The hash function is defined to perform 64 rounds of initial state
+ * expansion. (More rounds are performed by iterating the hash.)
+ *
+ * Note that this implementation pulls the SHA512 operations into the caller
+ * as a performance optimization.
+ *
+ * One modification from official pbkdf2. Instead of outputting key material
+ * linearly, we mix it. pbkdf2 has a known weakness where if one uses it to
+ * generate (i.e.) 512 bits of key material for use as two 256 bit keys, an
+ * attacker can merely run once through the outer loop below, but the user
+ * always runs it twice. Shuffling output bytes requires computing the
+ * entirety of the key material to assemble any subkey. This is something a
+ * wise caller could do; we just do it for you.
+ */
+
+#define BCRYPT_BLOCKS 8
+#define BCRYPT_HASHSIZE (BCRYPT_BLOCKS * 4)
+
+static void
+bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
+{
+ blf_ctx state;
+ uint8_t ciphertext[BCRYPT_HASHSIZE] =
+ "OxychromaticBlowfishSwatDynamite";
+ uint32_t cdata[BCRYPT_BLOCKS];
+ int i;
+ uint16_t j;
+ size_t shalen = SHA512_DIGEST_LENGTH;
+
+ /* key expansion */
+ Blowfish_initstate(&state);
+ Blowfish_expandstate(&state, sha2salt, shalen, sha2pass, shalen);
+ for(i = 0; i < 64; i++) {
+ Blowfish_expand0state(&state, sha2salt, shalen);
+ Blowfish_expand0state(&state, sha2pass, shalen);
+ }
+
+ /* encryption */
+ j = 0;
+ for(i = 0; i < BCRYPT_BLOCKS; i++)
+ cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
+ &j);
+ for(i = 0; i < 64; i++)
+ blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
+
+ /* copy out */
+ for(i = 0; i < BCRYPT_BLOCKS; i++) {
+ out[4 * i + 3] = (cdata[i] >> 24) & 0xff;
+ out[4 * i + 2] = (cdata[i] >> 16) & 0xff;
+ out[4 * i + 1] = (cdata[i] >> 8) & 0xff;
+ out[4 * i + 0] = cdata[i] & 0xff;
+ }
+
+ /* zap */
+ _libssh2_explicit_zero(ciphertext, sizeof(ciphertext));
+ _libssh2_explicit_zero(cdata, sizeof(cdata));
+ _libssh2_explicit_zero(&state, sizeof(state));
+}
+
+int
+bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
+ size_t saltlen,
+ uint8_t *key, size_t keylen, unsigned int rounds)
+{
+ uint8_t sha2pass[SHA512_DIGEST_LENGTH];
+ uint8_t sha2salt[SHA512_DIGEST_LENGTH];
+ uint8_t out[BCRYPT_HASHSIZE];
+ uint8_t tmpout[BCRYPT_HASHSIZE];
+ uint8_t *countsalt;
+ size_t i, j, amt, stride;
+ uint32_t count;
+ size_t origkeylen = keylen;
+ libssh2_sha512_ctx ctx;
+
+ /* nothing crazy */
+ if(rounds < 1)
+ return -1;
+ if(passlen == 0 || saltlen == 0 || keylen == 0 ||
+ keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20)
+ return -1;
+ countsalt = calloc(1, saltlen + 4);
+ if(countsalt == NULL)
+ return -1;
+ stride = (keylen + sizeof(out) - 1) / sizeof(out);
+ amt = (keylen + stride - 1) / stride;
+
+ memcpy(countsalt, salt, saltlen);
+
+ /* collapse password */
+ libssh2_sha512_init(&ctx);
+ libssh2_sha512_update(ctx, pass, passlen);
+ libssh2_sha512_final(ctx, sha2pass);
+
+ /* generate key, sizeof(out) at a time */
+ for(count = 1; keylen > 0; count++) {
+ countsalt[saltlen + 0] = (count >> 24) & 0xff;
+ countsalt[saltlen + 1] = (count >> 16) & 0xff;
+ countsalt[saltlen + 2] = (count >> 8) & 0xff;
+ countsalt[saltlen + 3] = count & 0xff;
+
+ /* first round, salt is salt */
+ libssh2_sha512_init(&ctx);
+ libssh2_sha512_update(ctx, countsalt, saltlen + 4);
+ libssh2_sha512_final(ctx, sha2salt);
+
+ bcrypt_hash(sha2pass, sha2salt, tmpout);
+ memcpy(out, tmpout, sizeof(out));
+
+ for(i = 1; i < rounds; i++) {
+ /* subsequent rounds, salt is previous output */
+ libssh2_sha512_init(&ctx);
+ libssh2_sha512_update(ctx, tmpout, sizeof(tmpout));
+ libssh2_sha512_final(ctx, sha2salt);
+
+ bcrypt_hash(sha2pass, sha2salt, tmpout);
+ for(j = 0; j < sizeof(out); j++)
+ out[j] ^= tmpout[j];
+ }
+
+ /*
+ * pbkdf2 deviation: ouput the key material non-linearly.
+ */
+ amt = MINIMUM(amt, keylen);
+ for(i = 0; i < amt; i++) {
+ size_t dest = i * stride + (count - 1);
+ if(dest >= origkeylen) {
+ break;
+ }
+ key[dest] = out[i];
+ }
+ keylen -= i;
+ }
+
+ /* zap */
+ _libssh2_explicit_zero(out, sizeof(out));
+ free(countsalt);
+
+ return 0;
+}
+#endif /* HAVE_BCRYPT_PBKDF */
diff --git a/libs/libssh2/src/blf.h b/libs/libssh2/src/blf.h
new file mode 100644
index 0000000000..1a85e6eef0
--- /dev/null
+++ b/libs/libssh2/src/blf.h
@@ -0,0 +1,90 @@
+/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
+/*
+ * Blowfish - a fast block cipher designed by Bruce Schneier
+ *
+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Niels Provos.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _BLF_H_
+#define _BLF_H_
+
+#if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H)
+
+/* Schneier specifies a maximum key length of 56 bytes.
+ * This ensures that every key bit affects every cipher
+ * bit. However, the subkeys can hold up to 72 bytes.
+ * Warning: For normal blowfish encryption only 56 bytes
+ * of the key affect all cipherbits.
+ */
+
+#define BLF_N 16 /* Number of Subkeys */
+#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */
+#define BLF_MAXUTILIZED ((BLF_N + 2)*4) /* 576 bits */
+
+/* Blowfish context */
+typedef struct BlowfishContext {
+ uint32_t S[4][256]; /* S-Boxes */
+ uint32_t P[BLF_N + 2]; /* Subkeys */
+} blf_ctx;
+
+/* Raw access to customized Blowfish
+ * blf_key is just:
+ * Blowfish_initstate( state )
+ * Blowfish_expand0state( state, key, keylen )
+ */
+
+void Blowfish_encipher(blf_ctx *, uint32_t *, uint32_t *);
+void Blowfish_decipher(blf_ctx *, uint32_t *, uint32_t *);
+void Blowfish_initstate(blf_ctx *);
+void Blowfish_expand0state(blf_ctx *, const uint8_t *, uint16_t);
+void Blowfish_expandstate
+(blf_ctx *, const uint8_t *, uint16_t, const uint8_t *, uint16_t);
+
+/* Standard Blowfish */
+
+void blf_key(blf_ctx *, const uint8_t *, uint16_t);
+void blf_enc(blf_ctx *, uint32_t *, uint16_t);
+void blf_dec(blf_ctx *, uint32_t *, uint16_t);
+
+void blf_ecb_encrypt(blf_ctx *, uint8_t *, uint32_t);
+void blf_ecb_decrypt(blf_ctx *, uint8_t *, uint32_t);
+
+void blf_cbc_encrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
+void blf_cbc_decrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
+
+/* Converts uint8_t to uint32_t */
+uint32_t Blowfish_stream2word(const uint8_t *, uint16_t, uint16_t *);
+
+/* bcrypt with pbkd */
+int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
+ size_t saltlen,
+ uint8_t *key, size_t keylen, unsigned int rounds);
+
+#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */
+#endif /* _BLF_H */
diff --git a/libs/libssh2/src/blowfish.c b/libs/libssh2/src/blowfish.c
new file mode 100644
index 0000000000..4aefc66ac7
--- /dev/null
+++ b/libs/libssh2/src/blowfish.c
@@ -0,0 +1,697 @@
+/* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */
+/*
+ * Blowfish block cipher for OpenBSD
+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
+ * All rights reserved.
+ *
+ * Implementation advice by David Mazieres <dm@lcs.mit.edu>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Niels Provos.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This code is derived from section 14.3 and the given source
+ * in section V of Applied Cryptography, second edition.
+ * Blowfish is an unpatented fast block cipher designed by
+ * Bruce Schneier.
+ */
+
+
+#if !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \
+ !defined(HAVE_BLOWFISH_EXPAND0STATE) || \
+ !defined(HAVE_BLF_ENC))
+
+#if 0
+#include <stdio.h> /* used for debugging */
+#include <string.h>
+#endif
+
+#include <sys/types.h>
+
+#include "libssh2.h"
+#include "blf.h"
+
+#undef inline
+#ifdef __GNUC__
+#define inline __inline
+#else /* !__GNUC__ */
+#define inline
+#endif /* !__GNUC__ */
+
+/* Function for Feistel Networks */
+
+#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \
+ + (s)[0x100 + (((x)>>16)&0xFF)]) \
+ ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \
+ + (s)[0x300 + ( (x) &0xFF)])
+
+#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
+
+void
+Blowfish_encipher(blf_ctx *c, uint32_t *xl, uint32_t *xr)
+{
+ uint32_t Xl;
+ uint32_t Xr;
+ uint32_t *s = c->S[0];
+ uint32_t *p = c->P;
+
+ Xl = *xl;
+ Xr = *xr;
+
+ Xl ^= p[0];
+ BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
+ BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
+ BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
+ BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
+ BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
+ BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
+ BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
+ BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
+
+ *xl = Xr ^ p[17];
+ *xr = Xl;
+}
+
+void
+Blowfish_decipher(blf_ctx *c, uint32_t *xl, uint32_t *xr)
+{
+ uint32_t Xl;
+ uint32_t Xr;
+ uint32_t *s = c->S[0];
+ uint32_t *p = c->P;
+
+ Xl = *xl;
+ Xr = *xr;
+
+ Xl ^= p[17];
+ BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
+ BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
+ BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
+ BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
+ BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
+ BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
+ BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
+ BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
+
+ *xl = Xr ^ p[0];
+ *xr = Xl;
+}
+
+void
+Blowfish_initstate(blf_ctx *c)
+{
+ /* P-box and S-box tables initialized with digits of Pi */
+
+ static const blf_ctx initstate =
+ { {
+ {
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
+ {
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+ 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+ 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+ 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+ 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+ 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+ 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+ 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+ 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+ 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
+ {
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
+ {
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+ 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+ 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+ 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+ 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+ 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+ 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+ 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+ 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+ 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+ 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
+ },
+ {
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+ 0x9216d5d9, 0x8979fb1b
+ } };
+
+ *c = initstate;
+}
+
+uint32_t
+Blowfish_stream2word(const uint8_t *data, uint16_t databytes,
+ uint16_t *current)
+{
+ uint8_t i;
+ uint16_t j;
+ uint32_t temp;
+
+ temp = 0x00000000;
+ j = *current;
+
+ for(i = 0; i < 4; i++, j++) {
+ if(j >= databytes)
+ j = 0;
+ temp = (temp << 8) | data[j];
+ }
+
+ *current = j;
+ return temp;
+}
+
+void
+Blowfish_expand0state(blf_ctx *c, const uint8_t *key, uint16_t keybytes)
+{
+ uint16_t i;
+ uint16_t j;
+ uint16_t k;
+ uint32_t temp;
+ uint32_t datal;
+ uint32_t datar;
+
+ j = 0;
+ for(i = 0; i < BLF_N + 2; i++) {
+ /* Extract 4 int8 to 1 int32 from keystream */
+ temp = Blowfish_stream2word(key, keybytes, &j);
+ c->P[i] = c->P[i] ^ temp;
+ }
+
+ j = 0;
+ datal = 0x00000000;
+ datar = 0x00000000;
+ for(i = 0; i < BLF_N + 2; i += 2) {
+ Blowfish_encipher(c, &datal, &datar);
+
+ c->P[i] = datal;
+ c->P[i + 1] = datar;
+ }
+
+ for(i = 0; i < 4; i++) {
+ for(k = 0; k < 256; k += 2) {
+ Blowfish_encipher(c, &datal, &datar);
+
+ c->S[i][k] = datal;
+ c->S[i][k + 1] = datar;
+ }
+ }
+}
+
+
+void
+Blowfish_expandstate(blf_ctx *c, const uint8_t *data, uint16_t databytes,
+ const uint8_t *key, uint16_t keybytes)
+{
+ uint16_t i;
+ uint16_t j;
+ uint16_t k;
+ uint32_t temp;
+ uint32_t datal;
+ uint32_t datar;
+
+ j = 0;
+ for(i = 0; i < BLF_N + 2; i++) {
+ /* Extract 4 int8 to 1 int32 from keystream */
+ temp = Blowfish_stream2word(key, keybytes, &j);
+ c->P[i] = c->P[i] ^ temp;
+ }
+
+ j = 0;
+ datal = 0x00000000;
+ datar = 0x00000000;
+ for(i = 0; i < BLF_N + 2; i += 2) {
+ datal ^= Blowfish_stream2word(data, databytes, &j);
+ datar ^= Blowfish_stream2word(data, databytes, &j);
+ Blowfish_encipher(c, &datal, &datar);
+
+ c->P[i] = datal;
+ c->P[i + 1] = datar;
+ }
+
+ for(i = 0; i < 4; i++) {
+ for(k = 0; k < 256; k += 2) {
+ datal ^= Blowfish_stream2word(data, databytes, &j);
+ datar ^= Blowfish_stream2word(data, databytes, &j);
+ Blowfish_encipher(c, &datal, &datar);
+
+ c->S[i][k] = datal;
+ c->S[i][k + 1] = datar;
+ }
+ }
+
+}
+
+void
+blf_key(blf_ctx *c, const uint8_t *k, uint16_t len)
+{
+ /* Initialize S-boxes and subkeys with Pi */
+ Blowfish_initstate(c);
+
+ /* Transform S-boxes and subkeys with key */
+ Blowfish_expand0state(c, k, len);
+}
+
+void
+blf_enc(blf_ctx *c, uint32_t *data, uint16_t blocks)
+{
+ uint32_t *d;
+ uint16_t i;
+
+ d = data;
+ for(i = 0; i < blocks; i++) {
+ Blowfish_encipher(c, d, d + 1);
+ d += 2;
+ }
+}
+
+void
+blf_dec(blf_ctx *c, uint32_t *data, uint16_t blocks)
+{
+ uint32_t *d;
+ uint16_t i;
+
+ d = data;
+ for(i = 0; i < blocks; i++) {
+ Blowfish_decipher(c, d, d + 1);
+ d += 2;
+ }
+}
+
+void
+blf_ecb_encrypt(blf_ctx *c, uint8_t *data, uint32_t len)
+{
+ uint32_t l, r;
+ uint32_t i;
+
+ for(i = 0; i < len; i += 8) {
+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+ Blowfish_encipher(c, &l, &r);
+ data[0] = l >> 24 & 0xff;
+ data[1] = l >> 16 & 0xff;
+ data[2] = l >> 8 & 0xff;
+ data[3] = l & 0xff;
+ data[4] = r >> 24 & 0xff;
+ data[5] = r >> 16 & 0xff;
+ data[6] = r >> 8 & 0xff;
+ data[7] = r & 0xff;
+ data += 8;
+ }
+}
+
+void
+blf_ecb_decrypt(blf_ctx *c, uint8_t *data, uint32_t len)
+{
+ uint32_t l, r;
+ uint32_t i;
+
+ for(i = 0; i < len; i += 8) {
+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+ Blowfish_decipher(c, &l, &r);
+ data[0] = l >> 24 & 0xff;
+ data[1] = l >> 16 & 0xff;
+ data[2] = l >> 8 & 0xff;
+ data[3] = l & 0xff;
+ data[4] = r >> 24 & 0xff;
+ data[5] = r >> 16 & 0xff;
+ data[6] = r >> 8 & 0xff;
+ data[7] = r & 0xff;
+ data += 8;
+ }
+}
+
+void
+blf_cbc_encrypt(blf_ctx *c, uint8_t *iv, uint8_t *data, uint32_t len)
+{
+ uint32_t l, r;
+ uint32_t i, j;
+
+ for(i = 0; i < len; i += 8) {
+ for(j = 0; j < 8; j++)
+ data[j] ^= iv[j];
+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+ Blowfish_encipher(c, &l, &r);
+ data[0] = l >> 24 & 0xff;
+ data[1] = l >> 16 & 0xff;
+ data[2] = l >> 8 & 0xff;
+ data[3] = l & 0xff;
+ data[4] = r >> 24 & 0xff;
+ data[5] = r >> 16 & 0xff;
+ data[6] = r >> 8 & 0xff;
+ data[7] = r & 0xff;
+ iv = data;
+ data += 8;
+ }
+}
+
+void
+blf_cbc_decrypt(blf_ctx *c, uint8_t *iva, uint8_t *data, uint32_t len)
+{
+ uint32_t l, r;
+ uint8_t *iv;
+ uint32_t i, j;
+
+ iv = data + len - 16;
+ data = data + len - 8;
+ for(i = len - 8; i >= 8; i -= 8) {
+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+ Blowfish_decipher(c, &l, &r);
+ data[0] = l >> 24 & 0xff;
+ data[1] = l >> 16 & 0xff;
+ data[2] = l >> 8 & 0xff;
+ data[3] = l & 0xff;
+ data[4] = r >> 24 & 0xff;
+ data[5] = r >> 16 & 0xff;
+ data[6] = r >> 8 & 0xff;
+ data[7] = r & 0xff;
+ for(j = 0; j < 8; j++)
+ data[j] ^= iv[j];
+ iv -= 8;
+ data -= 8;
+ }
+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
+ Blowfish_decipher(c, &l, &r);
+ data[0] = l >> 24 & 0xff;
+ data[1] = l >> 16 & 0xff;
+ data[2] = l >> 8 & 0xff;
+ data[3] = l & 0xff;
+ data[4] = r >> 24 & 0xff;
+ data[5] = r >> 16 & 0xff;
+ data[6] = r >> 8 & 0xff;
+ data[7] = r & 0xff;
+ for(j = 0; j < 8; j++)
+ data[j] ^= iva[j];
+}
+
+#if 0
+void
+report(uint32_t data[], uint16_t len)
+{
+ uint16_t i;
+ for(i = 0; i < len; i += 2)
+ printf("Block %0hd: %08lx %08lx.\n",
+ i / 2, data[i], data[i + 1]);
+}
+void
+main(void)
+{
+
+ blf_ctx c;
+ char key[] = "AAAAA";
+ char key2[] = "abcdefghijklmnopqrstuvwxyz";
+
+ uint32_t data[10];
+ uint32_t data2[] =
+ {0x424c4f57l, 0x46495348l};
+
+ uint16_t i;
+
+ /* First test */
+ for(i = 0; i < 10; i++)
+ data[i] = i;
+
+ blf_key(&c, (uint8_t *) key, 5);
+ blf_enc(&c, data, 5);
+ blf_dec(&c, data, 1);
+ blf_dec(&c, data + 2, 4);
+ printf("Should read as 0 - 9.\n");
+ report(data, 10);
+
+ /* Second test */
+ blf_key(&c, (uint8_t *) key2, strlen(key2));
+ blf_enc(&c, data2, 1);
+ printf("\nShould read as: 0x324ed0fe 0xf413a203.\n");
+ report(data2, 2);
+ blf_dec(&c, data2, 1);
+ report(data2, 2);
+}
+#endif
+
+#endif /* !defined(HAVE_BCRYPT_PBKDF) && \
+ (!defined(HAVE_BLOWFISH_INITSTATE) || \
+ !defined(HAVE_BLOWFISH_EXPAND0STATE) || \
+ '!defined(HAVE_BLF_ENC)) */
diff --git a/libs/libssh2/src/channel.c b/libs/libssh2/src/channel.c
index 39ff05bf13..7bbeeb88f6 100644
--- a/libs/libssh2/src/channel.c
+++ b/libs/libssh2/src/channel.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net>
- * Copyright (c) 2008-2014 by Daniel Stenberg
+ * Copyright (c) 2008-2019 by Daniel Stenberg
*
* All rights reserved.
*
@@ -66,8 +66,8 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session)
channel = _libssh2_list_first(&session->channels);
- while (channel) {
- if (channel->local.id > id) {
+ while(channel) {
+ if(channel->local.id > id) {
id = channel->local.id;
}
channel = _libssh2_list_next(&channel->node);
@@ -100,7 +100,7 @@ _libssh2_channel_locate(LIBSSH2_SESSION *session, uint32_t channel_id)
for(channel = _libssh2_list_first(&session->channels);
channel;
channel = _libssh2_list_next(&channel->node)) {
- if (channel->local.id == channel_id)
+ if(channel->local.id == channel_id)
return channel;
}
@@ -112,7 +112,7 @@ _libssh2_channel_locate(LIBSSH2_SESSION *session, uint32_t channel_id)
for(channel = _libssh2_list_first(&l->queue);
channel;
channel = _libssh2_list_next(&channel->node)) {
- if (channel->local.id == channel_id)
+ if(channel->local.id == channel_id)
return channel;
}
}
@@ -141,7 +141,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
unsigned char *s;
int rc;
- if (session->open_state == libssh2_NB_state_idle) {
+ if(session->open_state == libssh2_NB_state_idle) {
session->open_channel = NULL;
session->open_packet = NULL;
session->open_data = NULL;
@@ -159,7 +159,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
packet_size);
session->open_channel =
LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
- if (!session->open_channel) {
+ if(!session->open_channel) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate space for channel data");
return NULL;
@@ -167,7 +167,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
session->open_channel->channel_type_len = channel_type_len;
session->open_channel->channel_type =
LIBSSH2_ALLOC(session, channel_type_len);
- if (!session->open_channel->channel_type) {
+ if(!session->open_channel->channel_type) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Failed allocating memory for channel type name");
LIBSSH2_FREE(session, session->open_channel);
@@ -189,7 +189,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
s = session->open_packet =
LIBSSH2_ALLOC(session, session->open_packet_len);
- if (!session->open_packet) {
+ if(!session->open_packet) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate temporary space for packet");
goto channel_error;
@@ -205,17 +205,17 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
session->open_state = libssh2_NB_state_created;
}
- if (session->open_state == libssh2_NB_state_created) {
+ if(session->open_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session,
session->open_packet,
session->open_packet_len,
message, message_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending channel-open request");
return NULL;
}
- else if (rc) {
+ else if(rc) {
_libssh2_error(session, rc,
"Unable to send channel-open request");
goto channel_error;
@@ -224,17 +224,18 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
session->open_state = libssh2_NB_state_sent;
}
- if (session->open_state == libssh2_NB_state_sent) {
+ if(session->open_state == libssh2_NB_state_sent) {
rc = _libssh2_packet_requirev(session, reply_codes,
&session->open_data,
&session->open_data_len, 1,
session->open_packet + 5 +
channel_type_len, 4,
&session->open_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
return NULL;
- } else if (rc) {
+ }
+ else if(rc) {
goto channel_error;
}
@@ -244,9 +245,9 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
goto channel_error;
}
- if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
-
- if(session->open_data_len < 17) {
+ if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
+
+ if(session->open_data_len < 17) {
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet size");
goto channel_error;
@@ -278,12 +279,14 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
return session->open_channel;
}
- if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) {
- unsigned int reason_code = _libssh2_ntohu32(session->open_data + 5);
- switch (reason_code) {
+ if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) {
+ unsigned int reason_code =
+ _libssh2_ntohu32(session->open_data + 5);
+ switch(reason_code) {
case SSH_OPEN_ADMINISTRATIVELY_PROHIBITED:
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
- "Channel open failure (administratively prohibited)");
+ "Channel open failure "
+ "(administratively prohibited)");
break;
case SSH_OPEN_CONNECT_FAILED:
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
@@ -306,15 +309,15 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
channel_error:
- if (session->open_data) {
+ if(session->open_data) {
LIBSSH2_FREE(session, session->open_data);
session->open_data = NULL;
}
- if (session->open_packet) {
+ if(session->open_packet) {
LIBSSH2_FREE(session, session->open_packet);
session->open_packet = NULL;
}
- if (session->open_channel) {
+ if(session->open_channel) {
unsigned char channel_id[4];
LIBSSH2_FREE(session, session->open_channel->channel_type);
@@ -322,7 +325,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
/* Clear out packets meant for this channel */
_libssh2_htonu32(channel_id, session->open_channel->local.id);
- while ((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA,
+ while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA,
&session->open_data,
&session->open_data_len, 1,
channel_id, 4) >= 0)
@@ -379,7 +382,7 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
LIBSSH2_CHANNEL *channel;
unsigned char *s;
- if (session->direct_state == libssh2_NB_state_idle) {
+ if(session->direct_state == libssh2_NB_state_idle) {
session->direct_host_len = strlen(host);
session->direct_shost_len = strlen(shost);
/* host_len(4) + port(4) + shost_len(4) + sport(4) */
@@ -387,14 +390,15 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
session->direct_host_len + session->direct_shost_len + 16;
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
- "Requesting direct-tcpip session to from %s:%d to %s:%d",
+ "Requesting direct-tcpip session from %s:%d to %s:%d",
shost, sport, host, port);
s = session->direct_message =
LIBSSH2_ALLOC(session, session->direct_message_len);
- if (!session->direct_message) {
+ if(!session->direct_message) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate memory for direct-tcpip connection");
+ "Unable to allocate memory for "
+ "direct-tcpip connection");
return NULL;
}
_libssh2_store_str(&s, host, session->direct_host_len);
@@ -411,7 +415,7 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
session->direct_message,
session->direct_message_len);
- if (!channel &&
+ if(!channel &&
libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
/* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state
to created to avoid re-creating the package on next invoke */
@@ -442,7 +446,8 @@ libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host,
return NULL;
BLOCK_ADJUST_ERRNO(ptr, session,
- channel_direct_tcpip(session, host, port, shost, sport));
+ channel_direct_tcpip(session, host, port,
+ shost, sport));
return ptr;
}
@@ -463,7 +468,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
if(!host)
host = "0.0.0.0";
- if (session->fwdLstn_state == libssh2_NB_state_idle) {
+ if(session->fwdLstn_state == libssh2_NB_state_idle) {
session->fwdLstn_host_len = strlen(host);
/* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4)
+ port(4) */
@@ -480,7 +485,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
s = session->fwdLstn_packet =
LIBSSH2_ALLOC(session, session->fwdLstn_packet_len);
- if (!session->fwdLstn_packet) {
+ if(!session->fwdLstn_packet) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for setenv packet");
return NULL;
@@ -496,18 +501,18 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
session->fwdLstn_state = libssh2_NB_state_created;
}
- if (session->fwdLstn_state == libssh2_NB_state_created) {
+ if(session->fwdLstn_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session,
session->fwdLstn_packet,
session->fwdLstn_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending global-request packet for "
"forward listen request");
return NULL;
}
- else if (rc) {
+ else if(rc) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send global-request packet for forward "
"listen request");
@@ -522,34 +527,36 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
session->fwdLstn_state = libssh2_NB_state_sent;
}
- if (session->fwdLstn_state == libssh2_NB_state_sent) {
+ if(session->fwdLstn_state == libssh2_NB_state_sent) {
unsigned char *data;
size_t data_len;
rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
0, NULL, 0,
&session->fwdLstn_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
return NULL;
- } else if (rc || data_len < 1) {
+ }
+ else if(rc || (data_len < 1)) {
_libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
session->fwdLstn_state = libssh2_NB_state_idle;
return NULL;
}
- if (data[0] == SSH_MSG_REQUEST_SUCCESS) {
+ if(data[0] == SSH_MSG_REQUEST_SUCCESS) {
LIBSSH2_LISTENER *listener;
listener = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_LISTENER));
- if (!listener)
+ if(!listener)
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for listener queue");
else {
listener->host =
LIBSSH2_ALLOC(session, session->fwdLstn_host_len + 1);
- if (!listener->host) {
+ if(!listener->host) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate memory for listener queue");
+ "Unable to allocate memory "
+ "for listener queue");
LIBSSH2_FREE(session, listener);
listener = NULL;
}
@@ -557,10 +564,11 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
listener->session = session;
memcpy(listener->host, host, session->fwdLstn_host_len);
listener->host[session->fwdLstn_host_len] = 0;
- if (data_len >= 5 && !port) {
+ if(data_len >= 5 && !port) {
listener->port = _libssh2_ntohu32(data + 1);
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
- "Dynamic tcpip-forward port allocated: %d",
+ "Dynamic tcpip-forward port "
+ "allocated: %d",
listener->port);
}
else
@@ -572,7 +580,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
/* append this to the parent's list of listeners */
_libssh2_list_add(&session->listeners, &listener->node);
- if (bound_port) {
+ if(bound_port) {
*bound_port = listener->port;
}
}
@@ -582,7 +590,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
session->fwdLstn_state = libssh2_NB_state_idle;
return listener;
}
- else if (data[0] == SSH_MSG_REQUEST_FAILURE) {
+ else if(data[0] == SSH_MSG_REQUEST_FAILURE) {
LIBSSH2_FREE(session, data);
_libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED,
"Unable to complete request for forward-listen");
@@ -637,13 +645,13 @@ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
int rc;
int retcode = 0;
- if (listener->chanFwdCncl_state == libssh2_NB_state_idle) {
+ if(listener->chanFwdCncl_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Cancelling tcpip-forward session for %s:%d",
listener->host, listener->port);
s = packet = LIBSSH2_ALLOC(session, packet_len);
- if (!packet) {
+ if(!packet) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for setenv packet");
return LIBSSH2_ERROR_ALLOC;
@@ -658,19 +666,20 @@ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
_libssh2_store_u32(&s, listener->port);
listener->chanFwdCncl_state = libssh2_NB_state_created;
- } else {
+ }
+ else {
packet = listener->chanFwdCncl_data;
}
- if (listener->chanFwdCncl_state == libssh2_NB_state_created) {
+ if(listener->chanFwdCncl_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending forward request");
listener->chanFwdCncl_data = packet;
return rc;
}
- else if (rc) {
+ else if(rc) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send global-request packet for forward "
"listen request");
@@ -686,11 +695,11 @@ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
}
queued = _libssh2_list_first(&listener->queue);
- while (queued) {
+ while(queued) {
LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node);
rc = _libssh2_channel_free(queued);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
queued = next;
@@ -738,9 +747,9 @@ channel_forward_accept(LIBSSH2_LISTENER *listener)
do {
rc = _libssh2_transport_read(listener->session);
- } while (rc > 0);
+ } while(rc > 0);
- if (_libssh2_list_first(&listener->queue)) {
+ if(_libssh2_list_first(&listener->queue)) {
LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue);
/* detach channel from listener's queue */
@@ -754,7 +763,7 @@ channel_forward_accept(LIBSSH2_LISTENER *listener)
return channel;
}
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for packet");
}
@@ -799,7 +808,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
size_t data_len;
int rc;
- if (channel->setenv_state == libssh2_NB_state_idle) {
+ if(channel->setenv_state == libssh2_NB_state_idle) {
/* 21 = packet_type(1) + channel_id(4) + request_len(4) +
* request(3)"env" + want_reply(1) + varname_len(4) + value_len(4) */
channel->setenv_packet_len = varname_len + value_len + 21;
@@ -815,7 +824,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
s = channel->setenv_packet =
LIBSSH2_ALLOC(session, channel->setenv_packet_len);
- if (!channel->setenv_packet) {
+ if(!channel->setenv_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory "
"for setenv packet");
@@ -831,16 +840,17 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
channel->setenv_state = libssh2_NB_state_created;
}
- if (channel->setenv_state == libssh2_NB_state_created) {
+ if(channel->setenv_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session,
channel->setenv_packet,
channel->setenv_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending setenv request");
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
LIBSSH2_FREE(session, channel->setenv_packet);
channel->setenv_packet = NULL;
channel->setenv_state = libssh2_NB_state_idle;
@@ -856,15 +866,15 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
channel->setenv_state = libssh2_NB_state_sent;
}
- if (channel->setenv_state == libssh2_NB_state_sent) {
+ if(channel->setenv_state == libssh2_NB_state_sent) {
rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1, channel->setenv_local_channel, 4,
&channel->
setenv_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- if (rc) {
+ if(rc) {
channel->setenv_state = libssh2_NB_state_idle;
return rc;
}
@@ -874,7 +884,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
"Unexpected packet size");
}
- if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
+ if(data[0] == SSH_MSG_CHANNEL_SUCCESS) {
LIBSSH2_FREE(session, data);
channel->setenv_state = libssh2_NB_state_idle;
return 0;
@@ -925,7 +935,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
{ SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
int rc;
- if (channel->reqPTY_state == libssh2_NB_state_idle) {
+ if(channel->reqPTY_state == libssh2_NB_state_idle) {
/* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) +
* want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) +
* height_px(4) + modes_len(4) */
@@ -962,15 +972,16 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
channel->reqPTY_state = libssh2_NB_state_created;
}
- if (channel->reqPTY_state == libssh2_NB_state_created) {
+ if(channel->reqPTY_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, channel->reqPTY_packet,
channel->reqPTY_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending pty request");
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
channel->reqPTY_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send pty-request packet");
@@ -980,16 +991,17 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
channel->reqPTY_state = libssh2_NB_state_sent;
}
- if (channel->reqPTY_state == libssh2_NB_state_sent) {
+ if(channel->reqPTY_state == libssh2_NB_state_sent) {
unsigned char *data;
size_t data_len;
unsigned char code;
rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1, channel->reqPTY_local_channel, 4,
&channel->reqPTY_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc || data_len < 1) {
+ }
+ else if(rc || data_len < 1) {
channel->reqPTY_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Failed to require the PTY package");
@@ -1000,12 +1012,13 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
LIBSSH2_FREE(session, data);
channel->reqPTY_state = libssh2_NB_state_idle;
- if (code == SSH_MSG_CHANNEL_SUCCESS)
+ if(code == SSH_MSG_CHANNEL_SUCCESS)
return 0;
}
return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
- "Unable to complete request for channel request-pty");
+ "Unable to complete request for "
+ "channel request-pty");
}
/*
@@ -1039,7 +1052,7 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
int rc;
int retcode = LIBSSH2_ERROR_PROTO;
- if (channel->reqPTY_state == libssh2_NB_state_idle) {
+ if(channel->reqPTY_state == libssh2_NB_state_idle) {
channel->reqPTY_packet_len = 39;
/* Zero the whole thing out */
@@ -1066,15 +1079,16 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
channel->reqPTY_state = libssh2_NB_state_created;
}
- if (channel->reqPTY_state == libssh2_NB_state_created) {
+ if(channel->reqPTY_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, channel->reqPTY_packet,
channel->reqPTY_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending window-change request");
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
channel->reqPTY_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send window-change packet");
@@ -1124,7 +1138,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
int rc;
- if (channel->reqX11_state == libssh2_NB_state_idle) {
+ if(channel->reqX11_state == libssh2_NB_state_idle) {
/* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) +
* want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) +
* screen_num(4) */
@@ -1144,7 +1158,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
s = channel->reqX11_packet =
LIBSSH2_ALLOC(session, channel->reqX11_packet_len);
- if (!channel->reqX11_packet) {
+ if(!channel->reqX11_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for pty-request");
}
@@ -1156,23 +1170,24 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
*(s++) = 0x01; /* want_reply */
*(s++) = single_connection ? 0x01 : 0x00;
- _libssh2_store_str(&s, auth_proto?auth_proto:"MIT-MAGIC-COOKIE-1",
+ _libssh2_store_str(&s, auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
proto_len);
_libssh2_store_u32(&s, cookie_len);
- if (auth_cookie) {
+ if(auth_cookie) {
memcpy(s, auth_cookie, cookie_len);
- } else {
+ }
+ else {
int i;
/* note: the extra +1 below is necessary since the sprintf()
loop will always write 3 bytes so the last one will write
the trailing zero at the LIBSSH2_X11_RANDOM_COOKIE_LEN/2
border */
- unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) +1];
+ unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
_libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
- sprintf((char *)&s[i*2], "%02X", buffer[i]);
+ snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
}
}
s += cookie_len;
@@ -1181,16 +1196,16 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
channel->reqX11_state = libssh2_NB_state_created;
}
- if (channel->reqX11_state == libssh2_NB_state_created) {
+ if(channel->reqX11_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, channel->reqX11_packet,
channel->reqX11_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending X11-req packet");
return rc;
}
- if (rc) {
+ if(rc) {
LIBSSH2_FREE(session, channel->reqX11_packet);
channel->reqX11_packet = NULL;
channel->reqX11_state = libssh2_NB_state_idle;
@@ -1205,7 +1220,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
channel->reqX11_state = libssh2_NB_state_sent;
}
- if (channel->reqX11_state == libssh2_NB_state_sent) {
+ if(channel->reqX11_state == libssh2_NB_state_sent) {
size_t data_len;
unsigned char *data;
unsigned char code;
@@ -1213,9 +1228,10 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1, channel->reqX11_local_channel, 4,
&channel->reqX11_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc || data_len < 1) {
+ }
+ else if(rc || data_len < 1) {
channel->reqX11_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"waiting for x11-req response packet");
@@ -1225,7 +1241,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
LIBSSH2_FREE(session, data);
channel->reqX11_state = libssh2_NB_state_idle;
- if (code == SSH_MSG_CHANNEL_SUCCESS)
+ if(code == SSH_MSG_CHANNEL_SUCCESS)
return 0;
}
@@ -1270,12 +1286,12 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
{ SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
int rc;
- if (channel->process_state == libssh2_NB_state_end) {
+ if(channel->process_state == libssh2_NB_state_end) {
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"Channel can not be reused");
}
- if (channel->process_state == libssh2_NB_state_idle) {
+ if(channel->process_state == libssh2_NB_state_idle) {
/* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
channel->process_packet_len = request_len + 10;
@@ -1283,16 +1299,16 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
memset(&channel->process_packet_requirev_state, 0,
sizeof(channel->process_packet_requirev_state));
- if (message)
+ if(message)
channel->process_packet_len += + 4;
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"starting request(%s) on channel %lu/%lu, message=%s",
request, channel->local.id, channel->remote.id,
- message?message:"<null>");
+ message ? message : "<null>");
s = channel->process_packet =
LIBSSH2_ALLOC(session, channel->process_packet_len);
- if (!channel->process_packet)
+ if(!channel->process_packet)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory "
"for channel-process request");
@@ -1302,23 +1318,23 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
_libssh2_store_str(&s, request, request_len);
*(s++) = 0x01;
- if (message)
+ if(message)
_libssh2_store_u32(&s, message_len);
channel->process_state = libssh2_NB_state_created;
}
- if (channel->process_state == libssh2_NB_state_created) {
+ if(channel->process_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session,
channel->process_packet,
channel->process_packet_len,
(unsigned char *)message, message_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending channel request");
return rc;
}
- else if (rc) {
+ else if(rc) {
LIBSSH2_FREE(session, channel->process_packet);
channel->process_packet = NULL;
channel->process_state = libssh2_NB_state_end;
@@ -1333,16 +1349,17 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
channel->process_state = libssh2_NB_state_sent;
}
- if (channel->process_state == libssh2_NB_state_sent) {
+ if(channel->process_state == libssh2_NB_state_sent) {
unsigned char *data;
size_t data_len;
unsigned char code;
rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1, channel->process_local_channel, 4,
&channel->process_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc || data_len < 1) {
+ }
+ else if(rc || data_len < 1) {
channel->process_state = libssh2_NB_state_end;
return _libssh2_error(session, rc,
"Failed waiting for channel success");
@@ -1352,7 +1369,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
LIBSSH2_FREE(session, data);
channel->process_state = libssh2_NB_state_end;
- if (code == SSH_MSG_CHANNEL_SUCCESS)
+ if(code == SSH_MSG_CHANNEL_SUCCESS)
return 0;
}
@@ -1405,30 +1422,54 @@ libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
int
_libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
{
- if (channel->flush_state == libssh2_NB_state_idle) {
+ if(channel->flush_state == libssh2_NB_state_idle) {
LIBSSH2_PACKET *packet =
_libssh2_list_first(&channel->session->packets);
channel->flush_refund_bytes = 0;
channel->flush_flush_bytes = 0;
- while (packet) {
+ while(packet) {
+ unsigned char packet_type;
LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node);
- unsigned char packet_type = packet->data[0];
- if (((packet_type == SSH_MSG_CHANNEL_DATA)
- || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
- && (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) {
+ if(packet->data_len < 1) {
+ packet = next;
+ _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+ "Unexpected packet length");
+ continue;
+ }
+
+ packet_type = packet->data[0];
+
+ if(((packet_type == SSH_MSG_CHANNEL_DATA)
+ || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
+ && ((packet->data_len >= 5)
+ && (_libssh2_ntohu32(packet->data + 1)
+ == channel->local.id))) {
/* It's our channel at least */
- long packet_stream_id =
- (packet_type == SSH_MSG_CHANNEL_DATA) ? 0 :
- _libssh2_ntohu32(packet->data + 5);
- if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
+ int packet_stream_id;
+
+ if(packet_type == SSH_MSG_CHANNEL_DATA) {
+ packet_stream_id = 0;
+ }
+ else if(packet->data_len >= 9) {
+ packet_stream_id = _libssh2_ntohu32(packet->data + 5);
+ }
+ else {
+ channel->flush_state = libssh2_NB_state_idle;
+ return _libssh2_error(channel->session,
+ LIBSSH2_ERROR_PROTO,
+ "Unexpected packet length");
+ }
+
+ if((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
|| ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
&& ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
|| (streamid == packet_stream_id)))
|| ((packet_type == SSH_MSG_CHANNEL_DATA)
&& (streamid == 0))) {
- int bytes_to_flush = packet->data_len - packet->data_head;
+ size_t bytes_to_flush = packet->data_len -
+ packet->data_head;
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
"Flushing %d bytes of data from stream "
@@ -1456,13 +1497,12 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
channel->read_avail -= channel->flush_flush_bytes;
channel->remote.window_size -= channel->flush_flush_bytes;
- if (channel->flush_refund_bytes) {
- int rc;
-
- rc = _libssh2_channel_receive_window_adjust(channel,
- channel->flush_refund_bytes,
- 1, NULL);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(channel->flush_refund_bytes) {
+ int rc =
+ _libssh2_channel_receive_window_adjust(channel,
+ channel->flush_refund_bytes,
+ 1, NULL);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
}
@@ -1528,41 +1568,42 @@ libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel,
{
size_t namelen = 0;
- if (channel) {
+ if(channel) {
LIBSSH2_SESSION *session = channel->session;
- if (channel->exit_signal) {
+ if(channel->exit_signal) {
namelen = strlen(channel->exit_signal);
- if (exitsignal) {
- *exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
- if (!*exitsignal) {
+ if(exitsignal) {
+ *exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
+ if(!*exitsignal) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for signal name");
}
memcpy(*exitsignal, channel->exit_signal, namelen);
(*exitsignal)[namelen] = '\0';
}
- if (exitsignal_len)
+ if(exitsignal_len)
*exitsignal_len = namelen;
- } else {
- if (exitsignal)
+ }
+ else {
+ if(exitsignal)
*exitsignal = NULL;
- if (exitsignal_len)
+ if(exitsignal_len)
*exitsignal_len = 0;
}
/* TODO: set error message and language tag */
- if (errmsg)
+ if(errmsg)
*errmsg = NULL;
- if (errmsg_len)
+ if(errmsg_len)
*errmsg_len = 0;
- if (langtag)
+ if(langtag)
*langtag = NULL;
- if (langtag_len)
+ if(langtag_len)
*langtag_len = 0;
}
@@ -1589,8 +1630,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
if(store)
*store = channel->remote.window_size;
- if (channel->adjust_state == libssh2_NB_state_idle) {
- if (!force
+ if(channel->adjust_state == libssh2_NB_state_idle) {
+ if(!force
&& (adjustment + channel->adjust_queue <
LIBSSH2_CHANNEL_MINADJUST)) {
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
@@ -1601,7 +1642,7 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
return 0;
}
- if (!adjustment && !channel->adjust_queue) {
+ if(!adjustment && !channel->adjust_queue) {
return 0;
}
@@ -1622,12 +1663,12 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(channel->session, rc,
"Would block sending window adjust");
return rc;
}
- else if (rc) {
+ else if(rc) {
channel->adjust_queue = adjustment;
return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send transfer-window adjustment "
@@ -1672,7 +1713,7 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
/* stupid - but this is how it was made to work before and this is just
kept for backwards compatibility */
- return rc?(unsigned long)rc:window;
+ return rc ? (unsigned long)rc : window;
}
/*
@@ -1706,7 +1747,7 @@ libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel,
int
_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
{
- if (channel->extData2_state == libssh2_NB_state_idle) {
+ if(channel->extData2_state == libssh2_NB_state_idle) {
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
"Setting channel %lu/%lu handle_extended_data"
" mode to %d",
@@ -1716,8 +1757,8 @@ _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
channel->extData2_state = libssh2_NB_state_created;
}
- if (channel->extData2_state == libssh2_NB_state_idle) {
- if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
+ if(channel->extData2_state == libssh2_NB_state_idle) {
+ if(ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
int rc =
_libssh2_channel_flush(channel,
LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
@@ -1784,8 +1825,8 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
{
LIBSSH2_SESSION *session = channel->session;
int rc;
- int bytes_read = 0;
- int bytes_want;
+ size_t bytes_read = 0;
+ size_t bytes_want;
int unlink_packet;
LIBSSH2_PACKET *read_packet;
LIBSSH2_PACKET *read_next;
@@ -1797,11 +1838,13 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
stream_id);
/* expand the receiving window first if it has become too narrow */
- if( (channel->read_state == libssh2_NB_state_jump1) ||
- (channel->remote.window_size < channel->remote.window_size_initial / 4 * 3 + buflen) ) {
+ if((channel->read_state == libssh2_NB_state_jump1) ||
+ (channel->remote.window_size <
+ channel->remote.window_size_initial / 4 * 3 + buflen) ) {
- uint32_t adjustment = channel->remote.window_size_initial + buflen - channel->remote.window_size;
- if (adjustment < LIBSSH2_CHANNEL_MINADJUST)
+ uint32_t adjustment = channel->remote.window_size_initial + buflen -
+ channel->remote.window_size;
+ if(adjustment < LIBSSH2_CHANNEL_MINADJUST)
adjustment = LIBSSH2_CHANNEL_MINADJUST;
/* the actual window adjusting may not finish so we need to deal with
@@ -1809,7 +1852,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
channel->read_state = libssh2_NB_state_jump1;
rc = _libssh2_channel_receive_window_adjust(channel, adjustment,
0, NULL);
- if (rc)
+ if(rc)
return rc;
channel->read_state = libssh2_NB_state_idle;
@@ -1819,13 +1862,13 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
produces faster transfers. */
do {
rc = _libssh2_transport_read(session);
- } while (rc > 0);
+ } while(rc > 0);
- if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
+ if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
return _libssh2_error(session, rc, "transport read");
read_packet = _libssh2_list_first(&session->packets);
- while (read_packet && (bytes_read < (int) buflen)) {
+ while(read_packet && (bytes_read < buflen)) {
/* previously this loop condition also checked for
!channel->remote.close but we cannot let it do this:
@@ -1839,6 +1882,13 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
/* In case packet gets destroyed during this iteration */
read_next = _libssh2_list_next(&readpkt->node);
+ if(readpkt->data_len < 5) {
+ read_packet = read_next;
+ _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+ "Unexpected packet length");
+ continue;
+ }
+
channel->read_local_id =
_libssh2_ntohu32(readpkt->data + 1);
@@ -1849,9 +1899,10 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
* or the standard stream with extended_data_merge
* enabled and data was available
*/
- if ((stream_id
+ if((stream_id
&& (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
&& (channel->local.id == channel->read_local_id)
+ && (readpkt->data_len >= 9)
&& (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5)))
|| (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA)
&& (channel->local.id == channel->read_local_id))
@@ -1865,7 +1916,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
bytes_want = buflen - bytes_read;
unlink_packet = FALSE;
- if (bytes_want >= (int) (readpkt->data_len - readpkt->data_head)) {
+ if(bytes_want >= (readpkt->data_len - readpkt->data_head)) {
/* we want more than this node keeps, so adjust the number and
delete this node after the copy */
bytes_want = readpkt->data_len - readpkt->data_head;
@@ -1887,7 +1938,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
bytes_read += bytes_want;
/* if drained, remove from list */
- if (unlink_packet) {
+ if(unlink_packet) {
/* detach readpkt from session->packets list */
_libssh2_list_remove(&readpkt->node);
@@ -1900,7 +1951,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
read_packet = read_next;
}
- if (!bytes_read) {
+ if(!bytes_read) {
/* If the channel is already at EOF or even closed, we need to signal
that back. We may have gotten that info while draining the incoming
transport layer until EAGAIN so we must not be fooled by that
@@ -1968,13 +2019,24 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
{
LIBSSH2_SESSION *session = channel->session;
LIBSSH2_PACKET *read_packet;
+ LIBSSH2_PACKET *next_packet;
uint32_t read_local_id;
read_packet = _libssh2_list_first(&session->packets);
- if (read_packet == NULL)
+ if(read_packet == NULL)
return 0;
- while (read_packet) {
+ while(read_packet) {
+
+ next_packet = _libssh2_list_next(&read_packet->node);
+
+ if(read_packet->data_len < 5) {
+ read_packet = next_packet;
+ _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+ "Unexpected packet length");
+ continue;
+ }
+
read_local_id = _libssh2_ntohu32(read_packet->data + 1);
/*
@@ -1984,9 +2046,10 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
* or the standard stream with extended_data_merge
* enabled and data was available
*/
- if ((stream_id
+ if((stream_id
&& (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
&& (channel->local.id == read_local_id)
+ && (read_packet->data_len >= 9)
&& (stream_id == (int) _libssh2_ntohu32(read_packet->data + 5)))
||
(!stream_id
@@ -1997,11 +2060,11 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
&& (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
&& (channel->local.id == read_local_id)
&& (channel->remote.extended_data_ignore_mode
- == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE)))
- {
+ == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
return (read_packet->data_len - read_packet->data_head);
}
- read_packet = _libssh2_list_next(&read_packet->node);
+
+ read_packet = next_packet;
}
return 0;
@@ -2035,7 +2098,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
if(buflen > 32700)
buflen = 32700;
- if (channel->write_state == libssh2_NB_state_idle) {
+ if(channel->write_state == libssh2_NB_state_idle) {
unsigned char *s = channel->write_packet;
_libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
@@ -2043,11 +2106,11 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
(int) buflen, channel->local.id, channel->remote.id,
stream_id);
- if (channel->local.close)
+ if(channel->local.close)
return _libssh2_error(channel->session,
LIBSSH2_ERROR_CHANNEL_CLOSED,
"We've already closed this channel");
- else if (channel->local.eof)
+ else if(channel->local.eof)
return _libssh2_error(channel->session,
LIBSSH2_ERROR_CHANNEL_EOF_SENT,
"EOF has already been received, "
@@ -2057,7 +2120,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
* pending window adjust packets */
do
rc = _libssh2_transport_read(session);
- while (rc > 0);
+ while(rc > 0);
if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
return _libssh2_error(channel->session, rc,
@@ -2073,7 +2136,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
*/
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND;
- return (rc==LIBSSH2_ERROR_EAGAIN?rc:0);
+ return (rc == LIBSSH2_ERROR_EAGAIN?rc:0);
}
channel->write_bufwrite = buflen;
@@ -2081,12 +2144,12 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
*(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
SSH_MSG_CHANNEL_DATA;
_libssh2_store_u32(&s, channel->remote.id);
- if (stream_id)
+ if(stream_id)
_libssh2_store_u32(&s, stream_id);
/* Don't exceed the remote end's limits */
/* REMEMBER local means local as the SOURCE of the data */
- if (channel->write_bufwrite > channel->local.window_size) {
+ 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",
@@ -2094,7 +2157,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
channel->remote.id, stream_id);
channel->write_bufwrite = channel->local.window_size;
}
- if (channel->write_bufwrite > channel->local.packet_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",
@@ -2115,15 +2178,15 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
channel->write_state = libssh2_NB_state_created;
}
- if (channel->write_state == libssh2_NB_state_created) {
+ if(channel->write_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, channel->write_packet,
channel->write_packet_len,
buf, channel->write_bufwrite);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, rc,
"Unable to send channel data");
}
- else if (rc) {
+ else if(rc) {
channel->write_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send channel data");
@@ -2182,17 +2245,18 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel)
unsigned char packet[5]; /* packet_type(1) + channelno(4) */
int rc;
- _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Sending EOF on channel %lu/%lu",
+ _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+ "Sending EOF on channel %lu/%lu",
channel->local.id, channel->remote.id);
packet[0] = SSH_MSG_CHANNEL_EOF;
_libssh2_htonu32(packet + 1, channel->remote.id);
rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending EOF");
return rc;
}
- else if (rc) {
+ else if(rc) {
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send EOF on channel");
}
@@ -2228,6 +2292,7 @@ libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
{
LIBSSH2_SESSION *session;
LIBSSH2_PACKET *packet;
+ LIBSSH2_PACKET *next_packet;
if(!channel)
return LIBSSH2_ERROR_BAD_USE;
@@ -2235,14 +2300,25 @@ libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
session = channel->session;
packet = _libssh2_list_first(&session->packets);
- while (packet) {
- if (((packet->data[0] == SSH_MSG_CHANNEL_DATA)
- || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA))
- && (channel->local.id == _libssh2_ntohu32(packet->data + 1))) {
+ while(packet) {
+
+ next_packet = _libssh2_list_next(&packet->node);
+
+ if(packet->data_len < 1) {
+ packet = next_packet;
+ _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+ "Unexpected packet length");
+ continue;
+ }
+
+ if(((packet->data[0] == SSH_MSG_CHANNEL_DATA)
+ || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA))
+ && ((packet->data_len >= 5)
+ && (channel->local.id == _libssh2_ntohu32(packet->data + 1)))) {
/* There's data waiting to be read yet, mask the EOF status */
return 0;
}
- packet = _libssh2_list_next(&packet->node);
+ packet = next_packet;
}
return channel->remote.eof;
@@ -2258,9 +2334,9 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
LIBSSH2_SESSION *session = channel->session;
int rc;
- if (channel->wait_eof_state == libssh2_NB_state_idle) {
+ if(channel->wait_eof_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
- "Awaiting close of channel %lu/%lu", channel->local.id,
+ "Awaiting EOF for channel %lu/%lu", channel->local.id,
channel->remote.id);
channel->wait_eof_state = libssh2_NB_state_created;
@@ -2271,19 +2347,26 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
* Either the EOF will be set or network timeout will occur.
*/
do {
- if (channel->remote.eof) {
+ if(channel->remote.eof) {
break;
}
+
+ if((channel->remote.window_size == channel->read_avail) &&
+ session->api_block_mode)
+ return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_FULL,
+ "Receiving channel window "
+ "has been exhausted");
+
rc = _libssh2_transport_read(session);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc < 0) {
+ else if(rc < 0) {
channel->wait_eof_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"_libssh2_transport_read() bailed out!");
}
- } while (1);
+ } while(1);
channel->wait_eof_state = libssh2_NB_state_idle;
@@ -2312,16 +2395,17 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
LIBSSH2_SESSION *session = channel->session;
int rc = 0;
- if (channel->local.close) {
+ if(channel->local.close) {
/* Already closed, act like we sent another close,
* even though we didn't... shhhhhh */
channel->close_state = libssh2_NB_state_idle;
return 0;
}
- if (!channel->local.eof) {
- if ((rc = channel_send_eof(channel))) {
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(!channel->local.eof) {
+ rc = channel_send_eof(channel);
+ if(rc) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
_libssh2_error(session, rc,
@@ -2332,7 +2416,7 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
/* ignore if we have received a remote eof or not, as it is now too
late for us to wait for it. Continue closing! */
- if (channel->close_state == libssh2_NB_state_idle) {
+ if(channel->close_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu",
channel->local.id, channel->remote.id);
@@ -2342,41 +2426,43 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
channel->close_state = libssh2_NB_state_created;
}
- if (channel->close_state == libssh2_NB_state_created) {
+ if(channel->close_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, channel->close_packet, 5,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending close-channel");
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
_libssh2_error(session, rc,
"Unable to send close-channel request, "
"but closing anyway");
/* skip waiting for the response and fall through to
LIBSSH2_CHANNEL_CLOSE below */
- } else
+ }
+ else
channel->close_state = libssh2_NB_state_sent;
}
- if (channel->close_state == libssh2_NB_state_sent) {
+ if(channel->close_state == libssh2_NB_state_sent) {
/* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
- while (!channel->remote.close && !rc &&
+ while(!channel->remote.close && !rc &&
(session->socket_state != LIBSSH2_SOCKET_DISCONNECTED))
rc = _libssh2_transport_read(session);
}
if(rc != LIBSSH2_ERROR_EAGAIN) {
- /* set the local close state first when we're perfectly confirmed to not
- do any more EAGAINs */
+ /* set the local close state first when we're perfectly confirmed to
+ not do any more EAGAINs */
channel->local.close = 1;
/* We call the callback last in this function to make it keep the local
data as long as EAGAIN is returned. */
- if (channel->close_cb) {
+ if(channel->close_cb) {
LIBSSH2_CHANNEL_CLOSE(session, channel);
}
@@ -2384,7 +2470,7 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
}
/* return 0 or an error */
- return rc>=0?0:rc;
+ return rc >= 0 ? 0 : rc;
}
/*
@@ -2414,13 +2500,13 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
LIBSSH2_SESSION *session = channel->session;
int rc;
- if (!libssh2_channel_eof(channel)) {
+ if(!channel->remote.eof) {
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"libssh2_channel_wait_closed() invoked when "
"channel is not in EOF state");
}
- if (channel->wait_closed_state == libssh2_NB_state_idle) {
+ if(channel->wait_closed_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Awaiting close of channel %lu/%lu", channel->local.id,
channel->remote.id);
@@ -2432,13 +2518,13 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
* While channel is not closed, read more packets from the network.
* Either the channel will be closed or network timeout will occur.
*/
- if (!channel->remote.close) {
+ if(!channel->remote.close) {
do {
rc = _libssh2_transport_read(session);
- if (channel->remote.close)
+ if(channel->remote.close)
/* it is now closed, move on! */
break;
- } while (rc > 0);
+ } while(rc > 0);
if(rc < 0)
return rc;
}
@@ -2483,7 +2569,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
assert(session);
- if (channel->free_state == libssh2_NB_state_idle) {
+ if(channel->free_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Freeing channel %lu/%lu resources", channel->local.id,
channel->remote.id);
@@ -2492,7 +2578,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
}
/* Allow channel freeing even when the socket has lost its connection */
- if (!channel->local.close
+ if(!channel->local.close
&& (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
rc = _libssh2_channel_close(channel);
@@ -2505,7 +2591,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
channel->free_state = libssh2_NB_state_idle;
- if (channel->exit_signal) {
+ if(channel->exit_signal) {
LIBSSH2_FREE(session, channel->exit_signal);
}
@@ -2517,7 +2603,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
/* Clear out packets meant for this channel */
_libssh2_htonu32(channel_id, channel->local.id);
- while ((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data,
+ while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data,
&data_len, 1, channel_id, 4) >= 0)
||
(_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data,
@@ -2526,7 +2612,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
}
/* free "channel_type" */
- if (channel->channel_type) {
+ if(channel->channel_type) {
LIBSSH2_FREE(session, channel->channel_type);
}
@@ -2536,13 +2622,13 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
/*
* Make sure all memory used in the state variables are free
*/
- if (channel->setenv_packet) {
+ if(channel->setenv_packet) {
LIBSSH2_FREE(session, channel->setenv_packet);
}
- if (channel->reqX11_packet) {
+ if(channel->reqX11_packet) {
LIBSSH2_FREE(session, channel->reqX11_packet);
}
- if (channel->process_packet) {
+ if(channel->process_packet) {
LIBSSH2_FREE(session, channel->process_packet);
}
@@ -2587,25 +2673,38 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel,
if(!channel)
return 0; /* no channel, no window! */
- if (window_size_initial) {
+ if(window_size_initial) {
*window_size_initial = channel->remote.window_size_initial;
}
- if (read_avail) {
+ if(read_avail) {
size_t bytes_queued = 0;
+ LIBSSH2_PACKET *next_packet;
LIBSSH2_PACKET *packet =
_libssh2_list_first(&channel->session->packets);
- while (packet) {
- unsigned char packet_type = packet->data[0];
+ while(packet) {
+ unsigned char packet_type;
+ next_packet = _libssh2_list_next(&packet->node);
+
+ if(packet->data_len < 1) {
+ packet = next_packet;
+ _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
+ "Unexpected packet length");
+ continue;
+ }
+
+ packet_type = packet->data[0];
- if (((packet_type == SSH_MSG_CHANNEL_DATA)
- || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
- && (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) {
+ if(((packet_type == SSH_MSG_CHANNEL_DATA)
+ || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
+ && ((packet->data_len >= 5)
+ && (_libssh2_ntohu32(packet->data + 1) ==
+ channel->local.id))) {
bytes_queued += packet->data_len - packet->data_head;
}
- packet = _libssh2_list_next(&packet->node);
+ packet = next_packet;
}
*read_avail = bytes_queued;
@@ -2629,7 +2728,7 @@ libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel,
if(!channel)
return 0; /* no channel, no window! */
- if (window_size_initial) {
+ if(window_size_initial) {
/* For locally initiated channels this is very often 0, so it's not
* *that* useful as information goes */
*window_size_initial = channel->local.window_size_initial;
diff --git a/libs/libssh2/src/comp.c b/libs/libssh2/src/comp.c
index 6293195907..fec82a74ba 100644
--- a/libs/libssh2/src/comp.c
+++ b/libs/libssh2/src/comp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
+/* Copyright (c) 2004-2007, 2019, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2010-2014, Daniel Stenberg <daniel@haxx.se>
* All rights reserved.
*
@@ -142,7 +142,7 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compr,
int status;
strm = LIBSSH2_CALLOC(session, sizeof(z_stream));
- if (!strm) {
+ if(!strm) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"zlib compression/decompression");
@@ -151,15 +151,16 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compr,
strm->opaque = (voidpf) session;
strm->zalloc = (alloc_func) comp_method_zlib_alloc;
strm->zfree = (free_func) comp_method_zlib_free;
- if (compr) {
+ if(compr) {
/* deflate */
status = deflateInit(strm, Z_DEFAULT_COMPRESSION);
- } else {
+ }
+ else {
/* inflate */
status = inflateInit(strm);
}
- if (status != Z_OK) {
+ if(status != Z_OK) {
LIBSSH2_FREE(session, strm);
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
@@ -197,13 +198,14 @@ comp_method_zlib_comp(LIBSSH2_SESSION *session,
status = deflate(strm, Z_PARTIAL_FLUSH);
- if ((status == Z_OK) && (strm->avail_out > 0)) {
+ if((status == Z_OK) && (strm->avail_out > 0)) {
*dest_len = out_maxlen - strm->avail_out;
return 0;
}
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
- "unhandled zlib compression error %d, avail_out", status, strm->avail_out);
+ "unhandled zlib compression error %d, avail_out",
+ status, strm->avail_out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compression failure");
}
@@ -225,22 +227,22 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session,
reallocs */
char *out;
size_t out_maxlen = src_len;
-
- if (src_len <= SIZE_MAX / 4)
+
+ if(src_len <= SIZE_MAX / 4)
out_maxlen = src_len * 4;
else
out_maxlen = payload_limit;
/* If strm is null, then we have not yet been initialized. */
- if (strm == NULL)
+ if(strm == NULL)
return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS,
"decompression uninitialized");;
/* In practice they never come smaller than this */
- if (out_maxlen < 25)
+ if(out_maxlen < 25)
out_maxlen = 25;
- if (out_maxlen > (int) payload_limit)
+ if(out_maxlen > payload_limit)
out_maxlen = payload_limit;
strm->next_in = (unsigned char *) src;
@@ -248,26 +250,29 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session,
strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);
out = (char *) strm->next_out;
strm->avail_out = out_maxlen;
- if (!strm->next_out)
+ if(!strm->next_out)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate decompression buffer");
/* Loop until it's all inflated or hit error */
- for (;;) {
+ for(;;) {
int status;
size_t out_ofs;
char *newout;
status = inflate(strm, Z_PARTIAL_FLUSH);
- if (status == Z_OK) {
- if (strm->avail_out > 0)
- /* status is OK and the output buffer has not been exhausted so we're done */
+ if(status == Z_OK) {
+ if(strm->avail_out > 0)
+ /* status is OK and the output buffer has not been exhausted
+ so we're done */
break;
- } else if (status == Z_BUF_ERROR) {
+ }
+ else if(status == Z_BUF_ERROR) {
/* the input data has been exhausted so we are done */
break;
- } else {
+ }
+ else {
/* error state */
LIBSSH2_FREE(session, out);
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
@@ -276,7 +281,7 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session,
"decompression failure");
}
- if (out_maxlen > (int) payload_limit || out_maxlen > SIZE_MAX / 2) {
+ if(out_maxlen > payload_limit || out_maxlen > SIZE_MAX / 2) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression phase");
@@ -286,7 +291,7 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session,
out_ofs = out_maxlen - strm->avail_out;
out_maxlen *= 2;
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
- if (!newout) {
+ if(!newout) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand decompression buffer");
@@ -311,8 +316,8 @@ comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract)
{
z_stream *strm = *abstract;
- if (strm) {
- if (compr)
+ if(strm) {
+ if(compr)
deflateEnd(strm);
else
inflateEnd(strm);
diff --git a/libs/libssh2/src/crypt.c b/libs/libssh2/src/crypt.c
index 931ae8b805..8d493b4847 100644
--- a/libs/libssh2/src/crypt.c
+++ b/libs/libssh2/src/crypt.c
@@ -53,10 +53,11 @@ crypt_none_crypt(LIBSSH2_SESSION * session, unsigned char *buf,
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = {
"none",
- 8, /* blocksize (SSH2 defines minimum blocksize as 8) */
- 0, /* iv_len */
- 0, /* secret_len */
- 0, /* flags */
+ "DEK-Info: NONE",
+ 8, /* blocksize (SSH2 defines minimum blocksize as 8) */
+ 0, /* iv_len */
+ 0, /* secret_len */
+ 0, /* flags */
NULL,
crypt_none_crypt,
NULL
@@ -79,12 +80,12 @@ crypt_init(LIBSSH2_SESSION * session,
{
struct crypt_ctx *ctx = LIBSSH2_ALLOC(session,
sizeof(struct crypt_ctx));
- if (!ctx)
+ if(!ctx)
return LIBSSH2_ERROR_ALLOC;
ctx->encrypt = encrypt;
ctx->algo = method->algo;
- if (_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) {
+ if(_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) {
LIBSSH2_FREE(session, ctx);
return -1;
}
@@ -108,7 +109,7 @@ static int
crypt_dtor(LIBSSH2_SESSION * session, void **abstract)
{
struct crypt_ctx **cctx = (struct crypt_ctx **) abstract;
- if (cctx && *cctx) {
+ if(cctx && *cctx) {
_libssh2_cipher_dtor(&(*cctx)->h);
LIBSSH2_FREE(session, *cctx);
*abstract = NULL;
@@ -119,6 +120,7 @@ crypt_dtor(LIBSSH2_SESSION * session, void **abstract)
#if LIBSSH2_AES_CTR
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = {
"aes128-ctr",
+ "",
16, /* blocksize */
16, /* initial value length */
16, /* secret length -- 16*8 == 128bit */
@@ -131,6 +133,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = {
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = {
"aes192-ctr",
+ "",
16, /* blocksize */
16, /* initial value length */
24, /* secret length -- 24*8 == 192bit */
@@ -143,6 +146,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = {
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = {
"aes256-ctr",
+ "",
16, /* blocksize */
16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
@@ -157,6 +161,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = {
#if LIBSSH2_AES
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
"aes128-cbc",
+ "DEK-Info: AES-128-CBC",
16, /* blocksize */
16, /* initial value length */
16, /* secret length -- 16*8 == 128bit */
@@ -169,6 +174,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = {
"aes192-cbc",
+ "DEK-Info: AES-192-CBC",
16, /* blocksize */
16, /* initial value length */
24, /* secret length -- 24*8 == 192bit */
@@ -181,6 +187,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = {
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = {
"aes256-cbc",
+ "DEK-Info: AES-256-CBC",
16, /* blocksize */
16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
@@ -195,6 +202,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = {
static const LIBSSH2_CRYPT_METHOD
libssh2_crypt_method_rijndael_cbc_lysator_liu_se = {
"rijndael-cbc@lysator.liu.se",
+ "DEK-Info: AES-256-CBC",
16, /* blocksize */
16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
@@ -209,6 +217,7 @@ static const LIBSSH2_CRYPT_METHOD
#if LIBSSH2_BLOWFISH
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = {
"blowfish-cbc",
+ "",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
@@ -223,6 +232,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = {
#if LIBSSH2_RC4
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = {
"arcfour",
+ "DEK-Info: RC4",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
@@ -242,13 +252,13 @@ crypt_init_arcfour128(LIBSSH2_SESSION * session,
{
int rc;
- rc = crypt_init (session, method, iv, free_iv, secret, free_secret,
- encrypt, abstract);
- if (rc == 0) {
+ rc = crypt_init(session, method, iv, free_iv, secret, free_secret,
+ encrypt, abstract);
+ if(rc == 0) {
struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
unsigned char block[8];
size_t discard = 1536;
- for (; discard; discard -= 8)
+ for(; discard; discard -= 8)
_libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block,
method->blocksize);
}
@@ -258,6 +268,7 @@ crypt_init_arcfour128(LIBSSH2_SESSION * session,
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = {
"arcfour128",
+ "",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
@@ -272,6 +283,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = {
#if LIBSSH2_CAST
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = {
"cast128-cbc",
+ "",
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
@@ -286,6 +298,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = {
#if LIBSSH2_3DES
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = {
"3des-cbc",
+ "DEK-Info: DES-EDE3-CBC",
8, /* blocksize */
8, /* initial value length */
24, /* secret length */
diff --git a/libs/libssh2/src/crypto.h b/libs/libssh2/src/crypto.h
index aa997a3071..8b1e004028 100644
--- a/libs/libssh2/src/crypto.h
+++ b/libs/libssh2/src/crypto.h
@@ -1,6 +1,6 @@
/* Copyright (C) 2009, 2010 Simon Josefsson
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
- * Copyright (C) 2010 Daniel Stenberg
+ * Copyright (C) 2010-2019 Daniel Stenberg
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@@ -58,6 +58,11 @@
#include "mbedtls.h"
#endif
+#define LIBSSH2_ED25519_KEY_LEN 32
+#define LIBSSH2_ED25519_PRIVATE_KEY_LEN 64
+#define LIBSSH2_ED25519_SIG_LEN 64
+
+#if LIBSSH2_RSA
int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
unsigned long elen,
@@ -90,8 +95,10 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
size_t *signature_len);
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);
+#endif
#if LIBSSH2_DSA
int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
@@ -116,10 +123,102 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
unsigned long hash_len, unsigned char *sig);
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);
#endif
+#if LIBSSH2_ECDSA
+int
+_libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ecdsactx,
+ const unsigned char *k,
+ size_t k_len,
+ libssh2_curve_type type);
+int
+_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filename,
+ unsigned const char *passphrase);
+
+int
+_libssh2_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_ecdsa_create_key(LIBSSH2_SESSION *session,
+ _libssh2_ec_key **out_private_key,
+ unsigned char **out_public_key_octal,
+ size_t *out_public_key_octal_len,
+ libssh2_curve_type curve_type);
+
+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);
+
+int
+_libssh2_ecdsa_sign(LIBSSH2_SESSION *session, libssh2_ecdsa_ctx *ec_ctx,
+ const unsigned char *hash, unsigned long hash_len,
+ unsigned char **signature, size_t *signature_len);
+
+int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filedata,
+ size_t filedata_len,
+ unsigned const char *passphrase);
+
+libssh2_curve_type
+_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key);
+
+int
+_libssh2_ecdsa_curve_type_from_name(const char *name,
+ libssh2_curve_type *out_type);
+
+#endif /* LIBSSH2_ECDSA */
+
+#if LIBSSH2_ED25519
+
+int
+_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_ed25519_ctx **ctx,
+ uint8_t **out_public_key, uint8_t **out_private_key);
+
+int
+_libssh2_curve25519_gen_k(_libssh2_bn **k,
+ uint8_t private_key[LIBSSH2_ED25519_KEY_LEN],
+ uint8_t server_public_key[LIBSSH2_ED25519_KEY_LEN]);
+
+int
+_libssh2_ed25519_verify(libssh2_ed25519_ctx *ctx, const uint8_t *s,
+ size_t s_len, const uint8_t *m, size_t m_len);
+
+int
+_libssh2_ed25519_new_private(libssh2_ed25519_ctx **ed_ctx,
+ LIBSSH2_SESSION *session,
+ const char *filename, const uint8_t *passphrase);
+
+int
+_libssh2_ed25519_new_public(libssh2_ed25519_ctx **ed_ctx,
+ LIBSSH2_SESSION *session,
+ const unsigned char *raw_pub_key,
+ const uint8_t key_len);
+
+int
+_libssh2_ed25519_sign(libssh2_ed25519_ctx *ctx, LIBSSH2_SESSION *session,
+ uint8_t **out_sig, size_t *out_sig_len,
+ const uint8_t *message, size_t message_len);
+
+int
+_libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx **ed_ctx,
+ LIBSSH2_SESSION *session,
+ const char *filedata,
+ size_t filedata_len,
+ unsigned const char *passphrase);
+
+#endif /* LIBSSH2_ED25519 */
+
+
int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo),
unsigned char *iv,
@@ -136,6 +235,7 @@ int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
size_t *pubkeydata_len,
const char *privatekey,
const char *passphrase);
+
int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
unsigned char **method,
size_t *method_len,
@@ -145,6 +245,4 @@ int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
size_t privatekeydata_len,
const char *passphrase);
-void _libssh2_init_aes_ctr(void);
-
#endif
diff --git a/libs/libssh2/src/global.c b/libs/libssh2/src/global.c
index dc45e70036..f88eb33da3 100644
--- a/libs/libssh2/src/global.c
+++ b/libs/libssh2/src/global.c
@@ -44,9 +44,8 @@ static int _libssh2_init_flags = 0;
LIBSSH2_API int
libssh2_init(int flags)
{
- if (_libssh2_initialized == 0 && !(flags & LIBSSH2_INIT_NO_CRYPTO)) {
+ if(_libssh2_initialized == 0 && !(flags & LIBSSH2_INIT_NO_CRYPTO)) {
libssh2_crypto_init();
- _libssh2_init_aes_ctr();
}
_libssh2_initialized++;
@@ -58,12 +57,12 @@ libssh2_init(int flags)
LIBSSH2_API void
libssh2_exit(void)
{
- if (_libssh2_initialized == 0)
+ if(_libssh2_initialized == 0)
return;
_libssh2_initialized--;
- if (!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) {
+ if(!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) {
libssh2_crypto_exit();
}
@@ -73,6 +72,6 @@ libssh2_exit(void)
void
_libssh2_init_if_needed(void)
{
- if (_libssh2_initialized == 0)
+ if(_libssh2_initialized == 0)
(void)libssh2_init (0);
}
diff --git a/libs/libssh2/src/hostkey.c b/libs/libssh2/src/hostkey.c
index 2a0a8f943b..a8bd42b7a0 100644
--- a/libs/libssh2/src/hostkey.c
+++ b/libs/libssh2/src/hostkey.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
- * Copyright (c) 2009-2014 by Daniel Stenberg
+ * Copyright (c) 2009-2019 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -64,38 +64,36 @@ hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session,
void **abstract)
{
libssh2_rsa_ctx *rsactx;
- const unsigned char *s, *e, *n;
- unsigned long len, e_len, n_len;
- int ret;
-
- (void) hostkey_data_len;
+ unsigned char *e, *n;
+ size_t e_len, n_len;
+ struct string_buf buf;
- if (*abstract) {
+ if(*abstract) {
hostkey_method_ssh_rsa_dtor(session, abstract);
*abstract = NULL;
}
- s = hostkey_data;
- len = _libssh2_ntohu32(s);
- s += 4;
-
- if (len != 7 || strncmp((char *) s, "ssh-rsa", 7) != 0) {
+ if(hostkey_data_len < 19) {
+ _libssh2_debug(session, LIBSSH2_TRACE_ERROR,
+ "host key length too short");
return -1;
}
- s += 7;
- e_len = _libssh2_ntohu32(s);
- s += 4;
+ buf.data = (unsigned char *)hostkey_data;
+ buf.dataptr = buf.data;
+ buf.len = hostkey_data_len;
- e = s;
- s += e_len;
- n_len = _libssh2_ntohu32(s);
- s += 4;
- n = s;
+ if(_libssh2_match_string(&buf, "ssh-rsa"))
+ return -1;
+
+ if(_libssh2_get_string(&buf, &e, &e_len))
+ return -1;
+
+ if(_libssh2_get_string(&buf, &n, &n_len))
+ return -1;
- ret = _libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0,
- NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0);
- if (ret) {
+ if(_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0,
+ NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0)) {
return -1;
}
@@ -118,13 +116,13 @@ hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
libssh2_rsa_ctx *rsactx;
int ret;
- if (*abstract) {
+ if(*abstract) {
hostkey_method_ssh_rsa_dtor(session, abstract);
*abstract = NULL;
}
ret = _libssh2_rsa_new_private(&rsactx, session, privkeyfile, passphrase);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -148,7 +146,7 @@ hostkey_method_ssh_rsa_initPEMFromMemory(LIBSSH2_SESSION * session,
libssh2_rsa_ctx *rsactx;
int ret;
- if (*abstract) {
+ if(*abstract) {
hostkey_method_ssh_rsa_dtor(session, abstract);
*abstract = NULL;
}
@@ -156,7 +154,7 @@ hostkey_method_ssh_rsa_initPEMFromMemory(LIBSSH2_SESSION * session,
ret = _libssh2_rsa_new_private_frommemory(&rsactx, session,
privkeyfiledata,
privkeyfiledata_len, passphrase);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -181,6 +179,9 @@ hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session,
(void) session;
/* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */
+ if(sig_len < 15)
+ return -1;
+
sig += 15;
sig_len -= 15;
return _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len);
@@ -218,7 +219,7 @@ hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session,
ret = _libssh2_rsa_sha1_sign(session, rsactx, hash, SHA_DIGEST_LENGTH,
signature, signature_len);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -281,45 +282,42 @@ hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session,
void **abstract)
{
libssh2_dsa_ctx *dsactx;
- const unsigned char *p, *q, *g, *y, *s;
- unsigned long p_len, q_len, g_len, y_len, len;
- int ret;
-
- (void) hostkey_data_len;
+ unsigned char *p, *q, *g, *y;
+ size_t p_len, q_len, g_len, y_len;
+ struct string_buf buf;
- if (*abstract) {
+ if(*abstract) {
hostkey_method_ssh_dss_dtor(session, abstract);
*abstract = NULL;
}
- s = hostkey_data;
- len = _libssh2_ntohu32(s);
- s += 4;
- if (len != 7 || strncmp((char *) s, "ssh-dss", 7) != 0) {
+ if(hostkey_data_len < 27) {
+ _libssh2_debug(session, LIBSSH2_TRACE_ERROR,
+ "host key length too short");
return -1;
}
- s += 7;
- p_len = _libssh2_ntohu32(s);
- s += 4;
- p = s;
- s += p_len;
- q_len = _libssh2_ntohu32(s);
- s += 4;
- q = s;
- s += q_len;
- g_len = _libssh2_ntohu32(s);
- s += 4;
- g = s;
- s += g_len;
- y_len = _libssh2_ntohu32(s);
- s += 4;
- y = s;
- /* s += y_len; */
+ buf.data = (unsigned char *)hostkey_data;
+ buf.dataptr = buf.data;
+ buf.len = hostkey_data_len;
+
+ if(_libssh2_match_string(&buf, "ssh-dss"))
+ return -1;
+
+ if(_libssh2_get_string(&buf, &p, &p_len))
+ return -1;
+
+ if(_libssh2_get_string(&buf, &q, &q_len))
+ return -1;
+
+ if(_libssh2_get_string(&buf, &g, &g_len))
+ return -1;
+
+ if(_libssh2_get_string(&buf, &y, &y_len))
+ return -1;
- ret = _libssh2_dsa_new(&dsactx, p, p_len, q, q_len,
- g, g_len, y, y_len, NULL, 0);
- if (ret) {
+ if(_libssh2_dsa_new(&dsactx, p, p_len, q, q_len,
+ g, g_len, y, y_len, NULL, 0)) {
return -1;
}
@@ -342,13 +340,13 @@ hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
libssh2_dsa_ctx *dsactx;
int ret;
- if (*abstract) {
+ if(*abstract) {
hostkey_method_ssh_dss_dtor(session, abstract);
*abstract = NULL;
}
ret = _libssh2_dsa_new_private(&dsactx, session, privkeyfile, passphrase);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -372,7 +370,7 @@ hostkey_method_ssh_dss_initPEMFromMemory(LIBSSH2_SESSION * session,
libssh2_dsa_ctx *dsactx;
int ret;
- if (*abstract) {
+ if(*abstract) {
hostkey_method_ssh_dss_dtor(session, abstract);
*abstract = NULL;
}
@@ -380,7 +378,7 @@ hostkey_method_ssh_dss_initPEMFromMemory(LIBSSH2_SESSION * session,
ret = _libssh2_dsa_new_private_frommemory(&dsactx, session,
privkeyfiledata,
privkeyfiledata_len, passphrase);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -404,12 +402,14 @@ hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session,
libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
/* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */
- sig += 15;
- sig_len -= 15;
- if (sig_len != 40) {
+ if(sig_len != 55) {
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Invalid DSS signature length");
}
+
+ sig += 15;
+ sig_len -= 15;
+
return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len);
}
@@ -432,7 +432,7 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session,
int i;
*signature = LIBSSH2_CALLOC(session, 2 * SHA_DIGEST_LENGTH);
- if (!*signature) {
+ if(!*signature) {
return -1;
}
@@ -444,7 +444,7 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session,
}
libssh2_sha1_final(ctx, hash);
- if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) {
+ if(_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) {
LIBSSH2_FREE(session, *signature);
return -1;
}
@@ -483,7 +483,526 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_dss = {
};
#endif /* LIBSSH2_DSA */
+#if LIBSSH2_ECDSA
+
+/* ***********
+ * ecdsa-sha2-nistp256/384/521 *
+ *********** */
+
+static int
+hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session,
+ void **abstract);
+
+/*
+ * hostkey_method_ssh_ecdsa_init
+ *
+ * Initialize the server hostkey working area with e/n pair
+ */
+static int
+hostkey_method_ssh_ecdsa_init(LIBSSH2_SESSION * session,
+ const unsigned char *hostkey_data,
+ size_t hostkey_data_len,
+ void **abstract)
+{
+ libssh2_ecdsa_ctx *ecdsactx = NULL;
+ unsigned char *type_str, *domain, *public_key;
+ size_t key_len, len;
+ libssh2_curve_type type;
+ struct string_buf buf;
+
+ if(abstract != NULL && *abstract) {
+ hostkey_method_ssh_ecdsa_dtor(session, abstract);
+ *abstract = NULL;
+ }
+
+ if(hostkey_data_len < 39) {
+ _libssh2_debug(session, LIBSSH2_TRACE_ERROR,
+ "host key length too short");
+ return -1;
+ }
+
+ buf.data = (unsigned char *)hostkey_data;
+ buf.dataptr = buf.data;
+ buf.len = hostkey_data_len;
+
+ if(_libssh2_get_string(&buf, &type_str, &len) || len != 19)
+ return -1;
+
+ if(strncmp((char *) type_str, "ecdsa-sha2-nistp256", 19) == 0) {
+ type = LIBSSH2_EC_CURVE_NISTP256;
+ }
+ else if(strncmp((char *) type_str, "ecdsa-sha2-nistp384", 19) == 0) {
+ type = LIBSSH2_EC_CURVE_NISTP384;
+ }
+ else if(strncmp((char *) type_str, "ecdsa-sha2-nistp521", 19) == 0) {
+ type = LIBSSH2_EC_CURVE_NISTP521;
+ }
+ else {
+ return -1;
+ }
+
+ if(_libssh2_get_string(&buf, &domain, &len) || len != 8)
+ return -1;
+
+ if(type == LIBSSH2_EC_CURVE_NISTP256 &&
+ strncmp((char *)domain, "nistp256", 8) != 0) {
+ return -1;
+ }
+ else if(type == LIBSSH2_EC_CURVE_NISTP384 &&
+ strncmp((char *)domain, "nistp384", 8) != 0) {
+ return -1;
+ }
+ else if(type == LIBSSH2_EC_CURVE_NISTP521 &&
+ strncmp((char *)domain, "nistp521", 8) != 0) {
+ return -1;
+ }
+
+ /* public key */
+ if(_libssh2_get_string(&buf, &public_key, &key_len))
+ return -1;
+
+ if(_libssh2_ecdsa_curve_name_with_octal_new(&ecdsactx, public_key,
+ key_len, type))
+ return -1;
+
+ if(abstract != NULL)
+ *abstract = ecdsactx;
+
+ return 0;
+}
+
+/*
+ * hostkey_method_ssh_ecdsa_initPEM
+ *
+ * Load a Private Key from a PEM file
+ */
+static int
+hostkey_method_ssh_ecdsa_initPEM(LIBSSH2_SESSION * session,
+ const char *privkeyfile,
+ unsigned const char *passphrase,
+ void **abstract)
+{
+ libssh2_ecdsa_ctx *ec_ctx = NULL;
+ int ret;
+
+ if(abstract != NULL && *abstract) {
+ hostkey_method_ssh_ecdsa_dtor(session, abstract);
+ *abstract = NULL;
+ }
+
+ ret = _libssh2_ecdsa_new_private(&ec_ctx, session,
+ privkeyfile, passphrase);
+
+ if(abstract != NULL)
+ *abstract = ec_ctx;
+
+ return ret;
+}
+
+/*
+ * hostkey_method_ssh_ecdsa_initPEMFromMemory
+ *
+ * Load a Private Key from memory
+ */
+static int
+hostkey_method_ssh_ecdsa_initPEMFromMemory(LIBSSH2_SESSION * session,
+ const char *privkeyfiledata,
+ size_t privkeyfiledata_len,
+ unsigned const char *passphrase,
+ void **abstract)
+{
+ libssh2_ecdsa_ctx *ec_ctx = NULL;
+ int ret;
+
+ if(abstract != NULL && *abstract) {
+ hostkey_method_ssh_ecdsa_dtor(session, abstract);
+ *abstract = NULL;
+ }
+
+ ret = _libssh2_ecdsa_new_private_frommemory(&ec_ctx, session,
+ privkeyfiledata,
+ privkeyfiledata_len,
+ passphrase);
+ if(ret) {
+ return -1;
+ }
+
+ if(abstract != NULL)
+ *abstract = ec_ctx;
+
+ return 0;
+}
+
+/*
+ * hostkey_method_ecdsa_sig_verify
+ *
+ * Verify signature created by remote
+ */
+static int
+hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session,
+ const unsigned char *sig,
+ size_t sig_len,
+ const unsigned char *m,
+ size_t m_len, void **abstract)
+{
+ unsigned char *r, *s, *name;
+ size_t r_len, s_len, name_len;
+ unsigned int len;
+ struct string_buf buf;
+ libssh2_ecdsa_ctx *ctx = (libssh2_ecdsa_ctx *) (*abstract);
+
+ (void) session;
+
+ if(sig_len < 35)
+ return -1;
+
+ /* keyname_len(4) + keyname(19){"ecdsa-sha2-nistp256"} +
+ signature_len(4) */
+ buf.data = (unsigned char *)sig;
+ buf.dataptr = buf.data;
+ buf.len = sig_len;
+
+ if(_libssh2_get_string(&buf, &name, &name_len) || name_len != 19)
+ return -1;
+
+ if(_libssh2_get_u32(&buf, &len) != 0 || len < 8)
+ return -1;
+
+ if(_libssh2_get_string(&buf, &r, &r_len))
+ return -1;
+
+ if(_libssh2_get_string(&buf, &s, &s_len))
+ return -1;
+
+ return _libssh2_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len);
+}
+
+
+#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type) \
+ { \
+ unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \
+ libssh2_sha##digest_type##_ctx ctx; \
+ int i; \
+ 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); \
+ }
+
+
+/*
+ * hostkey_method_ecdsa_signv
+ *
+ * Construct a signature from an array of vectors
+ */
+static int
+hostkey_method_ssh_ecdsa_signv(LIBSSH2_SESSION * session,
+ unsigned char **signature,
+ size_t *signature_len,
+ int veccount,
+ const struct iovec datavec[],
+ void **abstract)
+{
+ libssh2_ecdsa_ctx *ec_ctx = (libssh2_ecdsa_ctx *) (*abstract);
+ libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_ctx);
+ int ret = 0;
+
+ if(type == LIBSSH2_EC_CURVE_NISTP256) {
+ LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(256);
+ }
+ else if(type == LIBSSH2_EC_CURVE_NISTP384) {
+ LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(384);
+ }
+ else if(type == LIBSSH2_EC_CURVE_NISTP521) {
+ LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(512);
+ }
+ else {
+ return -1;
+ }
+
+ return ret;
+}
+
+/*
+ * hostkey_method_ssh_ecdsa_dtor
+ *
+ * Shutdown the hostkey by freeing EC_KEY context
+ */
+static int
+hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session, void **abstract)
+{
+ libssh2_ecdsa_ctx *keyctx = (libssh2_ecdsa_ctx *) (*abstract);
+ (void) session;
+
+ if(keyctx != NULL)
+ _libssh2_ecdsa_free(keyctx);
+
+ *abstract = NULL;
+
+ return 0;
+}
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp256 = {
+ "ecdsa-sha2-nistp256",
+ SHA256_DIGEST_LENGTH,
+ hostkey_method_ssh_ecdsa_init,
+ hostkey_method_ssh_ecdsa_initPEM,
+ hostkey_method_ssh_ecdsa_initPEMFromMemory,
+ hostkey_method_ssh_ecdsa_sig_verify,
+ hostkey_method_ssh_ecdsa_signv,
+ NULL, /* encrypt */
+ hostkey_method_ssh_ecdsa_dtor,
+};
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp384 = {
+ "ecdsa-sha2-nistp384",
+ SHA384_DIGEST_LENGTH,
+ hostkey_method_ssh_ecdsa_init,
+ hostkey_method_ssh_ecdsa_initPEM,
+ hostkey_method_ssh_ecdsa_initPEMFromMemory,
+ hostkey_method_ssh_ecdsa_sig_verify,
+ hostkey_method_ssh_ecdsa_signv,
+ NULL, /* encrypt */
+ hostkey_method_ssh_ecdsa_dtor,
+};
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521 = {
+ "ecdsa-sha2-nistp521",
+ SHA512_DIGEST_LENGTH,
+ hostkey_method_ssh_ecdsa_init,
+ hostkey_method_ssh_ecdsa_initPEM,
+ hostkey_method_ssh_ecdsa_initPEMFromMemory,
+ hostkey_method_ssh_ecdsa_sig_verify,
+ hostkey_method_ssh_ecdsa_signv,
+ NULL, /* encrypt */
+ hostkey_method_ssh_ecdsa_dtor,
+};
+
+#endif /* LIBSSH2_ECDSA */
+
+#if LIBSSH2_ED25519
+
+/* ***********
+ * ed25519 *
+ *********** */
+
+static int hostkey_method_ssh_ed25519_dtor(LIBSSH2_SESSION * session,
+ void **abstract);
+
+/*
+ * hostkey_method_ssh_ed25519_init
+ *
+ * Initialize the server hostkey working area with e/n pair
+ */
+static int
+hostkey_method_ssh_ed25519_init(LIBSSH2_SESSION * session,
+ const unsigned char *hostkey_data,
+ size_t hostkey_data_len,
+ void **abstract)
+{
+ const unsigned char *s;
+ unsigned long len, key_len;
+ libssh2_ed25519_ctx *ctx = NULL;
+
+ if(*abstract) {
+ hostkey_method_ssh_ed25519_dtor(session, abstract);
+ *abstract = NULL;
+ }
+
+ if(hostkey_data_len < 19) {
+ _libssh2_debug(session, LIBSSH2_TRACE_ERROR,
+ "host key length too short");
+ return -1;
+ }
+
+ s = hostkey_data;
+ len = _libssh2_ntohu32(s);
+ s += 4;
+
+ if(len != 11 || strncmp((char *) s, "ssh-ed25519", 11) != 0) {
+ return -1;
+ }
+
+ s += 11;
+
+ /* public key */
+ key_len = _libssh2_ntohu32(s);
+ s += 4;
+
+ if(_libssh2_ed25519_new_public(&ctx, session, s, key_len) != 0) {
+ return -1;
+ }
+
+ *abstract = ctx;
+
+ return 0;
+}
+
+/*
+ * hostkey_method_ssh_ed25519_initPEM
+ *
+ * Load a Private Key from a PEM file
+ */
+static int
+hostkey_method_ssh_ed25519_initPEM(LIBSSH2_SESSION * session,
+ const char *privkeyfile,
+ unsigned const char *passphrase,
+ void **abstract)
+{
+ libssh2_ed25519_ctx *ec_ctx = NULL;
+ int ret;
+
+ if(*abstract) {
+ hostkey_method_ssh_ed25519_dtor(session, abstract);
+ *abstract = NULL;
+ }
+
+ ret = _libssh2_ed25519_new_private(&ec_ctx, session,
+ privkeyfile, passphrase);
+ if(ret) {
+ return -1;
+ }
+
+ *abstract = ec_ctx;
+
+ return ret;
+}
+
+/*
+ * hostkey_method_ssh_ed25519_initPEMFromMemory
+ *
+ * Load a Private Key from memory
+ */
+static int
+hostkey_method_ssh_ed25519_initPEMFromMemory(LIBSSH2_SESSION * session,
+ const char *privkeyfiledata,
+ size_t privkeyfiledata_len,
+ unsigned const char *passphrase,
+ void **abstract)
+{
+ libssh2_ed25519_ctx *ed_ctx = NULL;
+ int ret;
+
+ if(abstract != NULL && *abstract) {
+ hostkey_method_ssh_ed25519_dtor(session, abstract);
+ *abstract = NULL;
+ }
+
+ ret = _libssh2_ed25519_new_private_frommemory(&ed_ctx, session,
+ privkeyfiledata,
+ privkeyfiledata_len,
+ passphrase);
+ if(ret) {
+ return -1;
+ }
+
+ if(abstract != NULL)
+ *abstract = ed_ctx;
+
+ return 0;
+}
+
+/*
+ * hostkey_method_ssh_ed25519_sig_verify
+ *
+ * Verify signature created by remote
+ */
+static int
+hostkey_method_ssh_ed25519_sig_verify(LIBSSH2_SESSION * session,
+ const unsigned char *sig,
+ size_t sig_len,
+ const unsigned char *m,
+ size_t m_len, void **abstract)
+{
+ libssh2_ed25519_ctx *ctx = (libssh2_ed25519_ctx *) (*abstract);
+ (void) session;
+
+ if(sig_len < 19)
+ return -1;
+
+ /* Skip past keyname_len(4) + keyname(11){"ssh-ed25519"} +
+ signature_len(4) */
+ sig += 19;
+ sig_len -= 19;
+
+ if(sig_len != LIBSSH2_ED25519_SIG_LEN)
+ return -1;
+
+ return _libssh2_ed25519_verify(ctx, sig, sig_len, m, m_len);
+}
+
+/*
+ * hostkey_method_ssh_ed25519_signv
+ *
+ * Construct a signature from an array of vectors
+ */
+static int
+hostkey_method_ssh_ed25519_signv(LIBSSH2_SESSION * session,
+ unsigned char **signature,
+ size_t *signature_len,
+ int veccount,
+ const struct iovec datavec[],
+ void **abstract)
+{
+ libssh2_ed25519_ctx *ctx = (libssh2_ed25519_ctx *) (*abstract);
+
+ if(veccount != 1) {
+ return -1;
+ }
+
+ return _libssh2_ed25519_sign(ctx, session, signature, signature_len,
+ datavec[0].iov_base, datavec[0].iov_len);
+}
+
+
+/*
+ * hostkey_method_ssh_ed25519_dtor
+ *
+ * Shutdown the hostkey by freeing key context
+ */
+static int
+hostkey_method_ssh_ed25519_dtor(LIBSSH2_SESSION * session, void **abstract)
+{
+ libssh2_ed25519_ctx *keyctx = (libssh2_ed25519_ctx*) (*abstract);
+ (void) session;
+
+ if(keyctx)
+ _libssh2_ed25519_free(keyctx);
+
+ *abstract = NULL;
+
+ return 0;
+}
+
+static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_ed25519 = {
+ "ssh-ed25519",
+ SHA256_DIGEST_LENGTH,
+ hostkey_method_ssh_ed25519_init,
+ hostkey_method_ssh_ed25519_initPEM,
+ hostkey_method_ssh_ed25519_initPEMFromMemory,
+ hostkey_method_ssh_ed25519_sig_verify,
+ hostkey_method_ssh_ed25519_signv,
+ NULL, /* encrypt */
+ hostkey_method_ssh_ed25519_dtor,
+};
+
+#endif /*LIBSSH2_ED25519*/
+
+
static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = {
+#if LIBSSH2_ECDSA
+ &hostkey_method_ecdsa_ssh_nistp256,
+ &hostkey_method_ecdsa_ssh_nistp384,
+ &hostkey_method_ecdsa_ssh_nistp521,
+#endif
+#if LIBSSH2_ED25519
+ &hostkey_method_ssh_ed25519,
+#endif
#if LIBSSH2_RSA
&hostkey_method_ssh_rsa,
#endif /* LIBSSH2_RSA */
@@ -505,12 +1024,12 @@ libssh2_hostkey_methods(void)
* Returns hash signature
* Returned buffer should NOT be freed
* Length of buffer is determined by hash type
- * i.e. MD5 == 16, SHA1 == 20
+ * i.e. MD5 == 16, SHA1 == 20, SHA256 == 32
*/
LIBSSH2_API const char *
libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type)
{
- switch (hash_type) {
+ switch(hash_type) {
#if LIBSSH2_MD5
case LIBSSH2_HOSTKEY_HASH_MD5:
return (session->server_hostkey_md5_valid)
@@ -523,6 +1042,11 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type)
? (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;
}
@@ -530,22 +1054,55 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type)
static int hostkey_type(const unsigned char *hostkey, size_t len)
{
- const unsigned char rsa[] = {
+ static const unsigned char rsa[] = {
0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a'
};
- const unsigned char dss[] = {
+ static const unsigned char dss[] = {
0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's'
};
+ 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'
+ };
+ static const unsigned char ecdsa_384[] = {
+ 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-',
+ 'n', 'i', 's', 't', 'p', '3', '8', '4'
+ };
+ static const unsigned char ecdsa_521[] = {
+ 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-',
+ 'n', 'i', 's', 't', 'p', '5', '2', '1'
+ };
+ static const unsigned char ed25519[] = {
+ 0, 0, 0, 0x0b, 's', 's', 'h', '-', 'e', 'd', '2', '5', '5', '1', '9'
+ };
- if (len < 11)
+ if(len < 11)
return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
- if (!memcmp(rsa, hostkey, 11))
+ if(!memcmp(rsa, hostkey, 11))
return LIBSSH2_HOSTKEY_TYPE_RSA;
- if (!memcmp(dss, hostkey, 11))
+ if(!memcmp(dss, hostkey, 11))
return LIBSSH2_HOSTKEY_TYPE_DSS;
+ if(len < 15)
+ return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
+
+ if(!memcmp(ed25519, hostkey, 15))
+ return LIBSSH2_HOSTKEY_TYPE_ED25519;
+
+ if(len < 23)
+ return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
+
+ if(!memcmp(ecdsa_256, hostkey, 23))
+ return LIBSSH2_HOSTKEY_TYPE_ECDSA_256;
+
+ if(!memcmp(ecdsa_384, hostkey, 23))
+ return LIBSSH2_HOSTKEY_TYPE_ECDSA_384;
+
+ if(!memcmp(ecdsa_521, hostkey, 23))
+ return LIBSSH2_HOSTKEY_TYPE_ECDSA_521;
+
return LIBSSH2_HOSTKEY_TYPE_UNKNOWN;
}
@@ -561,7 +1118,7 @@ libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type)
if(session->server_hostkey_len) {
if(len)
*len = session->server_hostkey_len;
- if (type)
+ if(type)
*type = hostkey_type(session->server_hostkey,
session->server_hostkey_len);
return (char *) session->server_hostkey;
@@ -570,4 +1127,3 @@ libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type)
*len = 0;
return NULL;
}
-
diff --git a/libs/libssh2/src/keepalive.c b/libs/libssh2/src/keepalive.c
index fd749dd296..2151b17100 100644
--- a/libs/libssh2/src/keepalive.c
+++ b/libs/libssh2/src/keepalive.c
@@ -46,7 +46,7 @@ libssh2_keepalive_config (LIBSSH2_SESSION *session,
int want_reply,
unsigned interval)
{
- if (interval == 1)
+ if(interval == 1)
session->keepalive_interval = 2;
else
session->keepalive_interval = interval;
@@ -59,20 +59,20 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session,
{
time_t now;
- if (!session->keepalive_interval) {
- if (seconds_to_next)
+ if(!session->keepalive_interval) {
+ if(seconds_to_next)
*seconds_to_next = 0;
return 0;
}
- now = time (NULL);
+ now = time(NULL);
- if (session->keepalive_last_sent + session->keepalive_interval <= now) {
+ if(session->keepalive_last_sent + session->keepalive_interval <= now) {
/* Format is
"SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */
unsigned char keepalive_data[]
= "\x50\x00\x00\x00\x15keepalive@libssh2.orgW";
- size_t len = sizeof (keepalive_data) - 1;
+ size_t len = sizeof(keepalive_data) - 1;
int rc;
keepalive_data[len - 1] =
@@ -81,16 +81,17 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session,
rc = _libssh2_transport_send(session, keepalive_data, len, NULL, 0);
/* Silently ignore PACKET_EAGAIN here: if the write buffer is
already full, sending another keepalive is not useful. */
- if (rc && rc != LIBSSH2_ERROR_EAGAIN) {
+ if(rc && rc != LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send keepalive message");
return rc;
}
session->keepalive_last_sent = now;
- if (seconds_to_next)
+ if(seconds_to_next)
*seconds_to_next = session->keepalive_interval;
- } else if (seconds_to_next) {
+ }
+ else if(seconds_to_next) {
*seconds_to_next = (int) (session->keepalive_last_sent - now)
+ session->keepalive_interval;
}
diff --git a/libs/libssh2/src/kex.c b/libs/libssh2/src/kex.c
index 3634cb5a91..cb1663937d 100644
--- a/libs/libssh2/src/kex.c
+++ b/libs/libssh2/src/kex.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
- * Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
+ * Copyright (c) 2010-2019, Daniel Stenberg <daniel@haxx.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -43,24 +43,26 @@
#include "mac.h"
/* TODO: Switch this to an inline and handle alloc() failures */
-/* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */
+/* Helper macro called from
+ kex_method_diffie_hellman_group1_sha1_key_exchange */
#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
{ \
libssh2_sha1_ctx hash; \
unsigned long len = 0; \
- if (!(value)) { \
+ if(!(value)) { \
value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
} \
- if (value) \
- while (len < (unsigned long)reqlen) { \
+ if(value) \
+ while(len < (unsigned long)reqlen) { \
libssh2_sha1_init(&hash); \
libssh2_sha1_update(hash, exchange_state->k_value, \
exchange_state->k_value_len); \
libssh2_sha1_update(hash, exchange_state->h_sig_comp, \
SHA_DIGEST_LENGTH); \
- if (len > 0) { \
+ if(len > 0) { \
libssh2_sha1_update(hash, value, len); \
- } else { \
+ } \
+ else { \
libssh2_sha1_update(hash, (version), 1); \
libssh2_sha1_update(hash, session->session_id, \
session->session_id_len); \
@@ -68,35 +70,53 @@
libssh2_sha1_final(hash, (value) + len); \
len += SHA_DIGEST_LENGTH; \
} \
- }
+ } \
-/* Helper macro called from kex_method_diffie_hellman_group1_sha256_key_exchange */
-#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(value, reqlen, version) \
- { \
- libssh2_sha256_ctx hash; \
- unsigned long len = 0; \
- if (!(value)) { \
- value = LIBSSH2_ALLOC(session, reqlen + SHA256_DIGEST_LENGTH); \
- } \
- if (value) \
- while (len < (unsigned long)reqlen) { \
- libssh2_sha256_init(&hash); \
- libssh2_sha256_update(hash, exchange_state->k_value, \
- exchange_state->k_value_len); \
- libssh2_sha256_update(hash, exchange_state->h_sig_comp, \
- SHA256_DIGEST_LENGTH); \
- if (len > 0) { \
- libssh2_sha256_update(hash, value, len); \
- } else { \
- libssh2_sha256_update(hash, (version), 1); \
- libssh2_sha256_update(hash, session->session_id, \
- session->session_id_len); \
- } \
- libssh2_sha256_final(hash, (value) + len); \
- len += SHA256_DIGEST_LENGTH; \
- } \
- }
+#define LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(value, reqlen, version) \
+ { \
+ if(type == LIBSSH2_EC_CURVE_NISTP256) { \
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, value, reqlen, version); \
+ } \
+ else if(type == LIBSSH2_EC_CURVE_NISTP384) { \
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(384, value, reqlen, version); \
+ } \
+ else if(type == LIBSSH2_EC_CURVE_NISTP521) { \
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, value, reqlen, version); \
+ } \
+ } \
+
+
+#define LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(digest_type, value, \
+ reqlen, version) \
+{ \
+ libssh2_sha##digest_type##_ctx hash; \
+ unsigned long len = 0; \
+ if(!(value)) { \
+ value = LIBSSH2_ALLOC(session, \
+ reqlen + SHA##digest_type##_DIGEST_LENGTH); \
+ } \
+ if(value) \
+ while(len < (unsigned long)reqlen) { \
+ 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(len > 0) { \
+ libssh2_sha##digest_type##_update(hash, value, len); \
+ } \
+ else { \
+ libssh2_sha##digest_type##_update(hash, (version), 1); \
+ libssh2_sha##digest_type##_update(hash, session->session_id, \
+ session->session_id_len); \
+ } \
+ libssh2_sha##digest_type##_final(hash, (value) + len); \
+ len += SHA##digest_type##_DIGEST_LENGTH; \
+ } \
+}
/*
@@ -118,37 +138,40 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
int rc;
libssh2_sha1_ctx exchange_hash_ctx;
- if (exchange_state->state == libssh2_NB_state_idle) {
+ if(exchange_state->state == libssh2_NB_state_idle) {
/* Setup initial values */
exchange_state->e_packet = NULL;
exchange_state->s_packet = NULL;
exchange_state->k_value = NULL;
exchange_state->ctx = _libssh2_bn_ctx_new();
- exchange_state->x = _libssh2_bn_init(); /* Random from client */
+ libssh2_dh_init(&exchange_state->x);
exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
- exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from server) mod p */
- exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */
+ exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from
+ server) mod p */
+ exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod
+ p */
/* Zero the whole thing out */
memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
/* Generate x and e */
- _libssh2_bn_rand(exchange_state->x, group_order * 8 - 1, 0, -1);
- _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p,
- exchange_state->ctx);
+ rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
+ group_order, exchange_state->ctx);
+ if(rc)
+ goto clean_exit;
/* Send KEX init */
/* packet_type(1) + String Length(4) + leading 0(1) */
exchange_state->e_packet_len =
_libssh2_bn_bytes(exchange_state->e) + 6;
- if (_libssh2_bn_bits(exchange_state->e) % 8) {
+ if(_libssh2_bn_bits(exchange_state->e) % 8) {
/* Leading 00 not needed */
exchange_state->e_packet_len--;
}
exchange_state->e_packet =
LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
- if (!exchange_state->e_packet) {
+ if(!exchange_state->e_packet) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Out of memory error");
goto clean_exit;
@@ -156,10 +179,11 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->e_packet[0] = packet_type_init;
_libssh2_htonu32(exchange_state->e_packet + 1,
exchange_state->e_packet_len - 5);
- if (_libssh2_bn_bits(exchange_state->e) % 8) {
+ if(_libssh2_bn_bits(exchange_state->e) % 8) {
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 5);
- } else {
+ }
+ else {
exchange_state->e_packet[5] = 0;
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 6);
@@ -170,13 +194,14 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_created;
}
- if (exchange_state->state == libssh2_NB_state_created) {
+ if(exchange_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, exchange_state->e_packet,
exchange_state->e_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Unable to send KEX init message");
goto clean_exit;
@@ -184,20 +209,22 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent;
}
- if (exchange_state->state == libssh2_NB_state_sent) {
- if (session->burn_optimistic_kexinit) {
+ if(exchange_state->state == libssh2_NB_state_sent) {
+ if(session->burn_optimistic_kexinit) {
/* The first KEX packet to come along will be the guess initially
* sent by the server. That guess turned out to be wrong so we
* need to silently ignore it */
int burn_type;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Waiting for badly guessed KEX packet (to be ignored)");
+ "Waiting for badly guessed KEX packet "
+ "(to be ignored)");
burn_type =
_libssh2_packet_burn(session, &exchange_state->burn_state);
- if (burn_type == LIBSSH2_ERROR_EAGAIN) {
+ if(burn_type == LIBSSH2_ERROR_EAGAIN) {
return burn_type;
- } else if (burn_type <= 0) {
+ }
+ else if(burn_type <= 0) {
/* Failed to receive a packet */
ret = burn_type;
goto clean_exit;
@@ -212,16 +239,19 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent1;
}
- if (exchange_state->state == libssh2_NB_state_sent1) {
+ if(exchange_state->state == libssh2_NB_state_sent1) {
/* Wait for KEX reply */
+ struct string_buf buf;
+ size_t host_key_len;
+
rc = _libssh2_packet_require(session, packet_type_reply,
&exchange_state->s_packet,
&exchange_state->s_packet_len, 0, NULL,
0, &exchange_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- if (rc) {
+ if(rc) {
ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for KEX reply");
goto clean_exit;
@@ -234,37 +264,28 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
goto clean_exit;
}
- exchange_state->s = exchange_state->s_packet + 1;
-
- session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
-
- if(session->server_hostkey_len > exchange_state->s_packet_len - 5) {
- ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
- "Host key length out of bounds");
- goto clean_exit;
- }
+ buf.data = exchange_state->s_packet;
+ buf.len = exchange_state->s_packet_len;
+ 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 =
- LIBSSH2_ALLOC(session, session->server_hostkey_len);
- if (!session->server_hostkey) {
+ if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
+ &host_key_len)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate memory for a copy "
- "of the host key");
+ "Could not copy host key");
goto clean_exit;
}
- memcpy(session->server_hostkey, exchange_state->s,
- session->server_hostkey_len);
- exchange_state->s += session->server_hostkey_len;
+
+ session->server_hostkey_len = (uint32_t)host_key_len;
#if LIBSSH2_MD5
{
libssh2_md5_ctx fingerprint_ctx;
- if (libssh2_md5_init(&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,
@@ -292,7 +313,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
{
libssh2_sha1_ctx fingerprint_ctx;
- if (libssh2_sha1_init(&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,
@@ -317,7 +338,38 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
#endif /* LIBSSH2DEBUG */
- if (session->hostkey->init(session, session->server_hostkey,
+ {
+ 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);
+ session->server_hostkey_sha256_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha256_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char *base64Fingerprint = NULL;
+ _libssh2_base64_encode(session,
+ (const char *)
+ session->server_hostkey_sha256,
+ SHA256_DIGEST_LENGTH, &base64Fingerprint);
+ if(base64Fingerprint != NULL) {
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA256 Fingerprint: %s",
+ base64Fingerprint);
+ LIBSSH2_FREE(session, base64Fingerprint);
+ }
+ }
+#endif /* LIBSSH2DEBUG */
+
+
+ if(session->hostkey->init(session, session->server_hostkey,
session->server_hostkey_len,
&session->server_hostkey_abstract)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
@@ -325,58 +377,67 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
goto clean_exit;
}
- exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
- exchange_state->f_value = exchange_state->s;
- exchange_state->s += exchange_state->f_value_len;
+ if(_libssh2_get_string(&buf, &(exchange_state->f_value),
+ &(exchange_state->f_value_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to get f value");
+ goto clean_exit;
+ }
+
_libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
exchange_state->f_value);
- exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
- exchange_state->h_sig = exchange_state->s;
+ if(_libssh2_get_string(&buf, &(exchange_state->h_sig),
+ &(exchange_state->h_sig_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to get h sig");
+ goto clean_exit;
+ }
/* Compute the shared secret */
- _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f,
- exchange_state->x, p, exchange_state->ctx);
+ libssh2_dh_secret(&exchange_state->x, exchange_state->k,
+ exchange_state->f, p, exchange_state->ctx);
exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
- if (_libssh2_bn_bits(exchange_state->k) % 8) {
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
/* don't need leading 00 */
exchange_state->k_value_len--;
}
exchange_state->k_value =
LIBSSH2_ALLOC(session, exchange_state->k_value_len);
- if (!exchange_state->k_value) {
+ if(!exchange_state->k_value) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for K");
goto clean_exit;
}
_libssh2_htonu32(exchange_state->k_value,
exchange_state->k_value_len - 4);
- if (_libssh2_bn_bits(exchange_state->k) % 8) {
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
- } else {
+ }
+ else {
exchange_state->k_value[4] = 0;
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
}
- exchange_state->exchange_hash = (void*)&exchange_hash_ctx;
+ exchange_state->exchange_hash = (void *)&exchange_hash_ctx;
libssh2_sha1_init(&exchange_hash_ctx);
- if (session->local.banner) {
+ if(session->local.banner) {
_libssh2_htonu32(exchange_state->h_sig_comp,
strlen((char *) session->local.banner) - 2);
libssh2_sha1_update(exchange_hash_ctx,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_hash_ctx,
- (char *) session->local.banner,
+ session->local.banner,
strlen((char *) session->local.banner) - 2);
- } else {
+ }
+ else {
_libssh2_htonu32(exchange_state->h_sig_comp,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
libssh2_sha1_update(exchange_hash_ctx,
exchange_state->h_sig_comp, 4);
libssh2_sha1_update(exchange_hash_ctx,
+ (const unsigned char *)
LIBSSH2_SSH_DEFAULT_BANNER,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
}
@@ -413,7 +474,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
session->server_hostkey,
session->server_hostkey_len);
- if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
+ if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
/* diffie-hellman-group-exchange hashes additional fields */
#ifdef LIBSSH2_DH_GEX_NEW
_libssh2_htonu32(exchange_state->h_sig_comp,
@@ -432,7 +493,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
#endif
}
- if (midhash) {
+ if(midhash) {
libssh2_sha1_update(exchange_hash_ctx, midhash,
midhash_len);
}
@@ -456,7 +517,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
libssh2_sha1_final(exchange_hash_ctx,
exchange_state->h_sig_comp);
- if (session->hostkey->
+ if(session->hostkey->
sig_verify(session, exchange_state->h_sig,
exchange_state->h_sig_len, exchange_state->h_sig_comp,
20, &session->server_hostkey_abstract)) {
@@ -471,26 +532,29 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent2;
}
- if (exchange_state->state == libssh2_NB_state_sent2) {
+ if(exchange_state->state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
- ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message");
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send NEWKEYS message");
goto clean_exit;
}
exchange_state->state = libssh2_NB_state_sent3;
}
- if (exchange_state->state == libssh2_NB_state_sent3) {
+ if(exchange_state->state == libssh2_NB_state_sent3) {
rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
&exchange_state->tmp,
&exchange_state->tmp_len, 0, NULL, 0,
&exchange_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
goto clean_exit;
}
@@ -503,46 +567,52 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
for this packet type anyway */
LIBSSH2_FREE(session, exchange_state->tmp);
- if (!session->session_id) {
+ if(!session->session_id) {
session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH);
- if (!session->session_id) {
+ if(!session->session_id) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate buffer for SHA digest");
+ "Unable to allocate buffer for "
+ "SHA digest");
goto clean_exit;
}
memcpy(session->session_id, exchange_state->h_sig_comp,
SHA_DIGEST_LENGTH);
session->session_id_len = SHA_DIGEST_LENGTH;
- _libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated");
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "session_id calculated");
}
/* Cleanup any existing cipher */
- if (session->local.crypt->dtor) {
+ if(session->local.crypt->dtor) {
session->local.crypt->dtor(session,
&session->local.crypt_abstract);
}
/* Calculate IV/Secret/Key for each direction */
- if (session->local.crypt->init) {
+ if(session->local.crypt->init) {
unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
session->local.crypt->
- iv_len, "A");
- if (!iv) {
+ iv_len,
+ (const unsigned char *)
+ "A");
+ if(!iv) {
ret = -1;
goto clean_exit;
}
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
session->local.crypt->
- secret_len, "C");
- if (!secret) {
+ secret_len,
+ (const unsigned char *)
+ "C");
+ if(!secret) {
LIBSSH2_FREE(session, iv);
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- if (session->local.crypt->
+ if(session->local.crypt->
init(session, session->local.crypt, iv, &free_iv, secret,
&free_secret, 1, &session->local.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
@@ -551,45 +621,50 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
goto clean_exit;
}
- if (free_iv) {
- memset(iv, 0, session->local.crypt->iv_len);
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
LIBSSH2_FREE(session, iv);
}
- if (free_secret) {
- memset(secret, 0, session->local.crypt->secret_len);
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->local.crypt->secret_len);
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server IV and Key calculated");
- if (session->remote.crypt->dtor) {
+ if(session->remote.crypt->dtor) {
/* Cleanup any existing cipher */
session->remote.crypt->dtor(session,
&session->remote.crypt_abstract);
}
- if (session->remote.crypt->init) {
+ if(session->remote.crypt->init) {
unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
session->remote.crypt->
- iv_len, "B");
- if (!iv) {
+ iv_len,
+ (const unsigned char *)
+ "B");
+ if(!iv) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
session->remote.crypt->
- secret_len, "D");
- if (!secret) {
+ secret_len,
+ (const unsigned char *)
+ "D");
+ if(!secret) {
LIBSSH2_FREE(session, iv);
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- if (session->remote.crypt->
+ if(session->remote.crypt->
init(session, session->remote.crypt, iv, &free_iv, secret,
&free_secret, 0, &session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
@@ -598,65 +673,70 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
goto clean_exit;
}
- if (free_iv) {
- memset(iv, 0, session->remote.crypt->iv_len);
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
LIBSSH2_FREE(session, iv);
}
- if (free_secret) {
- memset(secret, 0, session->remote.crypt->secret_len);
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->remote.crypt->secret_len);
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server to Client IV and Key calculated");
- if (session->local.mac->dtor) {
+ if(session->local.mac->dtor) {
session->local.mac->dtor(session, &session->local.mac_abstract);
}
- if (session->local.mac->init) {
+ if(session->local.mac->init) {
unsigned char *key = NULL;
int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
session->local.mac->
- key_len, "E");
- if (!key) {
+ key_len,
+ (const unsigned char *)
+ "E");
+ if(!key) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->local.mac->init(session, key, &free_key,
&session->local.mac_abstract);
- if (free_key) {
- memset(key, 0, session->local.mac->key_len);
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->local.mac->key_len);
LIBSSH2_FREE(session, key);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server HMAC Key calculated");
- if (session->remote.mac->dtor) {
+ if(session->remote.mac->dtor) {
session->remote.mac->dtor(session, &session->remote.mac_abstract);
}
- if (session->remote.mac->init) {
+ if(session->remote.mac->init) {
unsigned char *key = NULL;
int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
session->remote.mac->
- key_len, "F");
- if (!key) {
+ key_len,
+ (const unsigned char *)
+ "F");
+ if(!key) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->remote.mac->init(session, key, &free_key,
&session->remote.mac_abstract);
- if (free_key) {
- memset(key, 0, session->remote.mac->key_len);
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->remote.mac->key_len);
LIBSSH2_FREE(session, key);
}
}
@@ -666,13 +746,13 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
/* Initialize compression for each direction */
/* Cleanup any existing compression */
- if (session->local.comp && session->local.comp->dtor) {
+ if(session->local.comp && session->local.comp->dtor) {
session->local.comp->dtor(session, 1,
&session->local.comp_abstract);
}
- if (session->local.comp && session->local.comp->init) {
- if (session->local.comp->init(session, 1,
+ if(session->local.comp && session->local.comp->init) {
+ if(session->local.comp->init(session, 1,
&session->local.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
@@ -681,13 +761,13 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server compression initialized");
- if (session->remote.comp && session->remote.comp->dtor) {
+ if(session->remote.comp && session->remote.comp->dtor) {
session->remote.comp->dtor(session, 0,
&session->remote.comp_abstract);
}
- if (session->remote.comp && session->remote.comp->init) {
- if (session->remote.comp->init(session, 0,
+ if(session->remote.comp && session->remote.comp->init) {
+ if(session->remote.comp->init(session, 0,
&session->remote.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
@@ -699,8 +779,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
}
clean_exit:
- _libssh2_bn_free(exchange_state->x);
- exchange_state->x = NULL;
+ libssh2_dh_dtor(&exchange_state->x);
_libssh2_bn_free(exchange_state->e);
exchange_state->e = NULL;
_libssh2_bn_free(exchange_state->f);
@@ -710,17 +789,17 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
_libssh2_bn_ctx_free(exchange_state->ctx);
exchange_state->ctx = NULL;
- if (exchange_state->e_packet) {
+ if(exchange_state->e_packet) {
LIBSSH2_FREE(session, exchange_state->e_packet);
exchange_state->e_packet = NULL;
}
- if (exchange_state->s_packet) {
+ if(exchange_state->s_packet) {
LIBSSH2_FREE(session, exchange_state->s_packet);
exchange_state->s_packet = NULL;
}
- if (exchange_state->k_value) {
+ if(exchange_state->k_value) {
LIBSSH2_FREE(session, exchange_state->k_value);
exchange_state->k_value = NULL;
}
@@ -750,37 +829,40 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
int rc;
libssh2_sha256_ctx exchange_hash_ctx;
- if (exchange_state->state == libssh2_NB_state_idle) {
+ if(exchange_state->state == libssh2_NB_state_idle) {
/* Setup initial values */
exchange_state->e_packet = NULL;
exchange_state->s_packet = NULL;
exchange_state->k_value = NULL;
exchange_state->ctx = _libssh2_bn_ctx_new();
- exchange_state->x = _libssh2_bn_init(); /* Random from client */
+ libssh2_dh_init(&exchange_state->x);
exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
- exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from server) mod p */
- exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */
+ exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from
+ server) mod p */
+ exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod
+ p */
/* Zero the whole thing out */
memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
/* Generate x and e */
- _libssh2_bn_rand(exchange_state->x, group_order * 8 - 1, 0, -1);
- _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p,
- exchange_state->ctx);
+ rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
+ group_order, exchange_state->ctx);
+ if(rc)
+ goto clean_exit;
/* Send KEX init */
/* packet_type(1) + String Length(4) + leading 0(1) */
exchange_state->e_packet_len =
_libssh2_bn_bytes(exchange_state->e) + 6;
- if (_libssh2_bn_bits(exchange_state->e) % 8) {
+ if(_libssh2_bn_bits(exchange_state->e) % 8) {
/* Leading 00 not needed */
exchange_state->e_packet_len--;
}
exchange_state->e_packet =
LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
- if (!exchange_state->e_packet) {
+ if(!exchange_state->e_packet) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Out of memory error");
goto clean_exit;
@@ -788,10 +870,11 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->e_packet[0] = packet_type_init;
_libssh2_htonu32(exchange_state->e_packet + 1,
exchange_state->e_packet_len - 5);
- if (_libssh2_bn_bits(exchange_state->e) % 8) {
+ if(_libssh2_bn_bits(exchange_state->e) % 8) {
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 5);
- } else {
+ }
+ else {
exchange_state->e_packet[5] = 0;
_libssh2_bn_to_bin(exchange_state->e,
exchange_state->e_packet + 6);
@@ -802,13 +885,14 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_created;
}
- if (exchange_state->state == libssh2_NB_state_created) {
+ if(exchange_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, exchange_state->e_packet,
exchange_state->e_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Unable to send KEX init message");
goto clean_exit;
@@ -816,20 +900,22 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent;
}
- if (exchange_state->state == libssh2_NB_state_sent) {
- if (session->burn_optimistic_kexinit) {
+ if(exchange_state->state == libssh2_NB_state_sent) {
+ if(session->burn_optimistic_kexinit) {
/* The first KEX packet to come along will be the guess initially
* sent by the server. That guess turned out to be wrong so we
* need to silently ignore it */
int burn_type;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Waiting for badly guessed KEX packet (to be ignored)");
+ "Waiting for badly guessed KEX packet "
+ "(to be ignored)");
burn_type =
_libssh2_packet_burn(session, &exchange_state->burn_state);
- if (burn_type == LIBSSH2_ERROR_EAGAIN) {
+ if(burn_type == LIBSSH2_ERROR_EAGAIN) {
return burn_type;
- } else if (burn_type <= 0) {
+ }
+ else if(burn_type <= 0) {
/* Failed to receive a packet */
ret = burn_type;
goto clean_exit;
@@ -844,16 +930,19 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent1;
}
- if (exchange_state->state == libssh2_NB_state_sent1) {
+ if(exchange_state->state == libssh2_NB_state_sent1) {
/* Wait for KEX reply */
+ struct string_buf buf;
+ size_t host_key_len;
+
rc = _libssh2_packet_require(session, packet_type_reply,
&exchange_state->s_packet,
&exchange_state->s_packet_len, 0, NULL,
0, &exchange_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- if (rc) {
+ if(rc) {
ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"Timed out waiting for KEX reply");
goto clean_exit;
@@ -865,38 +954,29 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
"Unexpected packet length");
goto clean_exit;
}
-
- exchange_state->s = exchange_state->s_packet + 1;
- session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
+ buf.data = exchange_state->s_packet;
+ buf.len = exchange_state->s_packet_len;
+ buf.dataptr = buf.data;
+ buf.dataptr++; /* advance past type */
- if(session->server_hostkey_len > exchange_state->s_packet_len - 5) {
- ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
- "Host key length out of bounds");
- goto clean_exit;
- }
-
- if (session->server_hostkey)
+ if(session->server_hostkey)
LIBSSH2_FREE(session, session->server_hostkey);
- session->server_hostkey =
- LIBSSH2_ALLOC(session, session->server_hostkey_len);
- if (!session->server_hostkey) {
+ if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
+ &host_key_len)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate memory for a copy "
- "of the host key");
+ "Could not copy host key");
goto clean_exit;
}
- memcpy(session->server_hostkey, exchange_state->s,
- session->server_hostkey_len);
- exchange_state->s += session->server_hostkey_len;
+
+ session->server_hostkey_len = (uint32_t)host_key_len;
#if LIBSSH2_MD5
{
libssh2_md5_ctx fingerprint_ctx;
- if (libssh2_md5_init(&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,
@@ -924,7 +1004,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
{
libssh2_sha1_ctx fingerprint_ctx;
- if (libssh2_sha1_init(&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,
@@ -949,7 +1029,37 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
}
#endif /* LIBSSH2DEBUG */
- if (session->hostkey->init(session, session->server_hostkey,
+ {
+ 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);
+ session->server_hostkey_sha256_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha256_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char *base64Fingerprint = NULL;
+ _libssh2_base64_encode(session,
+ (const char *)
+ session->server_hostkey_sha256,
+ SHA256_DIGEST_LENGTH, &base64Fingerprint);
+ if(base64Fingerprint != NULL) {
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA256 Fingerprint: %s",
+ base64Fingerprint);
+ LIBSSH2_FREE(session, base64Fingerprint);
+ }
+ }
+#endif /* LIBSSH2DEBUG */
+
+ if(session->hostkey->init(session, session->server_hostkey,
session->server_hostkey_len,
&session->server_hostkey_abstract)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
@@ -957,58 +1067,67 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
goto clean_exit;
}
- exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
- exchange_state->f_value = exchange_state->s;
- exchange_state->s += exchange_state->f_value_len;
+ if(_libssh2_get_string(&buf, &(exchange_state->f_value),
+ &(exchange_state->f_value_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to get f value");
+ goto clean_exit;
+ }
+
_libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
exchange_state->f_value);
- exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s);
- exchange_state->s += 4;
- exchange_state->h_sig = exchange_state->s;
+ if(_libssh2_get_string(&buf, &(exchange_state->h_sig),
+ &(exchange_state->h_sig_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to get h sig");
+ goto clean_exit;
+ }
/* Compute the shared secret */
- _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f,
- exchange_state->x, p, exchange_state->ctx);
+ libssh2_dh_secret(&exchange_state->x, exchange_state->k,
+ exchange_state->f, p, exchange_state->ctx);
exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
- if (_libssh2_bn_bits(exchange_state->k) % 8) {
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
/* don't need leading 00 */
exchange_state->k_value_len--;
}
exchange_state->k_value =
LIBSSH2_ALLOC(session, exchange_state->k_value_len);
- if (!exchange_state->k_value) {
+ if(!exchange_state->k_value) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate buffer for K");
goto clean_exit;
}
_libssh2_htonu32(exchange_state->k_value,
exchange_state->k_value_len - 4);
- if (_libssh2_bn_bits(exchange_state->k) % 8) {
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
- } else {
+ }
+ else {
exchange_state->k_value[4] = 0;
_libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
}
- exchange_state->exchange_hash = (void*)&exchange_hash_ctx;
+ exchange_state->exchange_hash = (void *)&exchange_hash_ctx;
libssh2_sha256_init(&exchange_hash_ctx);
- if (session->local.banner) {
+ if(session->local.banner) {
_libssh2_htonu32(exchange_state->h_sig_comp,
strlen((char *) session->local.banner) - 2);
libssh2_sha256_update(exchange_hash_ctx,
exchange_state->h_sig_comp, 4);
libssh2_sha256_update(exchange_hash_ctx,
- (char *) session->local.banner,
+ session->local.banner,
strlen((char *) session->local.banner) - 2);
- } else {
+ }
+ else {
_libssh2_htonu32(exchange_state->h_sig_comp,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
libssh2_sha256_update(exchange_hash_ctx,
exchange_state->h_sig_comp, 4);
libssh2_sha256_update(exchange_hash_ctx,
+ (const unsigned char *)
LIBSSH2_SSH_DEFAULT_BANNER,
sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
}
@@ -1045,7 +1164,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
session->server_hostkey,
session->server_hostkey_len);
- if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
+ if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
/* diffie-hellman-group-exchange hashes additional fields */
#ifdef LIBSSH2_DH_GEX_NEW
_libssh2_htonu32(exchange_state->h_sig_comp,
@@ -1064,7 +1183,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
#endif
}
- if (midhash) {
+ if(midhash) {
libssh2_sha256_update(exchange_hash_ctx, midhash,
midhash_len);
}
@@ -1088,10 +1207,11 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
libssh2_sha256_final(exchange_hash_ctx,
exchange_state->h_sig_comp);
- if (session->hostkey->
- sig_verify(session, exchange_state->h_sig,
- exchange_state->h_sig_len, exchange_state->h_sig_comp,
- SHA256_DIGEST_LENGTH, &session->server_hostkey_abstract)) {
+ if(session->hostkey->
+ sig_verify(session, exchange_state->h_sig,
+ exchange_state->h_sig_len, exchange_state->h_sig_comp,
+ SHA256_DIGEST_LENGTH,
+ &session->server_hostkey_abstract)) {
ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
"Unable to verify hostkey signature");
goto clean_exit;
@@ -1105,26 +1225,29 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
exchange_state->state = libssh2_NB_state_sent2;
}
- if (exchange_state->state == libssh2_NB_state_sent2) {
+ if(exchange_state->state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
- ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message");
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send NEWKEYS message");
goto clean_exit;
}
exchange_state->state = libssh2_NB_state_sent3;
}
- if (exchange_state->state == libssh2_NB_state_sent3) {
+ if(exchange_state->state == libssh2_NB_state_sent3) {
rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
&exchange_state->tmp,
&exchange_state->tmp_len, 0, NULL, 0,
&exchange_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
goto clean_exit;
}
@@ -1137,46 +1260,50 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
for this packet type anyway */
LIBSSH2_FREE(session, exchange_state->tmp);
- if (!session->session_id) {
+ if(!session->session_id) {
session->session_id = LIBSSH2_ALLOC(session, SHA256_DIGEST_LENGTH);
- if (!session->session_id) {
+ if(!session->session_id) {
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate buffer for SHA digest");
+ "Unable to allocate buffer for "
+ "SHA digest");
goto clean_exit;
}
memcpy(session->session_id, exchange_state->h_sig_comp,
SHA256_DIGEST_LENGTH);
session->session_id_len = SHA256_DIGEST_LENGTH;
- _libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated");
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "session_id calculated");
}
/* Cleanup any existing cipher */
- if (session->local.crypt->dtor) {
+ if(session->local.crypt->dtor) {
session->local.crypt->dtor(session,
&session->local.crypt_abstract);
}
/* Calculate IV/Secret/Key for each direction */
- if (session->local.crypt->init) {
+ if(session->local.crypt->init) {
unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0;
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(iv,
- session->local.crypt->
- iv_len, "A");
- if (!iv) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+ session->local.crypt->
+ iv_len,
+ (const unsigned char *)"A");
+ if(!iv) {
ret = -1;
goto clean_exit;
}
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(secret,
- session->local.crypt->
- secret_len, "C");
- if (!secret) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+ session->local.crypt->
+ secret_len,
+ (const unsigned char *)"C");
+ if(!secret) {
LIBSSH2_FREE(session, iv);
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- if (session->local.crypt->
+ if(session->local.crypt->
init(session, session->local.crypt, iv, &free_iv, secret,
&free_secret, 1, &session->local.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
@@ -1185,45 +1312,48 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
goto clean_exit;
}
- if (free_iv) {
- memset(iv, 0, session->local.crypt->iv_len);
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
LIBSSH2_FREE(session, iv);
}
- if (free_secret) {
- memset(secret, 0, session->local.crypt->secret_len);
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->local.crypt->secret_len);
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server IV and Key calculated");
- if (session->remote.crypt->dtor) {
+ if(session->remote.crypt->dtor) {
/* Cleanup any existing cipher */
session->remote.crypt->dtor(session,
&session->remote.crypt_abstract);
}
- if (session->remote.crypt->init) {
+ if(session->remote.crypt->init) {
unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0;
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(iv,
- session->remote.crypt->
- iv_len, "B");
- if (!iv) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+ session->remote.crypt->
+ iv_len,
+ (const unsigned char *)"B");
+ if(!iv) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(secret,
- session->remote.crypt->
- secret_len, "D");
- if (!secret) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+ session->remote.crypt->
+ secret_len,
+ (const unsigned char *)"D");
+ if(!secret) {
LIBSSH2_FREE(session, iv);
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
- if (session->remote.crypt->
+ if(session->remote.crypt->
init(session, session->remote.crypt, iv, &free_iv, secret,
&free_secret, 0, &session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, iv);
@@ -1232,65 +1362,68 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
goto clean_exit;
}
- if (free_iv) {
- memset(iv, 0, session->remote.crypt->iv_len);
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
LIBSSH2_FREE(session, iv);
}
- if (free_secret) {
- memset(secret, 0, session->remote.crypt->secret_len);
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->remote.crypt->secret_len);
LIBSSH2_FREE(session, secret);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Server to Client IV and Key calculated");
- if (session->local.mac->dtor) {
+ if(session->local.mac->dtor) {
session->local.mac->dtor(session, &session->local.mac_abstract);
}
- if (session->local.mac->init) {
+ if(session->local.mac->init) {
unsigned char *key = NULL;
int free_key = 0;
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(key,
- session->local.mac->
- key_len, "E");
- if (!key) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+ session->local.mac->
+ key_len,
+ (const unsigned char *)"E");
+ if(!key) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->local.mac->init(session, key, &free_key,
&session->local.mac_abstract);
- if (free_key) {
- memset(key, 0, session->local.mac->key_len);
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->local.mac->key_len);
LIBSSH2_FREE(session, key);
}
}
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server HMAC Key calculated");
- if (session->remote.mac->dtor) {
+ if(session->remote.mac->dtor) {
session->remote.mac->dtor(session, &session->remote.mac_abstract);
}
- if (session->remote.mac->init) {
+ if(session->remote.mac->init) {
unsigned char *key = NULL;
int free_key = 0;
- LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(key,
- session->remote.mac->
- key_len, "F");
- if (!key) {
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+ session->remote.mac->
+ key_len,
+ (const unsigned char *)"F");
+ if(!key) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
}
session->remote.mac->init(session, key, &free_key,
&session->remote.mac_abstract);
- if (free_key) {
- memset(key, 0, session->remote.mac->key_len);
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->remote.mac->key_len);
LIBSSH2_FREE(session, key);
}
}
@@ -1300,13 +1433,13 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
/* Initialize compression for each direction */
/* Cleanup any existing compression */
- if (session->local.comp && session->local.comp->dtor) {
+ if(session->local.comp && session->local.comp->dtor) {
session->local.comp->dtor(session, 1,
&session->local.comp_abstract);
}
- if (session->local.comp && session->local.comp->init) {
- if (session->local.comp->init(session, 1,
+ if(session->local.comp && session->local.comp->init) {
+ if(session->local.comp->init(session, 1,
&session->local.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
@@ -1315,13 +1448,13 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Client to Server compression initialized");
- if (session->remote.comp && session->remote.comp->dtor) {
+ if(session->remote.comp && session->remote.comp->dtor) {
session->remote.comp->dtor(session, 0,
&session->remote.comp_abstract);
}
- if (session->remote.comp && session->remote.comp->init) {
- if (session->remote.comp->init(session, 0,
+ if(session->remote.comp && session->remote.comp->init) {
+ if(session->remote.comp->init(session, 0,
&session->remote.comp_abstract)) {
ret = LIBSSH2_ERROR_KEX_FAILURE;
goto clean_exit;
@@ -1333,8 +1466,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
}
clean_exit:
- _libssh2_bn_free(exchange_state->x);
- exchange_state->x = NULL;
+ libssh2_dh_dtor(&exchange_state->x);
_libssh2_bn_free(exchange_state->e);
exchange_state->e = NULL;
_libssh2_bn_free(exchange_state->f);
@@ -1344,17 +1476,17 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
_libssh2_bn_ctx_free(exchange_state->ctx);
exchange_state->ctx = NULL;
- if (exchange_state->e_packet) {
+ if(exchange_state->e_packet) {
LIBSSH2_FREE(session, exchange_state->e_packet);
exchange_state->e_packet = NULL;
}
- if (exchange_state->s_packet) {
+ if(exchange_state->s_packet) {
LIBSSH2_FREE(session, exchange_state->s_packet);
exchange_state->s_packet = NULL;
}
- if (exchange_state->k_value) {
+ if(exchange_state->k_value) {
LIBSSH2_FREE(session, exchange_state->k_value);
exchange_state->k_value = NULL;
}
@@ -1395,9 +1527,10 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
int ret;
- if (key_state->state == libssh2_NB_state_idle) {
+ if(key_state->state == libssh2_NB_state_idle) {
/* g == 2 */
- key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value (p_value) */
+ key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
+ (p_value) */
key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
/* Initialize P and G */
@@ -1412,7 +1545,7 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128,
SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
NULL, 0, &key_state->exchange_state);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -1471,8 +1604,9 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
};
int ret;
- if (key_state->state == libssh2_NB_state_idle) {
- key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value (p_value) */
+ if(key_state->state == libssh2_NB_state_idle) {
+ key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
+ (p_value) */
key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
/* g == 2 */
@@ -1488,7 +1622,7 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
ret = diffie_hellman_sha1(session, key_state->g, key_state->p,
256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
NULL, 0, &key_state->exchange_state);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -1511,11 +1645,10 @@ static int
kex_method_diffie_hellman_group_exchange_sha1_key_exchange
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
{
- unsigned long p_len, g_len;
int ret = 0;
int rc;
- if (key_state->state == libssh2_NB_state_idle) {
+ if(key_state->state == libssh2_NB_state_idle) {
key_state->p = _libssh2_bn_init_from_bin();
key_state->g = _libssh2_bn_init_from_bin();
/* Ask for a P and G pair */
@@ -1526,24 +1659,27 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
_libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
key_state->request_len = 13;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Initiating Diffie-Hellman Group-Exchange (New Method)");
+ "Initiating Diffie-Hellman Group-Exchange "
+ "(New Method)");
#else
key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
_libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
key_state->request_len = 5;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Initiating Diffie-Hellman Group-Exchange (Old Method)");
+ "Initiating Diffie-Hellman Group-Exchange "
+ "(Old Method)");
#endif
key_state->state = libssh2_NB_state_created;
}
- if (key_state->state == libssh2_NB_state_created) {
+ if(key_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, key_state->request,
key_state->request_len, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Unable to send Group Exchange Request");
goto dh_gex_clean_exit;
@@ -1552,13 +1688,14 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
key_state->state = libssh2_NB_state_sent;
}
- if (key_state->state == libssh2_NB_state_sent) {
+ if(key_state->state == libssh2_NB_state_sent) {
rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
&key_state->data, &key_state->data_len,
0, NULL, 0, &key_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Timeout waiting for GEX_GROUP reply");
goto dh_gex_clean_exit;
@@ -1567,16 +1704,37 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
key_state->state = libssh2_NB_state_sent1;
}
- if (key_state->state == libssh2_NB_state_sent1) {
- unsigned char *s = key_state->data + 1;
- p_len = _libssh2_ntohu32(s);
- s += 4;
- _libssh2_bn_from_bin(key_state->p, p_len, s);
- s += p_len;
+ if(key_state->state == libssh2_NB_state_sent1) {
+ size_t p_len, g_len;
+ unsigned char *p, *g;
+ struct string_buf buf;
- g_len = _libssh2_ntohu32(s);
- s += 4;
- _libssh2_bn_from_bin(key_state->g, g_len, s);
+ if(key_state->data_len < 9) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto dh_gex_clean_exit;
+ }
+
+ buf.data = key_state->data;
+ buf.dataptr = buf.data;
+ buf.len = key_state->data_len;
+
+ buf.dataptr++; /* increment to big num */
+
+ if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected value");
+ goto dh_gex_clean_exit;
+ }
+
+ if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected value");
+ 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);
ret = diffie_hellman_sha1(session, key_state->g, key_state->p, p_len,
SSH_MSG_KEX_DH_GEX_INIT,
@@ -1584,7 +1742,7 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange
key_state->data + 1,
key_state->data_len - 1,
&key_state->exchange_state);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -1611,11 +1769,10 @@ static int
kex_method_diffie_hellman_group_exchange_sha256_key_exchange
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
{
- unsigned long p_len, g_len;
int ret = 0;
int rc;
- if (key_state->state == libssh2_NB_state_idle) {
+ if(key_state->state == libssh2_NB_state_idle) {
key_state->p = _libssh2_bn_init();
key_state->g = _libssh2_bn_init();
/* Ask for a P and G pair */
@@ -1626,39 +1783,44 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange
_libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
key_state->request_len = 13;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Initiating Diffie-Hellman Group-Exchange (New Method SHA256)");
+ "Initiating Diffie-Hellman Group-Exchange "
+ "(New Method SHA256)");
#else
key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
_libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
key_state->request_len = 5;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Initiating Diffie-Hellman Group-Exchange (Old Method SHA256)");
+ "Initiating Diffie-Hellman Group-Exchange "
+ "(Old Method SHA256)");
#endif
key_state->state = libssh2_NB_state_created;
}
- if (key_state->state == libssh2_NB_state_created) {
+ if(key_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, key_state->request,
key_state->request_len, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
- "Unable to send Group Exchange Request SHA256");
+ "Unable to send "
+ "Group Exchange Request SHA256");
goto dh_gex_clean_exit;
}
key_state->state = libssh2_NB_state_sent;
}
- if (key_state->state == libssh2_NB_state_sent) {
+ if(key_state->state == libssh2_NB_state_sent) {
rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
&key_state->data, &key_state->data_len,
0, NULL, 0, &key_state->req_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
ret = _libssh2_error(session, rc,
"Timeout waiting for GEX_GROUP reply SHA256");
goto dh_gex_clean_exit;
@@ -1667,16 +1829,37 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange
key_state->state = libssh2_NB_state_sent1;
}
- if (key_state->state == libssh2_NB_state_sent1) {
- unsigned char *s = key_state->data + 1;
- p_len = _libssh2_ntohu32(s);
- s += 4;
- _libssh2_bn_from_bin(key_state->p, p_len, s);
- s += p_len;
+ if(key_state->state == libssh2_NB_state_sent1) {
+ unsigned char *p, *g;
+ size_t p_len, g_len;
+ struct string_buf buf;
- g_len = _libssh2_ntohu32(s);
- s += 4;
- _libssh2_bn_from_bin(key_state->g, g_len, s);
+ if(key_state->data_len < 9) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto dh_gex_clean_exit;
+ }
+
+ buf.data = key_state->data;
+ buf.dataptr = buf.data;
+ buf.len = key_state->data_len;
+
+ buf.dataptr++; /* increment to big num */
+
+ if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected value");
+ goto dh_gex_clean_exit;
+ }
+
+ if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected value");
+ 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);
ret = diffie_hellman_sha256(session, key_state->g, key_state->p, p_len,
SSH_MSG_KEX_DH_GEX_INIT,
@@ -1684,7 +1867,7 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange
key_state->data + 1,
key_state->data_len - 1,
&key_state->exchange_state);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
@@ -1702,6 +1885,1369 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange
}
+#if LIBSSH2_ECDSA
+
+/* kex_session_ecdh_curve_type
+ * returns the EC curve type by name used in key exchange
+ */
+
+static int
+kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type)
+{
+ int ret = 0;
+ libssh2_curve_type type;
+
+ if(name == NULL)
+ return -1;
+
+ if(strcmp(name, "ecdh-sha2-nistp256") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP256;
+ else if(strcmp(name, "ecdh-sha2-nistp384") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP384;
+ else if(strcmp(name, "ecdh-sha2-nistp521") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP521;
+ else {
+ ret = -1;
+ }
+
+ if(ret == 0 && out_type) {
+ *out_type = type;
+ }
+
+ return ret;
+}
+
+
+/* LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY
+ *
+ * Macro that create and verifies EC SHA hash with a given digest bytes
+ *
+ * Payload format:
+ *
+ * string V_C, client's identification string (CR and LF excluded)
+ * string V_S, server's identification string (CR and LF excluded)
+ * string I_C, payload of the client's SSH_MSG_KEXINIT
+ * string I_S, payload of the server's SSH_MSG_KEXINIT
+ * string K_S, server's public host key
+ * string Q_C, client's ephemeral public key octet string
+ * string Q_S, server's ephemeral public key octet string
+ * mpint K, shared secret
+ *
+ */
+
+#define LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(digest_type) \
+{ \
+ libssh2_sha##digest_type##_ctx ctx; \
+ exchange_state->exchange_hash = (void *)&ctx; \
+ libssh2_sha##digest_type##_init(&ctx); \
+ if(session->local.banner) { \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ 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); \
+ } \
+ else { \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); \
+ libssh2_sha##digest_type##_update(ctx, \
+ exchange_state->h_sig_comp, 4); \
+ libssh2_sha##digest_type##_update(ctx, \
+ LIBSSH2_SSH_DEFAULT_BANNER, \
+ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) \
+ - 1); \
+ } \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ 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)); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ 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); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ 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); \
+ \
+ _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); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ 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); \
+ \
+ _libssh2_htonu32(exchange_state->h_sig_comp, \
+ 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); \
+ \
+ 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(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)) { \
+ rc = -1; \
+ } \
+} \
+
+
+/* ecdh_sha2_nistp
+ * Elliptic Curve Diffie Hellman Key Exchange
+ */
+
+static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type,
+ unsigned char *data, size_t data_len,
+ unsigned char *public_key,
+ size_t public_key_len, _libssh2_ec_key *private_key,
+ kmdhgGPshakex_state_t *exchange_state)
+{
+ int ret = 0;
+ int rc;
+
+ if(data_len < 5) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Host key data is too short");
+ return ret;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_idle) {
+
+ /* Setup initial values */
+ exchange_state->k = _libssh2_bn_init();
+
+ exchange_state->state = libssh2_NB_state_created;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_created) {
+ /* parse INIT reply data */
+
+ /* host key K_S */
+ unsigned char *s = data + 1; /* Advance past packet type */
+ unsigned char *server_public_key;
+ size_t server_public_key_len;
+ size_t host_sig_len;
+
+ session->server_hostkey_len =
+ _libssh2_ntohu32((const unsigned char *)s);
+ s += 4;
+
+ session->server_hostkey = LIBSSH2_ALLOC(session,
+ session->server_hostkey_len);
+ if(!session->server_hostkey) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for a copy "
+ "of the host key");
+ goto clean_exit;
+ }
+
+ memcpy(session->server_hostkey, s, session->server_hostkey_len);
+ s += session->server_hostkey_len;
+
+#if LIBSSH2_MD5
+ {
+ 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);
+ session->server_hostkey_md5_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_md5_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char fingerprint[50], *fprint = fingerprint;
+ int i;
+ for(i = 0; i < 16; i++, fprint += 3) {
+ snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
+ }
+ *(--fprint) = '\0';
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's MD5 Fingerprint: %s", fingerprint);
+ }
+#endif /* LIBSSH2DEBUG */
+#endif /* ! LIBSSH2_MD5 */
+
+ {
+ 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);
+ session->server_hostkey_sha1_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha1_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char fingerprint[64], *fprint = fingerprint;
+ int i;
+
+ for(i = 0; i < 20; i++, fprint += 3) {
+ snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
+ }
+ *(--fprint) = '\0';
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA1 Fingerprint: %s", fingerprint);
+ }
+#endif /* LIBSSH2DEBUG */
+
+ /* SHA256 */
+ {
+ 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);
+ session->server_hostkey_sha256_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha256_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char *base64Fingerprint = NULL;
+ _libssh2_base64_encode(session,
+ (const char *)
+ session->server_hostkey_sha256,
+ SHA256_DIGEST_LENGTH, &base64Fingerprint);
+ if(base64Fingerprint != NULL) {
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA256 Fingerprint: %s",
+ base64Fingerprint);
+ LIBSSH2_FREE(session, base64Fingerprint);
+ }
+ }
+#endif /* LIBSSH2DEBUG */
+
+ if(session->hostkey->init(session, session->server_hostkey,
+ session->server_hostkey_len,
+ &session->server_hostkey_abstract)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to initialize hostkey importer");
+ goto clean_exit;
+ }
+
+ /* server public key Q_S */
+ server_public_key_len = _libssh2_ntohu32((const unsigned char *)s);
+ s += 4;
+
+ server_public_key = s;
+ s += server_public_key_len;
+
+ /* server signature */
+ host_sig_len = _libssh2_ntohu32((const unsigned char *)s);
+ s += 4;
+
+ exchange_state->h_sig = s;
+ exchange_state->h_sig_len = host_sig_len;
+ s += host_sig_len;
+
+ /* Compute the shared secret K */
+ rc = _libssh2_ecdh_gen_k(&exchange_state->k, private_key,
+ server_public_key, server_public_key_len);
+ if(rc != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+ "Unable to create ECDH shared secret");
+ goto clean_exit;
+ }
+
+ exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
+ /* don't need leading 00 */
+ exchange_state->k_value_len--;
+ }
+ exchange_state->k_value =
+ LIBSSH2_ALLOC(session, exchange_state->k_value_len);
+ if(!exchange_state->k_value) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate buffer for K");
+ goto clean_exit;
+ }
+ _libssh2_htonu32(exchange_state->k_value,
+ 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);
+ }
+ else {
+ exchange_state->k_value[4] = 0;
+ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+ }
+
+ /* verify hash */
+
+ switch(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;
+ case LIBSSH2_EC_CURVE_NISTP521:
+ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(512);
+ break;
+ }
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
+ "Unable to verify hostkey signature");
+ goto clean_exit;
+ }
+
+ exchange_state->c = SSH_MSG_NEWKEYS;
+ exchange_state->state = libssh2_NB_state_sent;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_sent) {
+ rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send NEWKEYS message");
+ goto clean_exit;
+ }
+
+ exchange_state->state = libssh2_NB_state_sent2;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_sent2) {
+ rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
+ &exchange_state->tmp,
+ &exchange_state->tmp_len, 0, NULL, 0,
+ &exchange_state->req_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
+ goto clean_exit;
+ }
+
+ /* The first key exchange has been performed,
+ switch to active crypt/comp/mac mode */
+ session->state |= LIBSSH2_STATE_NEWKEYS;
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
+
+ /* This will actually end up being just packet_type(1)
+ for this packet type anyway */
+ LIBSSH2_FREE(session, exchange_state->tmp);
+
+ if(!session->session_id) {
+
+ size_t digest_length = 0;
+
+ if(type == LIBSSH2_EC_CURVE_NISTP256)
+ digest_length = SHA256_DIGEST_LENGTH;
+ else if(type == LIBSSH2_EC_CURVE_NISTP384)
+ digest_length = SHA384_DIGEST_LENGTH;
+ else if(type == LIBSSH2_EC_CURVE_NISTP521)
+ digest_length = SHA512_DIGEST_LENGTH;
+ else{
+ ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+ "Unknown SHA digest for EC curve");
+ goto clean_exit;
+
+ }
+ session->session_id = LIBSSH2_ALLOC(session, digest_length);
+ if(!session->session_id) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate buffer for "
+ "SHA digest");
+ goto clean_exit;
+ }
+ memcpy(session->session_id, exchange_state->h_sig_comp,
+ digest_length);
+ session->session_id_len = digest_length;
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "session_id calculated");
+ }
+
+ /* Cleanup any existing cipher */
+ if(session->local.crypt->dtor) {
+ session->local.crypt->dtor(session,
+ &session->local.crypt_abstract);
+ }
+
+ /* Calculate IV/Secret/Key for each direction */
+ if(session->local.crypt->init) {
+ unsigned char *iv = NULL, *secret = NULL;
+ int free_iv = 0, free_secret = 0;
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv,
+ session->local.crypt->
+ iv_len, "A");
+ if(!iv) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret,
+ session->local.crypt->
+ secret_len, "C");
+
+ if(!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ if(session->local.crypt->
+ init(session, session->local.crypt, iv, &free_iv, secret,
+ &free_secret, 1, &session->local.crypt_abstract)) {
+ LIBSSH2_FREE(session, iv);
+ LIBSSH2_FREE(session, secret);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
+ LIBSSH2_FREE(session, iv);
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->local.crypt->secret_len);
+ LIBSSH2_FREE(session, secret);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server IV and Key calculated");
+
+ if(session->remote.crypt->dtor) {
+ /* Cleanup any existing cipher */
+ session->remote.crypt->dtor(session,
+ &session->remote.crypt_abstract);
+ }
+
+ if(session->remote.crypt->init) {
+ unsigned char *iv = NULL, *secret = NULL;
+ int free_iv = 0, free_secret = 0;
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv,
+ session->remote.crypt->
+ iv_len, "B");
+
+ if(!iv) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret,
+ session->remote.crypt->
+ secret_len, "D");
+
+ if(!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ if(session->remote.crypt->
+ init(session, session->remote.crypt, iv, &free_iv, secret,
+ &free_secret, 0, &session->remote.crypt_abstract)) {
+ LIBSSH2_FREE(session, iv);
+ LIBSSH2_FREE(session, secret);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
+ LIBSSH2_FREE(session, iv);
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->remote.crypt->secret_len);
+ LIBSSH2_FREE(session, secret);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client IV and Key calculated");
+
+ if(session->local.mac->dtor) {
+ session->local.mac->dtor(session, &session->local.mac_abstract);
+ }
+
+ if(session->local.mac->init) {
+ unsigned char *key = NULL;
+ int free_key = 0;
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key,
+ session->local.mac->
+ key_len, "E");
+
+ if(!key) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ session->local.mac->init(session, key, &free_key,
+ &session->local.mac_abstract);
+
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->local.mac->key_len);
+ LIBSSH2_FREE(session, key);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server HMAC Key calculated");
+
+ if(session->remote.mac->dtor) {
+ session->remote.mac->dtor(session, &session->remote.mac_abstract);
+ }
+
+ if(session->remote.mac->init) {
+ unsigned char *key = NULL;
+ int free_key = 0;
+
+ LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key,
+ session->remote.mac->
+ key_len, "F");
+
+ if(!key) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ session->remote.mac->init(session, key, &free_key,
+ &session->remote.mac_abstract);
+
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->remote.mac->key_len);
+ LIBSSH2_FREE(session, key);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client HMAC Key calculated");
+
+ /* Initialize compression for each direction */
+
+ /* Cleanup any existing compression */
+ if(session->local.comp && session->local.comp->dtor) {
+ session->local.comp->dtor(session, 1,
+ &session->local.comp_abstract);
+ }
+
+ if(session->local.comp && session->local.comp->init) {
+ if(session->local.comp->init(session, 1,
+ &session->local.comp_abstract)) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server compression initialized");
+
+ if(session->remote.comp && session->remote.comp->dtor) {
+ session->remote.comp->dtor(session, 0,
+ &session->remote.comp_abstract);
+ }
+
+ if(session->remote.comp && session->remote.comp->init) {
+ if(session->remote.comp->init(session, 0,
+ &session->remote.comp_abstract)) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client compression initialized");
+
+ }
+
+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;
+
+ return ret;
+}
+
+/* kex_method_ecdh_key_exchange
+ *
+ * Elliptic Curve Diffie Hellman Key Exchange
+ * supports SHA256/384/512 hashes based on negotated ecdh method
+ *
+ */
+
+static int
+kex_method_ecdh_key_exchange
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+ int ret = 0;
+ int rc = 0;
+ unsigned char *s;
+ libssh2_curve_type type;
+
+ if(key_state->state == libssh2_NB_state_idle) {
+
+ key_state->public_key_oct = NULL;
+ key_state->state = libssh2_NB_state_created;
+ }
+
+ if(key_state->state == libssh2_NB_state_created) {
+ rc = kex_session_ecdh_curve_type(session->kex->name, &type);
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, -1,
+ "Unknown KEX nistp curve type");
+ goto ecdh_clean_exit;
+ }
+
+ rc = _libssh2_ecdsa_create_key(session, &key_state->private_key,
+ &key_state->public_key_oct,
+ &key_state->public_key_oct_len, type);
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, rc,
+ "Unable to create private key");
+ goto ecdh_clean_exit;
+ }
+
+ key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT;
+ s = key_state->request + 1;
+ _libssh2_store_str(&s, (const char *)key_state->public_key_oct,
+ key_state->public_key_oct_len);
+ key_state->request_len = key_state->public_key_oct_len + 5;
+
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Initiating ECDH SHA2 NISTP256");
+
+ key_state->state = libssh2_NB_state_sent;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent) {
+ rc = _libssh2_transport_send(session, key_state->request,
+ key_state->request_len, NULL, 0);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send ECDH_INIT");
+ goto ecdh_clean_exit;
+ }
+
+ key_state->state = libssh2_NB_state_sent1;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent1) {
+ rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY,
+ &key_state->data, &key_state->data_len,
+ 0, NULL, 0, &key_state->req_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Timeout waiting for ECDH_REPLY reply");
+ goto ecdh_clean_exit;
+ }
+
+ key_state->state = libssh2_NB_state_sent2;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent2) {
+
+ (void)kex_session_ecdh_curve_type(session->kex->name, &type);
+
+ ret = ecdh_sha2_nistp(session, type, key_state->data,
+ key_state->data_len,
+ (unsigned char *)key_state->public_key_oct,
+ key_state->public_key_oct_len,
+ key_state->private_key,
+ &key_state->exchange_state);
+
+ 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;
+
+ return ret;
+}
+
+#endif /*LIBSSH2_ECDSA*/
+
+
+#if LIBSSH2_ED25519
+
+/* curve25519_sha256
+ * Elliptic Curve Key Exchange
+ */
+
+static int
+curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data,
+ size_t data_len,
+ unsigned char public_key[LIBSSH2_ED25519_KEY_LEN],
+ unsigned char private_key[LIBSSH2_ED25519_KEY_LEN],
+ kmdhgGPshakex_state_t *exchange_state)
+{
+ int ret = 0;
+ int rc;
+ int public_key_len = LIBSSH2_ED25519_KEY_LEN;
+
+ if(data_len < 5) {
+ return _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Data is too short");
+ }
+
+ if(exchange_state->state == libssh2_NB_state_idle) {
+
+ /* Setup initial values */
+ exchange_state->k = _libssh2_bn_init();
+
+ exchange_state->state = libssh2_NB_state_created;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_created) {
+ /* parse INIT reply data */
+ unsigned char *server_public_key, *server_host_key;
+ size_t server_public_key_len, hostkey_len;
+ struct string_buf buf;
+
+ if(data_len < 5) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto clean_exit;
+ }
+
+ buf.data = data;
+ buf.len = data_len;
+ buf.dataptr = buf.data;
+ buf.dataptr++; /* advance past packet type */
+
+ if(_libssh2_get_string(&buf, &server_host_key, &hostkey_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto clean_exit;
+ }
+
+ session->server_hostkey_len = (uint32_t)hostkey_len;
+ session->server_hostkey = LIBSSH2_ALLOC(session,
+ session->server_hostkey_len);
+ if(!session->server_hostkey) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for a copy "
+ "of the host key");
+ goto clean_exit;
+ }
+
+ memcpy(session->server_hostkey, server_host_key,
+ session->server_hostkey_len);
+
+#if LIBSSH2_MD5
+ {
+ 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);
+ session->server_hostkey_md5_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_md5_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char fingerprint[50], *fprint = fingerprint;
+ int i;
+ for(i = 0; i < 16; i++, fprint += 3) {
+ snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
+ }
+ *(--fprint) = '\0';
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's MD5 Fingerprint: %s", fingerprint);
+ }
+#endif /* LIBSSH2DEBUG */
+#endif /* ! LIBSSH2_MD5 */
+
+ {
+ 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);
+ session->server_hostkey_sha1_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha1_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char fingerprint[64], *fprint = fingerprint;
+ int i;
+
+ for(i = 0; i < 20; i++, fprint += 3) {
+ snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
+ }
+ *(--fprint) = '\0';
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA1 Fingerprint: %s", fingerprint);
+ }
+#endif /* LIBSSH2DEBUG */
+
+ /* SHA256 */
+ {
+ 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);
+ session->server_hostkey_sha256_valid = TRUE;
+ }
+ else {
+ session->server_hostkey_sha256_valid = FALSE;
+ }
+ }
+#ifdef LIBSSH2DEBUG
+ {
+ char *base64Fingerprint = NULL;
+ _libssh2_base64_encode(session,
+ (const char *)
+ session->server_hostkey_sha256,
+ SHA256_DIGEST_LENGTH, &base64Fingerprint);
+ if(base64Fingerprint != NULL) {
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server's SHA256 Fingerprint: %s",
+ base64Fingerprint);
+ LIBSSH2_FREE(session, base64Fingerprint);
+ }
+ }
+#endif /* LIBSSH2DEBUG */
+
+ if(session->hostkey->init(session, session->server_hostkey,
+ session->server_hostkey_len,
+ &session->server_hostkey_abstract)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unable to initialize hostkey importer");
+ goto clean_exit;
+ }
+
+ /* server public key Q_S */
+ if(_libssh2_get_string(&buf, &server_public_key,
+ &server_public_key_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unexpected key length");
+ goto clean_exit;
+ }
+
+ if(server_public_key_len != LIBSSH2_ED25519_KEY_LEN) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unexpected curve25519 server "
+ "public key length");
+ goto clean_exit;
+ }
+
+ /* server signature */
+ if(_libssh2_get_string(&buf, &exchange_state->h_sig,
+ &(exchange_state->h_sig_len))) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
+ "Unexpected curve25519 server sig length");
+ goto clean_exit;
+ }
+
+ /* Compute the shared secret K */
+ rc = _libssh2_curve25519_gen_k(&exchange_state->k, private_key,
+ server_public_key);
+ if(rc != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
+ "Unable to create ECDH shared secret");
+ goto clean_exit;
+ }
+
+ exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
+ if(_libssh2_bn_bits(exchange_state->k) % 8) {
+ /* don't need leading 00 */
+ exchange_state->k_value_len--;
+ }
+ exchange_state->k_value =
+ LIBSSH2_ALLOC(session, exchange_state->k_value_len);
+ if(!exchange_state->k_value) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate buffer for K");
+ goto clean_exit;
+ }
+ _libssh2_htonu32(exchange_state->k_value,
+ 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);
+ }
+ else {
+ exchange_state->k_value[4] = 0;
+ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
+ }
+
+ /*/ verify hash */
+ LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256);
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
+ "Unable to verify hostkey signature");
+ goto clean_exit;
+ }
+
+ exchange_state->c = SSH_MSG_NEWKEYS;
+ exchange_state->state = libssh2_NB_state_sent;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_sent) {
+ rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send NEWKEYS message");
+ goto clean_exit;
+ }
+
+ exchange_state->state = libssh2_NB_state_sent2;
+ }
+
+ if(exchange_state->state == libssh2_NB_state_sent2) {
+ rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
+ &exchange_state->tmp,
+ &exchange_state->tmp_len, 0, NULL, 0,
+ &exchange_state->req_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS");
+ goto clean_exit;
+ }
+
+ /* The first key exchange has been performed, switch to active
+ crypt/comp/mac mode */
+
+ session->state |= LIBSSH2_STATE_NEWKEYS;
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message");
+
+ /* This will actually end up being just packet_type(1) for this packet
+ type anyway */
+ LIBSSH2_FREE(session, exchange_state->tmp);
+
+ if(!session->session_id) {
+
+ size_t digest_length = SHA256_DIGEST_LENGTH;
+ session->session_id = LIBSSH2_ALLOC(session, digest_length);
+ if(!session->session_id) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allxcocate buffer for "
+ "SHA digest");
+ goto clean_exit;
+ }
+ memcpy(session->session_id, exchange_state->h_sig_comp,
+ digest_length);
+ session->session_id_len = digest_length;
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "session_id calculated");
+ }
+
+ /* Cleanup any existing cipher */
+ if(session->local.crypt->dtor) {
+ session->local.crypt->dtor(session,
+ &session->local.crypt_abstract);
+ }
+
+ /* Calculate IV/Secret/Key for each direction */
+ if(session->local.crypt->init) {
+ unsigned char *iv = NULL, *secret = NULL;
+ int free_iv = 0, free_secret = 0;
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+ session->local.crypt->
+ iv_len, "A");
+ if(!iv) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+ session->local.crypt->
+ secret_len, "C");
+
+ if(!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ if(session->local.crypt->
+ init(session, session->local.crypt, iv, &free_iv, secret,
+ &free_secret, 1, &session->local.crypt_abstract)) {
+ LIBSSH2_FREE(session, iv);
+ LIBSSH2_FREE(session, secret);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
+ LIBSSH2_FREE(session, iv);
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->local.crypt->secret_len);
+ LIBSSH2_FREE(session, secret);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server IV and Key calculated");
+
+ if(session->remote.crypt->dtor) {
+ /* Cleanup any existing cipher */
+ session->remote.crypt->dtor(session,
+ &session->remote.crypt_abstract);
+ }
+
+ if(session->remote.crypt->init) {
+ unsigned char *iv = NULL, *secret = NULL;
+ int free_iv = 0, free_secret = 0;
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
+ session->remote.crypt->
+ iv_len, "B");
+
+ if(!iv) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
+ session->remote.crypt->
+ secret_len, "D");
+
+ if(!secret) {
+ LIBSSH2_FREE(session, iv);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ if(session->remote.crypt->
+ init(session, session->remote.crypt, iv, &free_iv, secret,
+ &free_secret, 0, &session->remote.crypt_abstract)) {
+ LIBSSH2_FREE(session, iv);
+ LIBSSH2_FREE(session, secret);
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+
+ if(free_iv) {
+ _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
+ LIBSSH2_FREE(session, iv);
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero(secret,
+ session->remote.crypt->secret_len);
+ LIBSSH2_FREE(session, secret);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client IV and Key calculated");
+
+ if(session->local.mac->dtor) {
+ session->local.mac->dtor(session, &session->local.mac_abstract);
+ }
+
+ if(session->local.mac->init) {
+ unsigned char *key = NULL;
+ int free_key = 0;
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+ session->local.mac->
+ key_len, "E");
+
+ if(!key) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ session->local.mac->init(session, key, &free_key,
+ &session->local.mac_abstract);
+
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->local.mac->key_len);
+ LIBSSH2_FREE(session, key);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server HMAC Key calculated");
+
+ if(session->remote.mac->dtor) {
+ session->remote.mac->dtor(session, &session->remote.mac_abstract);
+ }
+
+ if(session->remote.mac->init) {
+ unsigned char *key = NULL;
+ int free_key = 0;
+
+ LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
+ session->remote.mac->
+ key_len, "F");
+
+ if(!key) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ session->remote.mac->init(session, key, &free_key,
+ &session->remote.mac_abstract);
+
+ if(free_key) {
+ _libssh2_explicit_zero(key, session->remote.mac->key_len);
+ LIBSSH2_FREE(session, key);
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client HMAC Key calculated");
+
+ /* Initialize compression for each direction */
+
+ /* Cleanup any existing compression */
+ if(session->local.comp && session->local.comp->dtor) {
+ session->local.comp->dtor(session, 1,
+ &session->local.comp_abstract);
+ }
+
+ if(session->local.comp && session->local.comp->init) {
+ if(session->local.comp->init(session, 1,
+ &session->local.comp_abstract)) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Client to Server compression initialized");
+
+ if(session->remote.comp && session->remote.comp->dtor) {
+ session->remote.comp->dtor(session, 0,
+ &session->remote.comp_abstract);
+ }
+
+ if(session->remote.comp && session->remote.comp->init) {
+ if(session->remote.comp->init(session, 0,
+ &session->remote.comp_abstract)) {
+ ret = LIBSSH2_ERROR_KEX_FAILURE;
+ goto clean_exit;
+ }
+ }
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Server to Client compression initialized");
+ }
+
+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;
+
+ return ret;
+}
+
+/* kex_method_curve25519_key_exchange
+ *
+ * Elliptic Curve X25519 Key Exchange with SHA256 hash
+ *
+ */
+
+static int
+kex_method_curve25519_key_exchange
+(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
+{
+ int ret = 0;
+ int rc = 0;
+
+ if(key_state->state == libssh2_NB_state_idle) {
+
+ key_state->public_key_oct = NULL;
+ key_state->state = libssh2_NB_state_created;
+ }
+
+ if(key_state->state == libssh2_NB_state_created) {
+ unsigned char *s = NULL;
+
+ rc = strcmp(session->kex->name, "curve25519-sha256@libssh.org");
+ if(rc != 0)
+ rc = strcmp(session->kex->name, "curve25519-sha256");
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, -1,
+ "Unknown KEX curve25519 curve type");
+ goto clean_exit;
+ }
+
+ rc = _libssh2_curve25519_new(session, NULL,
+ &key_state->curve25519_public_key,
+ &key_state->curve25519_private_key);
+
+ if(rc != 0) {
+ ret = _libssh2_error(session, rc,
+ "Unable to create private key");
+ goto clean_exit;
+ }
+
+ key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT;
+ s = key_state->request + 1;
+ _libssh2_store_str(&s, (const char *)key_state->curve25519_public_key,
+ LIBSSH2_ED25519_KEY_LEN);
+ key_state->request_len = LIBSSH2_ED25519_KEY_LEN + 5;
+
+ _libssh2_debug(session, LIBSSH2_TRACE_KEX,
+ "Initiating curve25519 SHA2");
+
+ key_state->state = libssh2_NB_state_sent;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent) {
+ rc = _libssh2_transport_send(session, key_state->request,
+ key_state->request_len, NULL, 0);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Unable to send ECDH_INIT");
+ goto clean_exit;
+ }
+
+ key_state->state = libssh2_NB_state_sent1;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent1) {
+ rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY,
+ &key_state->data, &key_state->data_len,
+ 0, NULL, 0, &key_state->req_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return rc;
+ }
+ else if(rc) {
+ ret = _libssh2_error(session, rc,
+ "Timeout waiting for ECDH_REPLY reply");
+ goto clean_exit;
+ }
+
+ key_state->state = libssh2_NB_state_sent2;
+ }
+
+ if(key_state->state == libssh2_NB_state_sent2) {
+
+ ret = curve25519_sha256(session, key_state->data, key_state->data_len,
+ key_state->curve25519_public_key,
+ key_state->curve25519_private_key,
+ &key_state->exchange_state);
+
+ 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;
+
+ return ret;
+}
+
+
+#endif /*LIBSSH2_ED25519*/
+
+
#define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY 0x0001
#define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY 0x0002
@@ -1731,7 +3277,54 @@ kex_method_diffie_helman_group_exchange_sha256 = {
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
+#if LIBSSH2_ECDSA
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp256 = {
+ "ecdh-sha2-nistp256",
+ kex_method_ecdh_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp384 = {
+ "ecdh-sha2-nistp384",
+ kex_method_ecdh_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+
+static const LIBSSH2_KEX_METHOD
+kex_method_ecdh_sha2_nistp521 = {
+ "ecdh-sha2-nistp521",
+ kex_method_ecdh_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+#endif
+
+#if LIBSSH2_ED25519
+static const LIBSSH2_KEX_METHOD
+kex_method_ssh_curve25519_sha256_libssh = {
+ "curve25519-sha256@libssh.org",
+ kex_method_curve25519_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+static const LIBSSH2_KEX_METHOD
+kex_method_ssh_curve25519_sha256 = {
+ "curve25519-sha256",
+ kex_method_curve25519_key_exchange,
+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
+};
+#endif
+
static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
+#if LIBSSH2_ECDSA
+ &kex_method_ecdh_sha2_nistp256,
+ &kex_method_ecdh_sha2_nistp384,
+ &kex_method_ecdh_sha2_nistp521,
+#endif
+#if LIBSSH2_ED25519
+ &kex_method_ssh_curve25519_sha256,
+ &kex_method_ssh_curve25519_sha256_libssh,
+#endif
&kex_method_diffie_helman_group_exchange_sha256,
&kex_method_diffie_helman_group_exchange_sha1,
&kex_method_diffie_helman_group14_sha1,
@@ -1746,7 +3339,8 @@ typedef struct _LIBSSH2_COMMON_METHOD
/* kex_method_strlen
* Calculate the length of a particular method list's resulting string
- * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1 (because the last coma isn't used)
+ * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1
+ * (because the last coma isn't used)
* Another sign of bad coding practices gone mad. Pretend you don't see this.
*/
static size_t
@@ -1754,11 +3348,11 @@ kex_method_strlen(LIBSSH2_COMMON_METHOD ** method)
{
size_t len = 0;
- if (!method || !*method) {
+ if(!method || !*method) {
return 0;
}
- while (*method && (*method)->name) {
+ while(*method && (*method)->name) {
len += strlen((*method)->name) + 1;
method++;
}
@@ -1778,11 +3372,11 @@ kex_method_list(unsigned char *buf, size_t list_strlen,
_libssh2_htonu32(buf, list_strlen);
buf += 4;
- if (!method || !*method) {
+ if(!method || !*method) {
return 4;
}
- while (*method && (*method)->name) {
+ while(*method && (*method)->name) {
int mlen = strlen((*method)->name);
memcpy(buf, (*method)->name, mlen);
buf += mlen;
@@ -1800,12 +3394,13 @@ kex_method_list(unsigned char *buf, size_t list_strlen,
kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar)))
#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \
- if (prefvar) { \
+ if(prefvar) { \
_libssh2_htonu32((buf), (prefvarlen)); \
buf += 4; \
memcpy((buf), (prefvar), (prefvarlen)); \
buf += (prefvarlen); \
- } else { \
+ } \
+ else { \
buf += kex_method_list((buf), (prefvarlen), \
(LIBSSH2_COMMON_METHOD**)(defaultvar)); \
}
@@ -1826,7 +3421,7 @@ static int kexinit(LIBSSH2_SESSION * session)
unsigned char *data, *s;
int rc;
- if (session->kexinit_state == libssh2_NB_state_idle) {
+ if(session->kexinit_state == libssh2_NB_state_idle) {
kex_len =
LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods);
hostkey_len =
@@ -1860,7 +3455,7 @@ static int kexinit(LIBSSH2_SESSION * session)
lang_cs_len + lang_sc_len;
s = data = LIBSSH2_ALLOC(session, data_len);
- if (!data) {
+ if(!data) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory");
}
@@ -1907,7 +3502,7 @@ static int kexinit(LIBSSH2_SESSION * session)
#ifdef LIBSSH2DEBUG
{
/* Funnily enough, they'll all "appear" to be '\0' terminated */
- unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */
+ unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */
_libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent KEX: %s", p);
p += kex_len + 4;
@@ -1933,7 +3528,8 @@ static int kexinit(LIBSSH2_SESSION * session)
#endif /* LIBSSH2DEBUG */
session->kexinit_state = libssh2_NB_state_created;
- } else {
+ }
+ else {
data = session->kexinit_data;
data_len = session->kexinit_data_len;
/* zap the variables to ensure there is NOT a double free later */
@@ -1942,12 +3538,12 @@ static int kexinit(LIBSSH2_SESSION * session)
}
rc = _libssh2_transport_send(session, data, data_len, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
session->kexinit_data = data;
session->kexinit_data_len = data_len;
return rc;
}
- else if (rc) {
+ else if(rc) {
LIBSSH2_FREE(session, data);
session->kexinit_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
@@ -1955,7 +3551,7 @@ static int kexinit(LIBSSH2_SESSION * session)
}
- if (session->local.kexinit) {
+ if(session->local.kexinit) {
LIBSSH2_FREE(session, session->local.kexinit);
}
@@ -1969,7 +3565,7 @@ static int kexinit(LIBSSH2_SESSION * session)
/* kex_agree_instr
* Kex specific variant of strstr()
- * Needle must be preceed by BOL or ',', and followed by ',' or EOL
+ * Needle must be precede by BOL or ',', and followed by ',' or EOL
*/
static unsigned char *
kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
@@ -1978,12 +3574,12 @@ kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
unsigned char *s;
/* Haystack too short to bother trying */
- if (haystack_len < needle_len) {
+ if(haystack_len < needle_len) {
return NULL;
}
/* Needle at start of haystack */
- if ((strncmp((char *) haystack, (char *) needle, needle_len) == 0) &&
+ if((strncmp((char *) haystack, (char *) needle, needle_len) == 0) &&
(needle_len == haystack_len || haystack[needle_len] == ',')) {
return haystack;
}
@@ -1991,11 +3587,11 @@ kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
s = haystack;
/* Search until we run out of comas or we run out of haystack,
whichever comes first */
- while ((s = (unsigned char *) strchr((char *) s, ','))
+ while((s = (unsigned char *) strchr((char *) s, ','))
&& ((haystack_len - (s - haystack)) > needle_len)) {
s++;
/* Needle at X position */
- if ((strncmp((char *) s, (char *) needle, needle_len) == 0) &&
+ if((strncmp((char *) s, (char *) needle, needle_len) == 0) &&
(((s - haystack) + needle_len) == haystack_len
|| s[needle_len] == ',')) {
return s;
@@ -2013,8 +3609,8 @@ static const LIBSSH2_COMMON_METHOD *
kex_get_method_by_name(const char *name, size_t name_len,
const LIBSSH2_COMMON_METHOD ** methodlist)
{
- while (*methodlist) {
- if ((strlen((*methodlist)->name) == name_len) &&
+ while(*methodlist) {
+ if((strlen((*methodlist)->name) == name_len) &&
(strncmp((*methodlist)->name, name, name_len) == 0)) {
return *methodlist;
}
@@ -2035,31 +3631,31 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
const LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods();
unsigned char *s;
- if (session->hostkey_prefs) {
+ if(session->hostkey_prefs) {
s = (unsigned char *) session->hostkey_prefs;
- while (s && *s) {
+ 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(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,
(const LIBSSH2_COMMON_METHOD **)
hostkeyp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
/* So far so good, but does it suit our purposes? (Encrypting
vs Signing) */
- if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) ==
+ if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) ==
0) || (method->encrypt)) {
/* Either this hostkey can do encryption or this kex just
doesn't require it */
- if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY)
+ if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY)
== 0) || (method->sig_verify)) {
/* Either this hostkey can do signing or this kex just
doesn't require it */
@@ -2074,18 +3670,18 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
return -1;
}
- while (hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
+ while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
s = kex_agree_instr(hostkey, hostkey_len,
(unsigned char *) (*hostkeyp)->name,
strlen((*hostkeyp)->name));
- if (s) {
+ if(s) {
/* So far so good, but does it suit our purposes? (Encrypting vs
Signing) */
- if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
+ if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
((*hostkeyp)->encrypt)) {
/* Either this hostkey can do encryption or this kex just
doesn't require it */
- if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) ==
+ if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) ==
0) || ((*hostkeyp)->sig_verify)) {
/* Either this hostkey can do signing or this kex just
doesn't require it */
@@ -2112,19 +3708,20 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
unsigned char *s;
- if (session->kex_prefs) {
+ if(session->kex_prefs) {
s = (unsigned char *) session->kex_prefs;
- while (s && *s) {
+ while(s && *s) {
unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
- if ((q = kex_agree_instr(kex, kex_len, s, method_len))) {
+ q = 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,
(const LIBSSH2_COMMON_METHOD **)
kexp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
@@ -2132,13 +3729,13 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
/* We've agreed on a key exchange method,
* Can we agree on a hostkey that works with this kex?
*/
- if (kex_agree_hostkey(session, method->flags, hostkey,
+ if(kex_agree_hostkey(session, method->flags, hostkey,
hostkey_len) == 0) {
session->kex = method;
- if (session->burn_optimistic_kexinit && (kex == q)) {
- /* Server sent an optimistic packet,
- * and client agrees with preference
- * cancel burning the first KEX_INIT packet that comes in */
+ if(session->burn_optimistic_kexinit && (kex == q)) {
+ /* Server sent an optimistic packet, and client agrees
+ * with preference cancel burning the first KEX_INIT
+ * packet that comes in */
session->burn_optimistic_kexinit = 0;
}
return 0;
@@ -2150,21 +3747,21 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
return -1;
}
- while (*kexp && (*kexp)->name) {
+ while(*kexp && (*kexp)->name) {
s = kex_agree_instr(kex, kex_len,
(unsigned char *) (*kexp)->name,
strlen((*kexp)->name));
- if (s) {
+ if(s) {
/* We've agreed on a key exchange method,
* Can we agree on a hostkey that works with this kex?
*/
- if (kex_agree_hostkey(session, (*kexp)->flags, hostkey,
+ if(kex_agree_hostkey(session, (*kexp)->flags, hostkey,
hostkey_len) == 0) {
session->kex = *kexp;
- if (session->burn_optimistic_kexinit && (kex == s)) {
- /* Server sent an optimistic packet,
- * and client agrees with preference
- * cancel burning the first KEX_INIT packet that comes in */
+ if(session->burn_optimistic_kexinit && (kex == s)) {
+ /* Server sent an optimistic packet, and client agrees
+ * with preference cancel burning the first KEX_INIT
+ * packet that comes in */
session->burn_optimistic_kexinit = 0;
}
return 0;
@@ -2190,21 +3787,21 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
(void) session;
- if (endpoint->crypt_prefs) {
+ if(endpoint->crypt_prefs) {
s = (unsigned char *) endpoint->crypt_prefs;
- while (s && *s) {
+ 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(crypt, crypt_len, s, method_len)) {
+ if(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,
(const LIBSSH2_COMMON_METHOD **)
cryptp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
@@ -2218,11 +3815,11 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
return -1;
}
- while (*cryptp && (*cryptp)->name) {
+ while(*cryptp && (*cryptp)->name) {
s = kex_agree_instr(crypt, crypt_len,
(unsigned char *) (*cryptp)->name,
strlen((*cryptp)->name));
- if (s) {
+ if(s) {
endpoint->crypt = *cryptp;
return 0;
}
@@ -2245,20 +3842,20 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
unsigned char *s;
(void) session;
- if (endpoint->mac_prefs) {
+ if(endpoint->mac_prefs) {
s = (unsigned char *) endpoint->mac_prefs;
- while (s && *s) {
+ 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(mac, mac_len, s, method_len)) {
+ if(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 **)
macp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
@@ -2272,10 +3869,10 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
return -1;
}
- while (*macp && (*macp)->name) {
+ while(*macp && (*macp)->name) {
s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name,
strlen((*macp)->name));
- if (s) {
+ if(s) {
endpoint->mac = *macp;
return 0;
}
@@ -2298,21 +3895,21 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
unsigned char *s;
(void) session;
- if (endpoint->comp_prefs) {
+ if(endpoint->comp_prefs) {
s = (unsigned char *) endpoint->comp_prefs;
- while (s && *s) {
+ 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(comp, comp_len, s, method_len)) {
+ if(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,
(const LIBSSH2_COMMON_METHOD **)
compp);
- if (!method) {
+ if(!method) {
/* Invalid method -- Should never be reached */
return -1;
}
@@ -2326,10 +3923,10 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
return -1;
}
- while (*compp && (*compp)->name) {
+ while(*compp && (*compp)->name) {
s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name,
strlen((*compp)->name));
- if (s) {
+ if(s) {
endpoint->comp = *compp;
return 0;
}
@@ -2360,7 +3957,7 @@ static int kex_string_pair(unsigned char **sp, /* parsing position */
/* the length of the string must fit within the current pointer and the
end of the packet */
- if (*lenp > (data_len - (s - data) -4))
+ if(*lenp > (data_len - (s - data) -4))
return 1;
*strp = s + 4;
s += 4 + *lenp;
@@ -2411,30 +4008,31 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
session->burn_optimistic_kexinit = *(s++);
/* Next uint32 in packet is all zeros (reserved) */
- if (data_len < (unsigned) (s - data))
+ if(data_len < (unsigned) (s - data))
return -1; /* short packet */
- if (kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
+ if(kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
return -1;
}
- if (kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len)
- || kex_agree_crypt(session, &session->remote, crypt_sc, crypt_sc_len)) {
+ if(kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len)
+ || kex_agree_crypt(session, &session->remote, crypt_sc,
+ crypt_sc_len)) {
return -1;
}
- if (kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) ||
+ if(kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) ||
kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) {
return -1;
}
- if (kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) ||
+ if(kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) ||
kex_agree_comp(session, &session->remote, comp_sc, comp_sc_len)) {
return -1;
}
#if 0
- if (libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
+ if(libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
|| libssh2_kex_agree_lang(session, &session->remote, lang_sc,
lang_sc_len)) {
return -1;
@@ -2478,14 +4076,14 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
session->state |= LIBSSH2_STATE_KEX_ACTIVE;
- if (key_state->state == libssh2_NB_state_idle) {
+ if(key_state->state == libssh2_NB_state_idle) {
/* Prevent loop in packet_add() */
session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
- if (reexchange) {
+ if(reexchange) {
session->kex = NULL;
- if (session->hostkey && session->hostkey->dtor) {
+ if(session->hostkey && session->hostkey->dtor) {
session->hostkey->dtor(session,
&session->server_hostkey_abstract);
}
@@ -2495,8 +4093,8 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_state->state = libssh2_NB_state_created;
}
- if (!session->kex || !session->hostkey) {
- if (key_state->state == libssh2_NB_state_created) {
+ if(!session->kex || !session->hostkey) {
+ if(key_state->state == libssh2_NB_state_created) {
/* Preserve in case of failure */
key_state->oldlocal = session->local.kexinit;
key_state->oldlocal_len = session->local.kexinit_len;
@@ -2506,12 +4104,13 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_state->state = libssh2_NB_state_sent;
}
- if (key_state->state == libssh2_NB_state_sent) {
+ if(key_state->state == libssh2_NB_state_sent) {
retcode = kexinit(session);
- if (retcode == LIBSSH2_ERROR_EAGAIN) {
+ if(retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
- } else if (retcode) {
+ }
+ else if(retcode) {
session->local.kexinit = key_state->oldlocal;
session->local.kexinit_len = key_state->oldlocal_len;
key_state->state = libssh2_NB_state_idle;
@@ -2523,18 +4122,18 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_state->state = libssh2_NB_state_sent1;
}
- if (key_state->state == libssh2_NB_state_sent1) {
+ if(key_state->state == libssh2_NB_state_sent1) {
retcode =
_libssh2_packet_require(session, SSH_MSG_KEXINIT,
&key_state->data,
&key_state->data_len, 0, NULL, 0,
&key_state->req_state);
- if (retcode == LIBSSH2_ERROR_EAGAIN) {
+ if(retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
}
- else if (retcode) {
- if (session->local.kexinit) {
+ else if(retcode) {
+ if(session->local.kexinit) {
LIBSSH2_FREE(session, session->local.kexinit);
}
session->local.kexinit = key_state->oldlocal;
@@ -2545,42 +4144,45 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
return -1;
}
- if (session->remote.kexinit) {
+ if(session->remote.kexinit) {
LIBSSH2_FREE(session, session->remote.kexinit);
}
session->remote.kexinit = key_state->data;
session->remote.kexinit_len = key_state->data_len;
- if (kex_agree_methods(session, key_state->data,
+ if(kex_agree_methods(session, key_state->data,
key_state->data_len))
rc = LIBSSH2_ERROR_KEX_FAILURE;
key_state->state = libssh2_NB_state_sent2;
}
- } else {
+ }
+ else {
key_state->state = libssh2_NB_state_sent2;
}
- if (rc == 0 && session->kex) {
- if (key_state->state == libssh2_NB_state_sent2) {
+ if(rc == 0 && session->kex) {
+ if(key_state->state == libssh2_NB_state_sent2) {
retcode = session->kex->exchange_keys(session,
&key_state->key_state_low);
- if (retcode == LIBSSH2_ERROR_EAGAIN) {
+ if(retcode == LIBSSH2_ERROR_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return retcode;
- } else if (retcode) {
- rc = _libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
+ }
+ else if(retcode) {
+ rc = _libssh2_error(session,
+ LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
"Unrecoverable error exchanging keys");
}
}
}
/* Done with kexinit buffers */
- if (session->local.kexinit) {
+ if(session->local.kexinit) {
LIBSSH2_FREE(session, session->local.kexinit);
session->local.kexinit = NULL;
}
- if (session->remote.kexinit) {
+ if(session->remote.kexinit) {
LIBSSH2_FREE(session, session->remote.kexinit);
session->remote.kexinit = NULL;
}
@@ -2606,7 +4208,7 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
int prefs_len = strlen(prefs);
const LIBSSH2_COMMON_METHOD **mlist;
- switch (method_type) {
+ switch(method_type) {
case LIBSSH2_METHOD_KEX:
prefvar = &session->kex_prefs;
mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
@@ -2665,40 +4267,43 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
}
s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
- if (!newprefs) {
+ if(!newprefs) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Error allocated space for method preferences");
}
memcpy(s, prefs, prefs_len + 1);
- while (s && *s && mlist) {
+ while(s && *s && mlist) {
char *p = strchr(s, ',');
int method_len = p ? (p - s) : (int) strlen(s);
- if (!kex_get_method_by_name(s, method_len, mlist)) {
+ if(!kex_get_method_by_name(s, method_len, mlist)) {
/* Strip out unsupported method */
- if (p) {
+ if(p) {
memcpy(s, p + 1, strlen(s) - method_len);
- } else {
- if (s > newprefs) {
+ }
+ else {
+ if(s > newprefs) {
*(--s) = '\0';
- } else {
+ }
+ else {
*s = '\0';
}
}
}
-
- s = p ? (p + 1) : NULL;
+ else {
+ s = p ? (p + 1) : NULL;
+ }
}
- if (strlen(newprefs) == 0) {
+ if(strlen(newprefs) == 0) {
LIBSSH2_FREE(session, newprefs);
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"The requested method(s) are not currently "
"supported");
}
- if (*prefvar) {
+ if(*prefvar) {
LIBSSH2_FREE(session, *prefvar);
}
*prefvar = newprefs;
@@ -2714,7 +4319,7 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
int method_type,
- const char*** algs)
+ const char ***algs)
{
unsigned int i;
unsigned int j;
@@ -2722,11 +4327,11 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
const LIBSSH2_COMMON_METHOD **mlist;
/* to prevent coredumps due to dereferencing of NULL */
- if (NULL == algs)
+ if(NULL == algs)
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"algs must not be NULL");
- switch (method_type) {
+ switch(method_type) {
case LIBSSH2_METHOD_KEX:
mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
break;
@@ -2747,7 +4352,8 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
case LIBSSH2_METHOD_COMP_CS:
case LIBSSH2_METHOD_COMP_SC:
- mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods(session);
+ mlist = (const LIBSSH2_COMMON_METHOD **)
+ _libssh2_comp_methods(session);
break;
default:
@@ -2756,7 +4362,7 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
} /* switch */
/* weird situation */
- if (NULL==mlist)
+ if(NULL == mlist)
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"No algorithm found");
@@ -2773,28 +4379,28 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
*/
/* count the number of supported algorithms */
- for ( i=0, ialg=0; NULL!=mlist[i]; i++) {
+ for(i = 0, ialg = 0; NULL != mlist[i]; i++) {
/* do not count fields with NULL name */
- if (mlist[i]->name)
+ if(mlist[i]->name)
ialg++;
}
/* weird situation, no algorithm found */
- if (0==ialg)
+ if(0 == ialg)
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"No algorithm found");
/* allocate buffer */
- *algs = (const char**) LIBSSH2_ALLOC(session, ialg*sizeof(const char*));
- if ( NULL==*algs ) {
+ *algs = (const char **) LIBSSH2_ALLOC(session, ialg*sizeof(const char *));
+ if(NULL == *algs) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Memory allocation failed");
}
/* Past this point *algs must be deallocated in case of an error!! */
/* copy non-NULL pointers only */
- for ( i=0, j=0; NULL!=mlist[i] && j<ialg; i++ ) {
- if ( NULL==mlist[i]->name ){
+ for(i = 0, j = 0; NULL != mlist[i] && j < ialg; i++) {
+ if(NULL == mlist[i]->name) {
/* maybe a weird situation but if it occurs, do not include NULL
pointers */
continue;
@@ -2805,7 +4411,7 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
}
/* correct number of pointers copied? (test the code above) */
- if ( j!=ialg ) {
+ if(j != ialg) {
/* deallocate buffer */
LIBSSH2_FREE(session, (void *)*algs);
*algs = NULL;
diff --git a/libs/libssh2/src/knownhost.c b/libs/libssh2/src/knownhost.c
index a32dcf8764..b9dc47a80a 100644
--- a/libs/libssh2/src/knownhost.c
+++ b/libs/libssh2/src/knownhost.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 by Daniel Stenberg
+ * Copyright (c) 2009-2019 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -71,7 +71,7 @@ static void free_host(LIBSSH2_SESSION *session, struct known_host *entry)
if(entry) {
if(entry->comment)
LIBSSH2_FREE(session, entry->comment);
- if (entry->key_type_name)
+ if(entry->key_type_name)
LIBSSH2_FREE(session, entry->key_type_name);
if(entry->key)
LIBSSH2_FREE(session, entry->key);
@@ -149,7 +149,8 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL,
"No key type set");
- if(!(entry = LIBSSH2_CALLOC(hosts->session, sizeof(struct known_host))))
+ entry = LIBSSH2_CALLOC(hosts->session, sizeof(struct known_host));
+ if(!entry)
return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for known host "
"entry");
@@ -159,13 +160,13 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
switch(entry->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
case LIBSSH2_KNOWNHOST_TYPE_CUSTOM:
- entry->name = LIBSSH2_ALLOC(hosts->session, hostlen+1);
+ entry->name = LIBSSH2_ALLOC(hosts->session, hostlen + 1);
if(!entry->name) {
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for host name");
goto error;
}
- memcpy(entry->name, host, hostlen+1);
+ memcpy(entry->name, host, hostlen + 1);
entry->name_len = hostlen;
break;
case LIBSSH2_KNOWNHOST_TYPE_SHA1:
@@ -193,14 +194,14 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
/* the provided key is base64 encoded already */
if(!keylen)
keylen = strlen(key);
- entry->key = LIBSSH2_ALLOC(hosts->session, keylen+1);
+ entry->key = LIBSSH2_ALLOC(hosts->session, keylen + 1);
if(!entry->key) {
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for key");
goto error;
}
- memcpy(entry->key, key, keylen+1);
- entry->key[keylen]=0; /* force a terminating zero trailer */
+ memcpy(entry->key, key, keylen + 1);
+ entry->key[keylen] = 0; /* force a terminating zero trailer */
}
else {
/* key is raw, we base64 encode it and store it as such */
@@ -216,28 +217,28 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
entry->key = ptr;
}
- if (key_type_name && ((typemask & LIBSSH2_KNOWNHOST_KEY_MASK) ==
+ if(key_type_name && ((typemask & LIBSSH2_KNOWNHOST_KEY_MASK) ==
LIBSSH2_KNOWNHOST_KEY_UNKNOWN)) {
- entry->key_type_name = LIBSSH2_ALLOC(hosts->session, key_type_len+1);
- if (!entry->key_type_name) {
+ entry->key_type_name = LIBSSH2_ALLOC(hosts->session, key_type_len + 1);
+ if(!entry->key_type_name) {
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for key type");
goto error;
}
memcpy(entry->key_type_name, key_type_name, key_type_len);
- entry->key_type_name[key_type_len]=0;
+ entry->key_type_name[key_type_len] = 0;
entry->key_type_len = key_type_len;
}
- if (comment) {
- entry->comment = LIBSSH2_ALLOC(hosts->session, commentlen+1);
+ if(comment) {
+ entry->comment = LIBSSH2_ALLOC(hosts->session, commentlen + 1);
if(!entry->comment) {
rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for comment");
goto error;
}
- memcpy(entry->comment, comment, commentlen+1);
- entry->comment[commentlen]=0; /* force a terminating zero trailer */
+ memcpy(entry->comment, comment, commentlen + 1);
+ entry->comment[commentlen] = 0; /* force a terminating zero trailer */
entry->comment_len = commentlen;
}
else {
@@ -370,7 +371,7 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
plain 'host' */
if(port >= 0) {
int len = snprintf(hostbuff, sizeof(hostbuff), "[%s]:%d", hostp, port);
- if (len < 0 || len >= (int)sizeof(hostbuff)) {
+ if(len < 0 || len >= (int)sizeof(hostbuff)) {
_libssh2_error(hosts->session,
LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Known-host write buffer too small");
@@ -401,7 +402,7 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
do {
node = _libssh2_list_first(&hosts->head);
- while (node) {
+ while(node) {
switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) {
case LIBSSH2_KNOWNHOST_TYPE_PLAIN:
if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN)
@@ -450,13 +451,13 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
- if key_type is set to zero, ignore it an match always
- otherwise match when both key types are equal
*/
- if ( (host_key_type != LIBSSH2_KNOWNHOST_KEY_UNKNOWN ) &&
- ( (host_key_type == 0) ||
- (host_key_type == known_key_type) ) ) {
+ if(host_key_type != LIBSSH2_KNOWNHOST_KEY_UNKNOWN &&
+ (host_key_type == 0 ||
+ host_key_type == known_key_type)) {
/* host name and key type match, now compare the keys */
if(!strcmp(key, node->key)) {
/* they match! */
- if (ext)
+ if(ext)
*ext = knownhost_to_external(node);
badkey = NULL;
rc = LIBSSH2_KNOWNHOST_CHECK_MATCH;
@@ -472,14 +473,14 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts,
}
match = 0; /* don't count this as a match anymore */
}
- node= _libssh2_list_next(&node->node);
+ node = _libssh2_list_next(&node->node);
}
host = hostp;
} while(!match && --numcheck);
if(badkey) {
/* key mismatch */
- if (ext)
+ if(ext)
*ext = knownhost_to_external(badkey);
rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH;
}
@@ -646,7 +647,7 @@ static int oldstyle_hostline(LIBSSH2_KNOWNHOSTS *hosts,
/* copy host name to the temp buffer and zero terminate */
memcpy(hostbuf, name, namelen);
- hostbuf[namelen]=0;
+ hostbuf[namelen] = 0;
rc = knownhost_add(hosts, hostbuf, NULL,
key_type_name, key_type_len,
@@ -685,7 +686,7 @@ static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts,
for(p = salt; *p && (*p != '|'); p++)
;
- if(*p=='|') {
+ if(*p == '|') {
const char *hash = NULL;
size_t saltlen = p - salt;
if(saltlen >= (sizeof(saltbuf)-1)) /* weird length */
@@ -698,11 +699,11 @@ static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts,
saltbuf[saltlen] = 0; /* zero terminate */
salt = saltbuf; /* point to the stack based buffer */
- hash = p+1; /* the host hash is after the separator */
+ hash = p + 1; /* the host hash is after the separator */
/* now make the host point to the hash */
host = hash;
- hostlen -= saltlen+1; /* deduct the salt and separator */
+ hostlen -= saltlen + 1; /* deduct the salt and separator */
/* check that the lengths seem sensible */
if(hostlen >= sizeof(hostbuf)-1)
@@ -712,7 +713,7 @@ static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts,
"(unexpected length)");
memcpy(hostbuf, host, hostlen);
- hostbuf[hostlen]=0;
+ hostbuf[hostlen] = 0;
return knownhost_add(hosts, hostbuf, salt,
key_type_name, key_type_len,
@@ -766,17 +767,25 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
default:
key_type_name = key;
- while (keylen && *key &&
+ while(keylen && *key &&
(*key != ' ') && (*key != '\t')) {
key++;
keylen--;
}
key_type_len = key - key_type_name;
- if (!strncmp(key_type_name, "ssh-dss", key_type_len))
+ 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))
+ else if(!strncmp(key_type_name, "ssh-rsa", key_type_len))
key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
+ 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
key_type = LIBSSH2_KNOWNHOST_KEY_UNKNOWN;
@@ -800,7 +809,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
keylen -= commentlen;
/* Distinguish empty comment (a space) from no comment (no space) */
- if (commentlen == 0)
+ if(commentlen == 0)
comment = NULL;
/* skip whitespaces */
@@ -879,7 +888,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
cp = line;
/* skip leading whitespaces */
- while(len && ((*cp==' ') || (*cp == '\t'))) {
+ while(len && ((*cp == ' ') || (*cp == '\t'))) {
cp++;
len--;
}
@@ -892,7 +901,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
hostp = cp;
/* move over the host to the separator */
- while(len && *cp && (*cp!=' ') && (*cp != '\t')) {
+ while(len && *cp && (*cp != ' ') && (*cp != '\t')) {
cp++;
len--;
}
@@ -900,7 +909,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
hostlen = cp - hostp;
/* the key starts after the whitespaces */
- while(len && *cp && ((*cp==' ') || (*cp == '\t'))) {
+ while(len && *cp && ((*cp == ' ') || (*cp == '\t'))) {
cp++;
len--;
}
@@ -954,7 +963,7 @@ libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
"Unsupported type of known-host information "
"store");
- file = fopen(filename, "r");
+ file = fopen(filename, FOPEN_READTEXT);
if(file) {
while(fgets(buf, sizeof(buf), file)) {
if(libssh2_knownhost_readline(hosts, buf, strlen(buf), type)) {
@@ -1016,13 +1025,30 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
key_type_name = "ssh-dss";
key_type_len = 7;
break;
+ case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
+ key_type_name = "ecdsa-sha2-nistp256";
+ key_type_len = 19;
+ break;
+ case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
+ key_type_name = "ecdsa-sha2-nistp384";
+ key_type_len = 19;
+ break;
+ case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
+ key_type_name = "ecdsa-sha2-nistp521";
+ key_type_len = 19;
+ break;
+ case LIBSSH2_KNOWNHOST_KEY_ED25519:
+ key_type_name = "ssh-ed25519";
+ key_type_len = 11;
+ break;
case LIBSSH2_KNOWNHOST_KEY_UNKNOWN:
key_type_name = node->key_type_name;
- if (key_type_name) {
+ if(key_type_name) {
key_type_len = node->key_type_len;
break;
}
/* otherwise fallback to default and error */
+ /* FALL-THROUGH */
default:
return _libssh2_error(hosts->session,
LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
@@ -1033,7 +1059,7 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
- Hashed (SHA1) or unhashed hostname
- key name or no key name (RSA1)
- comment or no comment
-
+
This means there are 2^3 different formats:
("|1|%s|%s %s %s %s\n", salt, hashed_host, key_name, key, comment)
("|1|%s|%s %s %s\n", salt, hashed_host, key_name, key)
@@ -1043,7 +1069,7 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
("%s %s %s\n", host, key_name, key)
("%s %s %s\n", host, key, comment)
("%s %s\n", host, key)
-
+
Even if the buffer is too small, we have to set outlen to the number of
characters the complete line would have taken. We also don't write
anything to the buffer unless we are sure we can write everything to the
@@ -1087,10 +1113,10 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
if(node->comment && key_type_len)
snprintf(buf, buflen, "|1|%s|%s %s %s %s\n", saltalloc,
namealloc, key_type_name, node->key, node->comment);
- else if (node->comment)
+ else if(node->comment)
snprintf(buf, buflen, "|1|%s|%s %s %s\n", saltalloc, namealloc,
node->key, node->comment);
- else if (key_type_len)
+ else if(key_type_len)
snprintf(buf, buflen, "|1|%s|%s %s %s\n", saltalloc, namealloc,
key_type_name, node->key);
else
@@ -1109,10 +1135,10 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
if(node->comment && key_type_len)
snprintf(buf, buflen, "%s %s %s %s\n", node->name,
key_type_name, node->key, node->comment);
- else if (node->comment)
+ else if(node->comment)
snprintf(buf, buflen, "%s %s %s\n", node->name, node->key,
node->comment);
- else if (key_type_len)
+ else if(key_type_len)
snprintf(buf, buflen, "%s %s %s\n", node->name, key_type_name,
node->key);
else
@@ -1178,7 +1204,7 @@ libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
"Unsupported type of known-host information "
"store");
- file = fopen(filename, "w");
+ file = fopen(filename, FOPEN_WRITETEXT);
if(!file)
return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE,
"Failed to open file");
diff --git a/libs/libssh2/src/libgcrypt.c b/libs/libssh2/src/libgcrypt.c
index 366d007a34..0aff176a61 100644
--- a/libs/libssh2/src/libgcrypt.c
+++ b/libs/libssh2/src/libgcrypt.c
@@ -66,17 +66,18 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
(void) e2data;
(void) e2len;
- if (ddata) {
+ if(ddata) {
rc = gcry_sexp_build
(rsa, NULL,
"(private-key(rsa(n%b)(e%b)(d%b)(q%b)(p%b)(u%b)))",
nlen, ndata, elen, edata, dlen, ddata, plen, pdata,
qlen, qdata, coefflen, coeffdata);
- } else {
+ }
+ else {
rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))",
nlen, ndata, elen, edata);
}
- if (rc) {
+ if(rc) {
*rsa = NULL;
return -1;
}
@@ -99,12 +100,12 @@ _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
rc = gcry_sexp_build(&s_hash, NULL,
"(data (flags pkcs1) (hash sha1 %b))",
SHA_DIGEST_LENGTH, hash);
- if (rc != 0) {
+ if(rc != 0) {
return -1;
}
rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig);
- if (rc != 0) {
+ if(rc != 0) {
gcry_sexp_release(s_hash);
return -1;
}
@@ -130,18 +131,19 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
{
int rc;
- if (x_len) {
+ if(x_len) {
rc = gcry_sexp_build
(dsactx, NULL,
"(private-key(dsa(p%b)(q%b)(g%b)(y%b)(x%b)))",
p_len, p, q_len, q, g_len, g, y_len, y, x_len, x);
- } else {
+ }
+ else {
rc = gcry_sexp_build(dsactx, NULL,
"(public-key(dsa(p%b)(q%b)(g%b)(y%b)))",
p_len, p, q_len, q, g_len, g, y_len, y);
}
- if (rc) {
+ if(rc) {
*dsactx = NULL;
return -1;
}
@@ -172,84 +174,83 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
unsigned char *n, *e, *d, *p, *q, *e1, *e2, *coeff;
unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen;
- (void) passphrase;
-
- fp = fopen(filename, "r");
- if (!fp) {
+ fp = fopen(filename, FOPEN_READTEXT);
+ if(!fp) {
return -1;
}
ret = _libssh2_pem_parse(session,
"-----BEGIN RSA PRIVATE KEY-----",
"-----END RSA PRIVATE KEY-----",
+ passphrase,
fp, &data, &datalen);
fclose(fp);
- if (ret) {
+ if(ret) {
return -1;
}
save_data = data;
- if (_libssh2_pem_decode_sequence(&data, &datalen)) {
+ if(_libssh2_pem_decode_sequence(&data, &datalen)) {
ret = -1;
goto fail;
}
/* First read Version field (should be 0). */
ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen);
- if (ret != 0 || (nlen != 1 && *n != '\0')) {
+ if(ret != 0 || (nlen != 1 && *n != '\0')) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &e, &elen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &d, &dlen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &e1, &e1len);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &e2, &e2len);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &coeff, &coefflen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
- if (_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen,
+ if(_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen,
q, qlen, e1, e1len, e2, e2len, coeff, coefflen)) {
ret = -1;
goto fail;
@@ -285,72 +286,71 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
unsigned char *p, *q, *g, *y, *x;
unsigned int plen, qlen, glen, ylen, xlen;
- (void) passphrase;
-
- fp = fopen(filename, "r");
- if (!fp) {
+ fp = fopen(filename, FOPEN_READTEXT);
+ if(!fp) {
return -1;
}
ret = _libssh2_pem_parse(session,
"-----BEGIN DSA PRIVATE KEY-----",
"-----END DSA PRIVATE KEY-----",
+ passphrase,
fp, &data, &datalen);
fclose(fp);
- if (ret) {
+ if(ret) {
return -1;
}
save_data = data;
- if (_libssh2_pem_decode_sequence(&data, &datalen)) {
+ if(_libssh2_pem_decode_sequence(&data, &datalen)) {
ret = -1;
goto fail;
}
/* First read Version field (should be 0). */
ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
- if (ret != 0 || (plen != 1 && *p != '\0')) {
+ if(ret != 0 || (plen != 1 && *p != '\0')) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &g, &glen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &y, &ylen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
ret = _libssh2_pem_decode_integer(&data, &datalen, &x, &xlen);
- if (ret != 0) {
+ if(ret != 0) {
ret = -1;
goto fail;
}
- if (datalen != 0) {
+ if(datalen != 0) {
ret = -1;
goto fail;
}
- if (_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) {
+ if(_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) {
ret = -1;
goto fail;
}
@@ -375,11 +375,11 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
const char *tmp;
size_t size;
- if (hash_len != SHA_DIGEST_LENGTH) {
+ if(hash_len != SHA_DIGEST_LENGTH) {
return -1;
}
- if (gcry_sexp_build(&data, NULL,
+ if(gcry_sexp_build(&data, NULL,
"(data (flags pkcs1) (hash sha1 %b))",
hash_len, hash)) {
return -1;
@@ -389,32 +389,36 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
gcry_sexp_release(data);
- if (rc != 0) {
+ if(rc != 0) {
return -1;
}
data = gcry_sexp_find_token(sig_sexp, "s", 0);
- if (!data) {
+ if(!data) {
return -1;
}
tmp = gcry_sexp_nth_data(data, 1, &size);
- if (!tmp) {
+ if(!tmp) {
+ gcry_sexp_release(data);
return -1;
}
- if (tmp[0] == '\0') {
+ if(tmp[0] == '\0') {
tmp++;
size--;
}
*signature = LIBSSH2_ALLOC(session, size);
- if (!*signature) {
+ if(!*signature) {
+ gcry_sexp_release(data);
return -1;
}
memcpy(*signature, tmp, size);
*signature_len = size;
+ gcry_sexp_release(data);
+
return rc;
}
@@ -430,14 +434,15 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
const char *tmp;
size_t size;
- if (hash_len != SHA_DIGEST_LENGTH) {
+ if(hash_len != SHA_DIGEST_LENGTH) {
return -1;
}
memcpy(zhash + 1, hash, hash_len);
zhash[0] = 0;
- if (gcry_sexp_build(&data, NULL, "(data (value %b))", hash_len + 1, zhash)) {
+ if(gcry_sexp_build(&data, NULL, "(data (value %b))",
+ hash_len + 1, zhash)) {
return -1;
}
@@ -445,7 +450,7 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
gcry_sexp_release(data);
- if (ret != 0) {
+ if(ret != 0) {
return -1;
}
@@ -454,19 +459,19 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
/* Extract R. */
data = gcry_sexp_find_token(sig_sexp, "r", 0);
- if (!data)
+ if(!data)
goto err;
tmp = gcry_sexp_nth_data(data, 1, &size);
- if (!tmp)
+ if(!tmp)
goto err;
- if (tmp[0] == '\0') {
+ if(tmp[0] == '\0') {
tmp++;
size--;
}
- if (size < 1 || size > 20)
+ if(size < 1 || size > 20)
goto err;
memcpy(sig + (20 - size), tmp, size);
@@ -476,19 +481,19 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
/* Extract S. */
data = gcry_sexp_find_token(sig_sexp, "s", 0);
- if (!data)
+ if(!data)
goto err;
tmp = gcry_sexp_nth_data(data, 1, &size);
- if (!tmp)
+ if(!tmp)
goto err;
- if (tmp[0] == '\0') {
+ if(tmp[0] == '\0') {
tmp++;
size--;
}
- if (size < 1 || size > 20)
+ if(size < 1 || size > 20)
goto err;
memcpy(sig + 20 + (20 - size), tmp, size);
@@ -498,10 +503,10 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
ret = -1;
out:
- if (sig_sexp) {
+ if(sig_sexp) {
gcry_sexp_release(sig_sexp);
}
- if (data) {
+ if(data) {
gcry_sexp_release(data);
}
return ret;
@@ -519,12 +524,12 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
libssh2_sha1(m, m_len, hash + 1);
hash[0] = 0;
- if (gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))",
+ if(gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))",
SHA_DIGEST_LENGTH + 1, hash)) {
return -1;
}
- if (gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
+ if(gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
20, sig, 20, sig + 20)) {
gcry_sexp_release(s_hash);
return -1;
@@ -543,30 +548,30 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
unsigned char *iv, unsigned char *secret, int encrypt)
{
int ret;
- int cipher = _libssh2_gcry_cipher (algo);
- int mode = _libssh2_gcry_mode (algo);
+ int cipher = _libssh2_gcry_cipher(algo);
+ int mode = _libssh2_gcry_mode(algo);
int keylen = gcry_cipher_get_algo_keylen(cipher);
(void) encrypt;
ret = gcry_cipher_open(h, cipher, mode, 0);
- if (ret) {
+ if(ret) {
return -1;
}
ret = gcry_cipher_setkey(*h, secret, keylen);
- if (ret) {
+ if(ret) {
gcry_cipher_close(*h);
return -1;
}
- if (mode != GCRY_CIPHER_MODE_STREAM) {
+ if(mode != GCRY_CIPHER_MODE_STREAM) {
int blklen = gcry_cipher_get_algo_blklen(cipher);
- if (mode == GCRY_CIPHER_MODE_CTR)
+ if(mode == GCRY_CIPHER_MODE_CTR)
ret = gcry_cipher_setctr(*h, iv, blklen);
else
ret = gcry_cipher_setiv(*h, iv, blklen);
- if (ret) {
+ if(ret) {
gcry_cipher_close(*h);
return -1;
}
@@ -580,12 +585,13 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
_libssh2_cipher_type(algo),
int encrypt, unsigned char *block, size_t blklen)
{
- int cipher = _libssh2_gcry_cipher (algo);
+ int cipher = _libssh2_gcry_cipher(algo);
int ret;
- if (encrypt) {
+ if(encrypt) {
ret = gcry_cipher_encrypt(*ctx, block, blklen, block, blklen);
- } else {
+ }
+ else {
ret = gcry_cipher_decrypt(*ctx, block, blklen, block, blklen);
}
return ret;
@@ -602,8 +608,9 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
const char *passphrase)
{
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
- "Unable to extract public key from private key in memory: "
- "Method unimplemented in libgcrypt backend");
+ "Unable to extract public key from private "
+ "key in memory: "
+ "Method unimplemented in libgcrypt backend");
}
int
@@ -624,4 +631,37 @@ void _libssh2_init_aes_ctr(void)
{
/* no implementation */
}
+
+void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
+{
+ *dhctx = gcry_mpi_new(0); /* Random from client */
+}
+
+int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+ _libssh2_bn *g, _libssh2_bn *p, int group_order)
+{
+ /* Generate x and e */
+ gcry_mpi_randomize(*dhctx, group_order * 8 - 1, GCRY_WEAK_RANDOM);
+ gcry_mpi_powm(public, g, *dhctx, p);
+ return 0;
+}
+
+int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+ _libssh2_bn *f, _libssh2_bn *p)
+{
+ /* Compute the shared secret */
+ gcry_mpi_powm(secret, f, *dhctx, p);
+ return 0;
+}
+
+void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
+{
+ gcry_mpi_release(*dhctx);
+ *dhctx = NULL;
+}
+
#endif /* LIBSSH2_LIBGCRYPT */
diff --git a/libs/libssh2/src/libgcrypt.h b/libs/libssh2/src/libgcrypt.h
index 11d6ad2dc5..ec88aded62 100644
--- a/libs/libssh2/src/libgcrypt.h
+++ b/libs/libssh2/src/libgcrypt.h
@@ -54,10 +54,16 @@
#define LIBSSH2_RSA 1
#define LIBSSH2_DSA 1
+#define LIBSSH2_ECDSA 0
+#define LIBSSH2_ED25519 0
#define MD5_DIGEST_LENGTH 16
#define SHA_DIGEST_LENGTH 20
#define SHA256_DIGEST_LENGTH 32
+#define SHA384_DIGEST_LENGTH 48
+#define SHA512_DIGEST_LENGTH 64
+
+#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
#define _libssh2_random(buf, len) \
(gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1)
@@ -68,60 +74,82 @@
/* returns 0 in case of failure */
#define libssh2_sha1_init(ctx) \
- (GPG_ERR_NO_ERROR == gcry_md_open (ctx, GCRY_MD_SHA1, 0))
+ (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)
#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)
#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)
#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))
+ (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)
#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)
#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)
+
+#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)
+#define libssh2_sha384_final(ctx, out) \
+ memcpy(out, gcry_md_read(ctx, 0), SHA384_DIGEST_LENGTH), gcry_md_close(ctx)
+#define libssh2_sha384(message, len, out) \
+ gcry_md_hash_buffer(GCRY_MD_SHA384, out, message, len)
+
+#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)
+#define libssh2_sha512_final(ctx, out) \
+ memcpy(out, gcry_md_read(ctx, 0), SHA512_DIGEST_LENGTH), gcry_md_close(ctx)
+#define libssh2_sha512(message, len, out) \
+ gcry_md_hash_buffer(GCRY_MD_SHA512, out, message, len)
#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))
+ (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)
#define libssh2_md5_final(ctx, out) \
- memcpy (out, gcry_md_read (ctx, 0), MD5_DIGEST_LENGTH), gcry_md_close (ctx)
+ 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)
+ gcry_md_hash_buffer(GCRY_MD_MD5, out, message, len)
#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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)))
+ 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)
@@ -135,6 +163,11 @@
#define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx)
+#if LIBSSH2_ECDSA
+#else
+#define _libssh2_ec_key void
+#endif
+
#define _libssh2_cipher_type(name) int name
#define _libssh2_cipher_ctx gcry_cipher_hd_t
@@ -171,13 +204,31 @@
#define _libssh2_bn_ctx_new() 0
#define _libssh2_bn_ctx_free(bnctx) ((void)0)
#define _libssh2_bn_init() gcry_mpi_new(0)
-#define _libssh2_bn_init_from_bin() NULL /* because gcry_mpi_scan() creates a new bignum */
-#define _libssh2_bn_rand(bn, bits, top, bottom) gcry_mpi_randomize (bn, bits, GCRY_WEAK_RANDOM)
-#define _libssh2_bn_mod_exp(r, a, p, m, ctx) gcry_mpi_powm (r, a, p, m)
+#define _libssh2_bn_init_from_bin() NULL /* because gcry_mpi_scan() creates a
+ new bignum */
#define _libssh2_bn_set_word(bn, val) gcry_mpi_set_ui(bn, val)
-#define _libssh2_bn_from_bin(bn, len, val) gcry_mpi_scan(&((bn)), GCRYMPI_FMT_USG, val, len, NULL)
-#define _libssh2_bn_to_bin(bn, val) gcry_mpi_print (GCRYMPI_FMT_USG, val, _libssh2_bn_bytes(bn), NULL, bn)
-#define _libssh2_bn_bytes(bn) (gcry_mpi_get_nbits (bn) / 8 + ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1))
+#define _libssh2_bn_from_bin(bn, len, val) \
+ gcry_mpi_scan(&((bn)), GCRYMPI_FMT_USG, val, len, NULL)
+#define _libssh2_bn_to_bin(bn, val) \
+ gcry_mpi_print(GCRYMPI_FMT_USG, val, _libssh2_bn_bytes(bn), NULL, bn)
+#define _libssh2_bn_bytes(bn) \
+ (gcry_mpi_get_nbits (bn) / 8 + \
+ ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1))
#define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn)
#define _libssh2_bn_free(bn) gcry_mpi_release(bn)
+#define _libssh2_dh_ctx struct gcry_mpi *
+#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
+ _libssh2_dh_key_pair(dhctx, public, g, p, group_order)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
+ _libssh2_dh_secret(dhctx, secret, f, p)
+#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx)
+extern void _libssh2_dh_init(_libssh2_dh_ctx *dhctx);
+extern int _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+ _libssh2_bn *g, _libssh2_bn *p,
+ int group_order);
+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);
+
diff --git a/libs/libssh2/src/libssh2_config.h.in b/libs/libssh2/src/libssh2_config.h.in
index af4ab9ca0a..307c625533 100644
--- a/libs/libssh2/src/libssh2_config.h.in
+++ b/libs/libssh2/src/libssh2_config.h.in
@@ -64,8 +64,8 @@
/* Define if you have the gcrypt library. */
#undef HAVE_LIBGCRYPT
-/* Define if you have the mbedtls library. */
-#undef HAVE_LIBMBEDTLS
+/* Define if you have the mbedcrypto library. */
+#undef HAVE_LIBMBEDCRYPTO
/* Define if you have the ssl library. */
#undef HAVE_LIBSSL
@@ -79,6 +79,9 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
+/* Define to 1 if you have the `memset_s' function. */
+#undef HAVE_MEMSET_S
+
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
@@ -178,10 +181,10 @@
/* Use mbedtls */
#undef LIBSSH2_MBEDTLS
-/* Use OpenSSL */
+/* Use openssl */
#undef LIBSSH2_OPENSSL
-/* Use Windows CNG */
+/* Use wincng */
#undef LIBSSH2_WINCNG
/* Define to the sub-directory where libtool stores uninstalled libraries. */
diff --git a/libs/libssh2/src/libssh2_priv.h b/libs/libssh2/src/libssh2_priv.h
index edd5047138..33c5ad3f87 100644
--- a/libs/libssh2/src/libssh2_priv.h
+++ b/libs/libssh2/src/libssh2_priv.h
@@ -40,6 +40,7 @@
#ifndef LIBSSH2_PRIV_H
#define LIBSSH2_PRIV_H 1
+#define LIBSSH2_LIBRARY
#include "libssh2_config.h"
#ifdef HAVE_WINDOWS_H
@@ -57,18 +58,15 @@
#include <stdio.h>
#include <time.h>
-/* The following CPP block should really only be in session.c and
- packet.c. However, AIX have #define's for 'events' and 'revents'
- and we are using those names in libssh2.h, so we need to include
- the AIX headers first, to make sure all code is compiled with
- consistent names of these fields. While arguable the best would to
- change libssh2.h to use other names, that would break backwards
- compatibility. For more information, see:
- https://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00003.html
- https://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00224.html
+/* The following CPP block should really only be in session.c and packet.c.
+ However, AIX have #define's for 'events' and 'revents' and we are using
+ those names in libssh2.h, so we need to include the AIX headers first, to
+ make sure all code is compiled with consistent names of these fields.
+ While arguable the best would to change libssh2.h to use other names, that
+ would break backwards compatibility.
*/
#ifdef HAVE_POLL
-# include <sys/poll.h>
+# include <poll.h>
#else
# if defined(HAVE_SELECT) && !defined(WIN32)
# ifdef HAVE_SYS_SELECT_H
@@ -117,13 +115,13 @@
struct iovec {
size_t iov_len;
- void * iov_base;
+ void *iov_base;
};
static inline int writev(int sock, struct iovec *iov, int nvecs)
{
DWORD ret;
- if (WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) {
+ if(WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) {
return ret;
}
return -1;
@@ -165,7 +163,7 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
* padding length, payload, padding, and MAC.)."
*/
#define MAX_SSH_PACKET_LEN 35000
-#define MAX_SHA_DIGEST_LEN SHA256_DIGEST_LENGTH
+#define MAX_SHA_DIGEST_LEN SHA512_DIGEST_LENGTH
#define LIBSSH2_ALLOC(session, count) \
session->alloc((count), &(session)->abstract)
@@ -259,11 +257,10 @@ typedef struct kmdhgGPshakex_state_t
size_t s_packet_len;
size_t tmp_len;
_libssh2_bn_ctx *ctx;
- _libssh2_bn *x;
+ _libssh2_dh_ctx x;
_libssh2_bn *e;
_libssh2_bn *f;
_libssh2_bn *k;
- unsigned char *s;
unsigned char *f_value;
unsigned char *k_value;
unsigned char *h_sig;
@@ -282,10 +279,18 @@ typedef struct key_exchange_state_low_t
kmdhgGPshakex_state_t exchange_state;
_libssh2_bn *p; /* SSH2 defined value (p_value) */
_libssh2_bn *g; /* SSH2 defined value (2) */
- unsigned char request[13];
+ unsigned char request[256]; /* Must fit EC_MAX_POINT_LEN + data */
unsigned char *data;
size_t request_len;
size_t data_len;
+ _libssh2_ec_key *private_key; /* SSH2 ecdh private key */
+ unsigned char *public_key_oct; /* SSH2 ecdh public key octal value */
+ size_t public_key_oct_len; /* SSH2 ecdh public key octal value
+ length */
+ unsigned char *curve25519_public_key; /* curve25519 public key, 32
+ bytes */
+ unsigned char *curve25519_private_key; /* curve25519 private key, 32
+ bytes */
} key_exchange_state_low_t;
typedef struct key_exchange_state_t
@@ -417,7 +422,8 @@ struct _LIBSSH2_CHANNEL
/* State variables used in libssh2_channel_receive_window_adjust() */
libssh2_nonblocking_states adjust_state;
- unsigned char adjust_adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */
+ unsigned char adjust_adjust[9]; /* packet_type(1) + channel(4) +
+ adjustment(4) */
/* State variables used in libssh2_channel_read_ex() */
libssh2_nonblocking_states read_state;
@@ -620,6 +626,9 @@ struct _LIBSSH2_SESSION
unsigned char server_hostkey_sha1[SHA_DIGEST_LENGTH];
int server_hostkey_sha1_valid;
+ unsigned char server_hostkey_sha256[SHA256_DIGEST_LENGTH];
+ int server_hostkey_sha256_valid;
+
/* (remote as source of data -- packet_read ) */
libssh2_endpoint_data remote;
@@ -653,8 +662,9 @@ struct _LIBSSH2_SESSION
struct transportpacket packet;
#ifdef LIBSSH2DEBUG
int showmask; /* what debug/trace messages to display */
- libssh2_trace_handler_func tracehandler; /* callback to display trace messages */
- void* tracehandler_context; /* context for the trace handler */
+ libssh2_trace_handler_func tracehandler; /* callback to display trace
+ messages */
+ void *tracehandler_context; /* context for the trace handler */
#endif
/* State variables used in libssh2_banner_send() */
@@ -861,7 +871,8 @@ struct _LIBSSH2_KEX_METHOD
{
const char *name;
- /* Key exchange, populates session->* and returns 0 on success, non-0 on error */
+ /* Key exchange, populates session->* and returns 0 on success, non-0 on
+ error */
int (*exchange_keys) (LIBSSH2_SESSION * session,
key_exchange_state_low_t * key_state);
@@ -878,8 +889,10 @@ struct _LIBSSH2_HOSTKEY_METHOD
int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile,
unsigned const char *passphrase, void **abstract);
int (*initPEMFromMemory) (LIBSSH2_SESSION * session,
- const char *privkeyfiledata, size_t privkeyfiledata_len,
- unsigned const char *passphrase, void **abstract);
+ const char *privkeyfiledata,
+ size_t privkeyfiledata_len,
+ unsigned const char *passphrase,
+ void **abstract);
int (*sig_verify) (LIBSSH2_SESSION * session, const unsigned char *sig,
size_t sig_len, const unsigned char *m,
size_t m_len, void **abstract);
@@ -895,6 +908,7 @@ struct _LIBSSH2_HOSTKEY_METHOD
struct _LIBSSH2_CRYPT_METHOD
{
const char *name;
+ const char *pem_annotation;
int blocksize;
@@ -941,7 +955,8 @@ struct _LIBSSH2_COMP_METHOD
void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
...);
#else
-#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__)
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+ defined(__GNUC__)
/* C99 supported and also by older GCC */
#define _libssh2_debug(x,y,z,...) do {} while (0)
#else
@@ -962,7 +977,8 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
/* Initial packet state, prior to MAC check */
#define LIBSSH2_MAC_UNCONFIRMED 1
-/* When MAC type is "none" (proto initiation phase) all packets are deemed "confirmed" */
+/* When MAC type is "none" (proto initiation phase) all packets are deemed
+ "confirmed" */
#define LIBSSH2_MAC_CONFIRMED 0
/* Something very bad is going on */
#define LIBSSH2_MAC_INVALID -1
@@ -987,13 +1003,18 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
#define SSH_MSG_KEXDH_INIT 30
#define SSH_MSG_KEXDH_REPLY 31
-/* diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256 */
+/* diffie-hellman-group-exchange-sha1 and
+ diffie-hellman-group-exchange-sha256 */
#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
#define SSH_MSG_KEX_DH_GEX_REQUEST 34
#define SSH_MSG_KEX_DH_GEX_GROUP 31
#define SSH_MSG_KEX_DH_GEX_INIT 32
#define SSH_MSG_KEX_DH_GEX_REPLY 33
+/* ecdh */
+#define SSH2_MSG_KEX_ECDH_INIT 30
+#define SSH2_MSG_KEX_ECDH_REPLY 31
+
/* User Authentication */
#define SSH_MSG_USERAUTH_REQUEST 50
#define SSH_MSG_USERAUTH_FAILURE 51
@@ -1048,31 +1069,75 @@ int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void);
const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void);
+/* misc.c */
+int _libssh2_bcrypt_pbkdf(const char *pass,
+ size_t passlen,
+ const uint8_t *salt,
+ size_t saltlen,
+ uint8_t *key,
+ size_t keylen,
+ unsigned int rounds);
+
/* pem.c */
int _libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin,
const char *headerend,
+ const unsigned char *passphrase,
FILE * fp, unsigned char **data, unsigned int *datalen);
int _libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
const char *headerbegin,
const char *headerend,
const char *filedata, size_t filedata_len,
unsigned char **data, unsigned int *datalen);
+ /* OpenSSL keys */
+int
+_libssh2_openssh_pem_parse(LIBSSH2_SESSION * session,
+ const unsigned char *passphrase,
+ FILE * fp, struct string_buf **decrypted_buf);
+int
+_libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
+ const unsigned char *passphrase,
+ const char *filedata, size_t filedata_len,
+ struct string_buf **decrypted_buf);
+
int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen);
int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
unsigned char **i, unsigned int *ilen);
/* global.c */
-void _libssh2_init_if_needed (void);
+void _libssh2_init_if_needed(void);
#define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0]))
/* define to output the libssh2_int64_t type in a *printf() */
-#if defined( __BORLANDC__ ) || defined( _MSC_VER ) || defined( __MINGW32__ )
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
#define LIBSSH2_INT64_T_FORMAT "I64d"
#else
#define LIBSSH2_INT64_T_FORMAT "lld"
#endif
+/* 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)
+#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.
+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 line
+endings either CRLF or LF so 't' is appropriate.
+*/
+#define FOPEN_READTEXT "rt"
+#define FOPEN_WRITETEXT "w"
+#define FOPEN_APPENDTEXT "a"
+#else
+#define FOPEN_READTEXT "r"
+#define FOPEN_WRITETEXT "w"
+#define FOPEN_APPENDTEXT "a"
+#endif
+
#endif /* LIBSSH2_H */
diff --git a/libs/libssh2/src/mac.c b/libs/libssh2/src/mac.c
index 5ec26eb3b4..5ac71df4ce 100644
--- a/libs/libssh2/src/mac.c
+++ b/libs/libssh2/src/mac.c
@@ -86,7 +86,7 @@ mac_method_common_init(LIBSSH2_SESSION * session, unsigned char *key,
static int
mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract)
{
- if (*abstract) {
+ if(*abstract) {
LIBSSH2_FREE(session, *abstract);
}
*abstract = NULL;
@@ -118,7 +118,7 @@ mac_method_hmac_sha2_512_hash(LIBSSH2_SESSION * session,
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) {
+ if(addtl && addtl_len) {
libssh2_hmac_update(ctx, addtl, addtl_len);
}
libssh2_hmac_final(ctx, buf);
@@ -163,7 +163,7 @@ mac_method_hmac_sha2_256_hash(LIBSSH2_SESSION * session,
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) {
+ if(addtl && addtl_len) {
libssh2_hmac_update(ctx, addtl, addtl_len);
}
libssh2_hmac_final(ctx, buf);
@@ -208,7 +208,7 @@ mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session,
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) {
+ if(addtl && addtl_len) {
libssh2_hmac_update(ctx, addtl, addtl_len);
}
libssh2_hmac_final(ctx, buf);
@@ -281,7 +281,7 @@ mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf,
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) {
+ if(addtl && addtl_len) {
libssh2_hmac_update(ctx, addtl, addtl_len);
}
libssh2_hmac_final(ctx, buf);
@@ -354,7 +354,7 @@ mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session,
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) {
+ if(addtl && addtl_len) {
libssh2_hmac_update(ctx, addtl, addtl_len);
}
libssh2_hmac_final(ctx, buf);
diff --git a/libs/libssh2/src/mbedtls.c b/libs/libssh2/src/mbedtls.c
index 1d181e18ff..8bbcfd8d0d 100644
--- a/libs/libssh2/src/mbedtls.c
+++ b/libs/libssh2/src/mbedtls.c
@@ -1,9 +1,54 @@
+/* Copyright (c) 2016, Art <https://github.com/wildart>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
#include "libssh2_priv.h"
#ifdef LIBSSH2_MBEDTLS /* compile only if we build with mbedtls */
/*******************************************************************/
/*
+ * mbedTLS backend: Global context handles
+ */
+
+static mbedtls_entropy_context _libssh2_mbedtls_entropy;
+static mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg;
+
+/*******************************************************************/
+/*
* mbedTLS backend: Generic functions
*/
@@ -18,7 +63,7 @@ _libssh2_mbedtls_init(void)
ret = mbedtls_ctr_drbg_seed(&_libssh2_mbedtls_ctr_drbg,
mbedtls_entropy_func,
&_libssh2_mbedtls_entropy, NULL, 0);
- if (ret != 0)
+ if(ret != 0)
mbedtls_ctr_drbg_free(&_libssh2_mbedtls_ctr_drbg);
}
@@ -44,11 +89,11 @@ _libssh2_mbedtls_safe_free(void *buf, int len)
(void)len;
#endif
- if (!buf)
+ if(!buf)
return;
#ifdef LIBSSH2_CLEAR_MEMORY
- if (len > 0)
+ if(len > 0)
memset(buf, 0, len);
#endif
@@ -65,7 +110,7 @@ _libssh2_mbedtls_cipher_init(_libssh2_cipher_ctx *ctx,
const mbedtls_cipher_info_t *cipher_info;
int ret, op;
- if (!ctx)
+ if(!ctx)
return -1;
op = encrypt == 0 ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT;
@@ -99,11 +144,10 @@ _libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx,
(void) encrypt;
(void) algo;
- osize = blocklen+mbedtls_cipher_get_block_size(ctx);
+ osize = blocklen + mbedtls_cipher_get_block_size(ctx);
output = (unsigned char *)mbedtls_calloc(osize, sizeof(char));
- if(output)
- {
+ if(output) {
ret = mbedtls_cipher_reset(ctx);
if(!ret)
@@ -112,7 +156,7 @@ _libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx,
if(!ret)
ret = mbedtls_cipher_finish(ctx, output + olen, &finish_olen);
- if (!ret) {
+ if(!ret) {
olen += finish_olen;
memcpy(block, output, olen);
}
@@ -148,8 +192,8 @@ _libssh2_mbedtls_hash_init(mbedtls_md_context_t *ctx,
mbedtls_md_init(ctx);
ret = mbedtls_md_setup(ctx, md_info, hmac);
- if (!ret){
- if (hmac)
+ if(!ret) {
+ if(hmac)
ret = mbedtls_md_hmac_starts(ctx, key, keylen);
else
ret = mbedtls_md_starts(ctx);
@@ -196,50 +240,61 @@ _libssh2_mbedtls_bignum_init(void)
_libssh2_bn *bignum;
bignum = (_libssh2_bn *)mbedtls_calloc(1, sizeof(_libssh2_bn));
- if (bignum) {
+ if(bignum) {
mbedtls_mpi_init(bignum);
}
return bignum;
}
-int
+void
+_libssh2_mbedtls_bignum_free(_libssh2_bn *bn)
+{
+ if(bn) {
+ mbedtls_mpi_free(bn);
+ mbedtls_free(bn);
+ }
+}
+
+static int
_libssh2_mbedtls_bignum_random(_libssh2_bn *bn, int bits, int top, int bottom)
{
size_t len;
int err;
int i;
- if (!bn || bits <= 0)
+ if(!bn || bits <= 0)
return -1;
len = (bits + 7) >> 3;
- err = mbedtls_mpi_fill_random(bn, len, mbedtls_ctr_drbg_random, &_libssh2_mbedtls_ctr_drbg);
- if (err)
+ err = mbedtls_mpi_fill_random(bn, len, mbedtls_ctr_drbg_random,
+ &_libssh2_mbedtls_ctr_drbg);
+ if(err)
return -1;
/* Zero unsued bits above the most significant bit*/
- for(i=len*8-1;bits<=i;--i) {
+ for(i = len*8 - 1; bits <= i; --i) {
err = mbedtls_mpi_set_bit(bn, i, 0);
- if (err)
+ if(err)
return -1;
}
- /* If `top` is -1, the most significant bit of the random number can be zero.
- If top is 0, the most significant bit of the random number is set to 1,
- and if top is 1, the two most significant bits of the number will be set
- to 1, so that the product of two such random numbers will always have 2*bits length.
+ /* If `top` is -1, the most significant bit of the random number can be
+ zero. If top is 0, the most significant bit of the random number is
+ set to 1, and if top is 1, the two most significant bits of the number
+ will be set to 1, so that the product of two such random numbers will
+ always have 2*bits length.
*/
- for(i=0;i<=top;++i) {
+ for(i = 0; i <= top; ++i) {
err = mbedtls_mpi_set_bit(bn, bits-i-1, 1);
- if (err)
+ if(err)
return -1;
}
/* make odd by setting first bit in least significant byte */
- if (bottom) {
+ if(bottom) {
err = mbedtls_mpi_set_bit(bn, 0, 1);
- if (err)
+ if(err)
return -1;
}
@@ -275,42 +330,40 @@ _libssh2_mbedtls_rsa_new(libssh2_rsa_ctx **rsa,
libssh2_rsa_ctx *ctx;
ctx = (libssh2_rsa_ctx *) mbedtls_calloc(1, sizeof(libssh2_rsa_ctx));
- if (ctx != NULL) {
+ if(ctx != NULL) {
mbedtls_rsa_init(ctx, MBEDTLS_RSA_PKCS_V15, 0);
}
else
return -1;
- if( (ret = mbedtls_mpi_read_binary(&(ctx->E), edata, elen) ) != 0 ||
- (ret = mbedtls_mpi_read_binary(&(ctx->N), ndata, nlen) ) != 0 )
- {
+ /* !checksrc! disable ASSIGNWITHINCONDITION 1 */
+ if((ret = mbedtls_mpi_read_binary(&(ctx->E), edata, elen) ) != 0 ||
+ (ret = mbedtls_mpi_read_binary(&(ctx->N), ndata, nlen) ) != 0) {
ret = -1;
}
- if (!ret)
- {
+ if(!ret) {
ctx->len = mbedtls_mpi_size(&(ctx->N));
}
- if (!ret && ddata)
- {
- if( (ret = mbedtls_mpi_read_binary(&(ctx->D) , ddata, dlen) ) != 0 ||
- (ret = mbedtls_mpi_read_binary(&(ctx->P) , pdata, plen) ) != 0 ||
- (ret = mbedtls_mpi_read_binary(&(ctx->Q) , qdata, qlen) ) != 0 ||
- (ret = mbedtls_mpi_read_binary(&(ctx->DP), e1data, e1len) ) != 0 ||
- (ret = mbedtls_mpi_read_binary(&(ctx->DQ), e2data, e2len) ) != 0 ||
- (ret = mbedtls_mpi_read_binary(&(ctx->QP), coeffdata, coefflen) ) != 0 )
- {
+ if(!ret && ddata) {
+ /* !checksrc! disable ASSIGNWITHINCONDITION 1 */
+ if((ret = mbedtls_mpi_read_binary(&(ctx->D), ddata, dlen) ) != 0 ||
+ (ret = mbedtls_mpi_read_binary(&(ctx->P), pdata, plen) ) != 0 ||
+ (ret = mbedtls_mpi_read_binary(&(ctx->Q), qdata, qlen) ) != 0 ||
+ (ret = mbedtls_mpi_read_binary(&(ctx->DP), e1data, e1len) ) != 0 ||
+ (ret = mbedtls_mpi_read_binary(&(ctx->DQ), e2data, e2len) ) != 0 ||
+ (ret = mbedtls_mpi_read_binary(&(ctx->QP), coeffdata, coefflen) )
+ != 0) {
ret = -1;
}
ret = mbedtls_rsa_check_privkey(ctx);
}
- else if (!ret)
- {
+ else if(!ret) {
ret = mbedtls_rsa_check_pubkey(ctx);
}
- if (ret && ctx) {
+ if(ret && ctx) {
_libssh2_mbedtls_rsa_free(ctx);
ctx = NULL;
}
@@ -326,17 +379,17 @@ _libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa,
{
int ret;
mbedtls_pk_context pkey;
+ mbedtls_rsa_context *pk_rsa;
*rsa = (libssh2_rsa_ctx *) LIBSSH2_ALLOC(session, sizeof(libssh2_rsa_ctx));
- if (*rsa == NULL)
+ if(*rsa == NULL)
return -1;
mbedtls_rsa_init(*rsa, MBEDTLS_RSA_PKCS_V15, 0);
mbedtls_pk_init(&pkey);
ret = mbedtls_pk_parse_keyfile(&pkey, filename, (char *)passphrase);
- if( ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA)
- {
+ if(ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) {
mbedtls_pk_free(&pkey);
mbedtls_rsa_free(*rsa);
LIBSSH2_FREE(session, *rsa);
@@ -344,7 +397,7 @@ _libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa,
return -1;
}
- mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(pkey);
+ pk_rsa = mbedtls_pk_rsa(pkey);
mbedtls_rsa_copy(*rsa, pk_rsa);
mbedtls_pk_free(&pkey);
@@ -360,17 +413,33 @@ _libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
{
int ret;
mbedtls_pk_context pkey;
+ mbedtls_rsa_context *pk_rsa;
+ void *filedata_nullterm;
+ size_t pwd_len;
- *rsa = (libssh2_rsa_ctx *) mbedtls_calloc( 1, sizeof( libssh2_rsa_ctx ) );
- if (*rsa == NULL)
+ *rsa = (libssh2_rsa_ctx *) mbedtls_calloc(1, sizeof(libssh2_rsa_ctx));
+ if(*rsa == NULL)
return -1;
+ /*
+ mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'"
+ private-key from memory will fail if the last byte is not a null byte
+ */
+ filedata_nullterm = mbedtls_calloc(filedata_len + 1, 1);
+ if(filedata_nullterm == NULL) {
+ return -1;
+ }
+ memcpy(filedata_nullterm, filedata, filedata_len);
+
mbedtls_pk_init(&pkey);
- ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)filedata,
- filedata_len, NULL, 0);
- if( ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA)
- {
+ pwd_len = passphrase != NULL ? strlen((const char *)passphrase) : 0;
+ ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)filedata_nullterm,
+ filedata_len + 1,
+ passphrase, pwd_len);
+ _libssh2_mbedtls_safe_free(filedata_nullterm, filedata_len);
+
+ if(ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) {
mbedtls_pk_free(&pkey);
mbedtls_rsa_free(*rsa);
LIBSSH2_FREE(session, *rsa);
@@ -378,7 +447,7 @@ _libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
return -1;
}
- mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(pkey);
+ pk_rsa = mbedtls_pk_rsa(pkey);
mbedtls_rsa_copy(*rsa, pk_rsa);
mbedtls_pk_free(&pkey);
@@ -400,7 +469,8 @@ _libssh2_mbedtls_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
return -1; /* failure */
ret = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC,
- MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH, hash, sig);
+ MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH,
+ hash, sig);
return (ret == 0) ? 0 : -1;
}
@@ -421,14 +491,14 @@ _libssh2_mbedtls_rsa_sha1_sign(LIBSSH2_SESSION *session,
sig_len = rsa->len;
sig = LIBSSH2_ALLOC(session, sig_len);
- if (!sig) {
+ if(!sig) {
return -1;
}
ret = mbedtls_rsa_pkcs1_sign(rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH,
hash, sig);
- if (ret) {
+ if(ret) {
LIBSSH2_FREE(session, sig);
return -1;
}
@@ -453,8 +523,8 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session,
{
int e_bytes, n_bytes;
unsigned long len;
- unsigned char* key;
- unsigned char* p;
+ unsigned char *key;
+ unsigned char *p;
e_bytes = mbedtls_mpi_size(&rsa->E);
n_bytes = mbedtls_mpi_size(&rsa->N);
@@ -463,7 +533,7 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session,
len = 4 + 7 + 4 + e_bytes + 4 + n_bytes;
key = LIBSSH2_ALLOC(session, len);
- if (!key) {
+ if(!key) {
return NULL;
}
@@ -498,36 +568,38 @@ _libssh2_mbedtls_pub_priv_key(LIBSSH2_SESSION *session,
unsigned char *key = NULL, *mth = NULL;
size_t keylen = 0, mthlen = 0;
int ret;
+ mbedtls_rsa_context *rsa;
- if( mbedtls_pk_get_type(pkey) != MBEDTLS_PK_RSA )
- {
+ if(mbedtls_pk_get_type(pkey) != MBEDTLS_PK_RSA) {
mbedtls_pk_free(pkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Key type not supported");
}
- // write method
+ /* write method */
mthlen = 7;
mth = LIBSSH2_ALLOC(session, mthlen);
- if (mth) {
+ if(mth) {
memcpy(mth, "ssh-rsa", mthlen);
- } else {
+ }
+ else {
ret = -1;
}
- mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pkey);
+ rsa = mbedtls_pk_rsa(*pkey);
key = gen_publickey_from_rsa(session, rsa, &keylen);
- if (key == NULL) {
+ if(key == NULL) {
ret = -1;
}
- // write output
- if (ret) {
- if (mth)
+ /* write output */
+ if(ret) {
+ if(mth)
LIBSSH2_FREE(session, mth);
- if (key)
+ if(key)
LIBSSH2_FREE(session, key);
- } else {
+ }
+ else {
*method = mth;
*method_len = mthlen;
*pubkeydata = key;
@@ -552,8 +624,7 @@ _libssh2_mbedtls_pub_priv_keyfile(LIBSSH2_SESSION *session,
mbedtls_pk_init(&pkey);
ret = mbedtls_pk_parse_keyfile(&pkey, privatekey, passphrase);
- if( ret != 0 )
- {
+ if(ret != 0) {
mbedtls_strerror(ret, (char *)buf, sizeof(buf));
mbedtls_pk_free(&pkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE, buf);
@@ -580,12 +651,29 @@ _libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
mbedtls_pk_context pkey;
char buf[1024];
int ret;
+ void *privatekeydata_nullterm;
+ size_t pwd_len;
+
+ /*
+ mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'"
+ private-key from memory will fail if the last byte is not a null byte
+ */
+ privatekeydata_nullterm = mbedtls_calloc(privatekeydata_len + 1, 1);
+ if(privatekeydata_nullterm == NULL) {
+ return -1;
+ }
+ memcpy(privatekeydata_nullterm, privatekeydata, privatekeydata_len);
mbedtls_pk_init(&pkey);
- ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)privatekeydata,
- privatekeydata_len, NULL, 0);
- if( ret != 0 )
- {
+
+ pwd_len = passphrase != NULL ? strlen((const char *)passphrase) : 0;
+ ret = mbedtls_pk_parse_key(&pkey,
+ (unsigned char *)privatekeydata_nullterm,
+ privatekeydata_len + 1,
+ (const unsigned char *)passphrase, pwd_len);
+ _libssh2_mbedtls_safe_free(privatekeydata_nullterm, privatekeydata_len);
+
+ if(ret != 0) {
mbedtls_strerror(ret, (char *)buf, sizeof(buf));
mbedtls_pk_free(&pkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE, buf);
@@ -603,4 +691,43 @@ void _libssh2_init_aes_ctr(void)
{
/* no implementation */
}
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: Diffie-Hellman functions
+ */
+
+void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
+{
+ *dhctx = _libssh2_mbedtls_bignum_init(); /* Random from client */
+}
+
+int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+ _libssh2_bn *g, _libssh2_bn *p, int group_order)
+{
+ /* Generate x and e */
+ _libssh2_mbedtls_bignum_random(*dhctx, group_order * 8 - 1, 0, -1);
+ mbedtls_mpi_exp_mod(public, g, *dhctx, p, NULL);
+ return 0;
+}
+
+int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+ _libssh2_bn *f, _libssh2_bn *p)
+{
+ /* Compute the shared secret */
+ mbedtls_mpi_exp_mod(secret, f, *dhctx, p, NULL);
+ return 0;
+}
+
+void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
+{
+ _libssh2_mbedtls_bignum_free(*dhctx);
+ *dhctx = NULL;
+}
+
#endif /* LIBSSH2_MBEDTLS */
diff --git a/libs/libssh2/src/mbedtls.h b/libs/libssh2/src/mbedtls.h
index 248583ed3c..88b0e54d66 100644
--- a/libs/libssh2/src/mbedtls.h
+++ b/libs/libssh2/src/mbedtls.h
@@ -1,3 +1,40 @@
+/* Copyright (c) 2016, Art <https://github.com/wildart>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
#include <stdlib.h>
#include <string.h>
@@ -27,19 +64,21 @@
#define LIBSSH2_RSA 1
#define LIBSSH2_DSA 0
+#define LIBSSH2_ECDSA 0
+#define LIBSSH2_ED25519 0
#define MD5_DIGEST_LENGTH 16
#define SHA_DIGEST_LENGTH 20
#define SHA256_DIGEST_LENGTH 32
+#define SHA384_DIGEST_LENGTH 48
#define SHA512_DIGEST_LENGTH 64
-/*******************************************************************/
-/*
- * mbedTLS backend: Global context handles
- */
+#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
-mbedtls_entropy_context _libssh2_mbedtls_entropy;
-mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg;
+#if LIBSSH2_ECDSA
+#else
+#define _libssh2_ec_key void
+#endif
/*******************************************************************/
/*
@@ -80,6 +119,8 @@ mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg;
_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)
@@ -119,6 +160,23 @@ mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg;
/*******************************************************************/
/*
+ * mbedTLS backend: SHA384 functions
+ */
+
+#define libssh2_sha384_ctx mbedtls_md_context_t
+
+#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, (unsigned char *) data, datalen)
+#define libssh2_sha384_final(ctx, hash) \
+ _libssh2_mbedtls_hash_final(&ctx, hash)
+#define libssh2_sha384(data, datalen, hash) \
+ _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_SHA384, hash)
+
+
+/*******************************************************************/
+/*
* mbedTLS backend: SHA512 functions
*/
@@ -239,10 +297,6 @@ mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg;
_libssh2_mbedtls_bignum_init()
#define _libssh2_bn_init_from_bin() \
_libssh2_mbedtls_bignum_init()
-#define _libssh2_bn_rand(bn, bits, top, bottom) \
- _libssh2_mbedtls_bignum_random(bn, bits, top, bottom)
-#define _libssh2_bn_mod_exp(r, a, p, m, ctx) \
- mbedtls_mpi_exp_mod(r, a, p, m, NULL)
#define _libssh2_bn_set_word(bn, word) \
mbedtls_mpi_lset(bn, word)
#define _libssh2_bn_from_bin(bn, len, bin) \
@@ -254,7 +308,21 @@ mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg;
#define _libssh2_bn_bits(bn) \
mbedtls_mpi_bitlen(bn)
#define _libssh2_bn_free(bn) \
- mbedtls_mpi_free(bn)
+ _libssh2_mbedtls_bignum_free(bn)
+
+
+/*******************************************************************/
+/*
+ * mbedTLS backend: Diffie-Hellman support.
+ */
+
+#define _libssh2_dh_ctx mbedtls_mpi *
+#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
+ _libssh2_dh_key_pair(dhctx, public, g, p, group_order)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
+ _libssh2_dh_secret(dhctx, secret, f, p)
+#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx)
/*******************************************************************/
@@ -303,9 +371,6 @@ void
_libssh2_mbedtls_bignum_free(_libssh2_bn *bn);
int
-_libssh2_mbedtls_bignum_random(_libssh2_bn *bn, int bits, int top, int bottom);
-
-int
_libssh2_mbedtls_rsa_new(libssh2_rsa_ctx **rsa,
const unsigned char *edata,
unsigned long elen,
@@ -369,3 +434,14 @@ _libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
const char *privatekeydata,
size_t privatekeydata_len,
const char *passphrase);
+
+extern void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx);
+extern int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+ _libssh2_bn *g, _libssh2_bn *p, int group_order);
+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);
diff --git a/libs/libssh2/src/misc.c b/libs/libssh2/src/misc.c
index f7faae7b6a..bd084c854f 100644
--- a/libs/libssh2/src/misc.c
+++ b/libs/libssh2/src/misc.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
- * Copyright (c) 2009-2014 by Daniel Stenberg
+ * Copyright (c) 2009-2019 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson
* All rights reserved.
*
@@ -39,6 +39,11 @@
#include "libssh2_priv.h"
#include "misc.h"
+#include "blf.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -48,21 +53,28 @@
#include <sys/time.h>
#endif
+#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+#endif
+
#include <stdio.h>
#include <errno.h>
-int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errmsg, int errflags)
+int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode,
+ const char *errmsg, int errflags)
{
- if (session->err_flags & LIBSSH2_ERR_FLAG_DUP)
+ if(session->err_flags & LIBSSH2_ERR_FLAG_DUP)
LIBSSH2_FREE(session, (char *)session->err_msg);
session->err_code = errcode;
session->err_flags = 0;
- if ((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
+ if((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
size_t len = strlen(errmsg);
char *copy = LIBSSH2_ALLOC(session, len + 1);
- if (copy) {
+ if(copy) {
memcpy(copy, errmsg, len + 1);
session->err_flags = LIBSSH2_ERR_FLAG_DUP;
session->err_msg = copy;
@@ -86,7 +98,7 @@ int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errm
return errcode;
}
-int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
+int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg)
{
return _libssh2_error_flags(session, errcode, errmsg, 0);
}
@@ -94,7 +106,7 @@ int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
#ifdef WIN32
static int wsa2errno(void)
{
- switch (WSAGetLastError()) {
+ switch(WSAGetLastError()) {
case WSAEWOULDBLOCK:
return EAGAIN;
@@ -127,20 +139,20 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length,
rc = recv(sock, buffer, length, flags);
#ifdef WIN32
- if (rc < 0 )
+ if(rc < 0)
return -wsa2errno();
#elif defined(__VMS)
- if (rc < 0 ){
- if ( errno == EWOULDBLOCK )
+ if(rc < 0) {
+ if(errno == EWOULDBLOCK)
return -EAGAIN;
else
return -errno;
}
#else
- if (rc < 0 ){
+ if(rc < 0) {
/* Sometimes the first recv() function call sets errno to ENOENT on
Solaris and HP-UX */
- if ( errno == ENOENT )
+ if(errno == ENOENT)
return -EAGAIN;
else
return -errno;
@@ -163,17 +175,17 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
rc = send(sock, buffer, length, flags);
#ifdef WIN32
- if (rc < 0 )
+ if(rc < 0)
return -wsa2errno();
#elif defined(__VMS)
- if (rc < 0 ) {
- if ( errno == EWOULDBLOCK )
+ if(rc < 0) {
+ if(errno == EWOULDBLOCK)
return -EAGAIN;
else
return -errno;
}
#else
- if (rc < 0 )
+ if(rc < 0)
return -errno;
#endif
return rc;
@@ -269,15 +281,16 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
*data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
d = (unsigned char *) *data;
- if (!d) {
+ if(!d) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for base64 decoding");
}
for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
- if ((v = base64_reverse_table[*s]) < 0)
+ v = base64_reverse_table[*s];
+ if(v < 0)
continue;
- switch (i % 4) {
+ switch(i % 4) {
case 0:
d[len] = (unsigned char)(v << 2);
break;
@@ -295,10 +308,11 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
}
i++;
}
- if ((i % 4) == 1) {
+ if((i % 4) == 1) {
/* Invalid -- We have a byte which belongs exclusively to a partial
octet */
LIBSSH2_FREE(session, *data);
+ *data = NULL;
return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64");
}
@@ -321,68 +335,69 @@ static const char table64[]=
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
const char *inp, size_t insize, char **outptr)
{
- unsigned char ibuf[3];
- unsigned char obuf[4];
- int i;
- int inputparts;
- char *output;
- char *base64data;
- const char *indata = inp;
-
- *outptr = NULL; /* set to NULL in case of failure before we reach the end */
-
- if(0 == insize)
- insize = strlen(indata);
-
- base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4);
- if(NULL == output)
- return 0;
-
- while(insize > 0) {
- for (i = inputparts = 0; i < 3; i++) {
- if(insize > 0) {
- inputparts++;
- ibuf[i] = *indata;
- indata++;
- insize--;
- }
- else
- ibuf[i] = 0;
- }
+ unsigned char ibuf[3];
+ unsigned char obuf[4];
+ int i;
+ int inputparts;
+ char *output;
+ char *base64data;
+ const char *indata = inp;
+
+ *outptr = NULL; /* set to NULL in case of failure before we reach the
+ end */
+
+ if(0 == insize)
+ insize = strlen(indata);
+
+ base64data = output = LIBSSH2_ALLOC(session, insize * 4 / 3 + 4);
+ if(NULL == output)
+ return 0;
+
+ while(insize > 0) {
+ for(i = inputparts = 0; i < 3; i++) {
+ if(insize > 0) {
+ inputparts++;
+ ibuf[i] = *indata;
+ indata++;
+ insize--;
+ }
+ else
+ ibuf[i] = 0;
+ }
- obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
- obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
- ((ibuf[1] & 0xF0) >> 4));
- obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
- ((ibuf[2] & 0xC0) >> 6));
- obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
-
- switch(inputparts) {
- case 1: /* only one byte read */
- snprintf(output, 5, "%c%c==",
- table64[obuf[0]],
- table64[obuf[1]]);
- break;
- case 2: /* two bytes read */
- snprintf(output, 5, "%c%c%c=",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]]);
- break;
- default:
- snprintf(output, 5, "%c%c%c%c",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]],
- table64[obuf[3]] );
- break;
+ obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
+ obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
+ ((ibuf[1] & 0xF0) >> 4));
+ obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
+ ((ibuf[2] & 0xC0) >> 6));
+ obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
+
+ switch(inputparts) {
+ case 1: /* only one byte read */
+ snprintf(output, 5, "%c%c==",
+ table64[obuf[0]],
+ table64[obuf[1]]);
+ break;
+ case 2: /* two bytes read */
+ snprintf(output, 5, "%c%c%c=",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]]);
+ break;
+ default:
+ snprintf(output, 5, "%c%c%c%c",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]],
+ table64[obuf[3]]);
+ break;
+ }
+ output += 4;
}
- output += 4;
- }
- *output=0;
- *outptr = base64data; /* make it return the actual data memory */
+ *output = 0;
+ *outptr = base64data; /* make it return the actual data memory */
- return strlen(base64data); /* return the length of the new data */
+ return strlen(base64data); /* return the length of the new data */
}
/* ---- End of Base64 Encoding ---- */
@@ -403,7 +418,7 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
}
LIBSSH2_API int
-libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
+libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
libssh2_trace_handler_func callback)
{
session->tracehandler = callback;
@@ -431,18 +446,18 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
"Publickey",
"Socket",
};
- const char* contexttext = contexts[0];
+ const char *contexttext = contexts[0];
unsigned int contextindex;
- if (!(session->showmask & context)) {
+ if(!(session->showmask & context)) {
/* no such output asked for */
return;
}
/* Find the first matching context string for this message */
- for (contextindex = 0; contextindex < ARRAY_SIZE(contexts);
+ for(contextindex = 0; contextindex < ARRAY_SIZE(contexts);
contextindex++) {
- if ((context & (1 << contextindex)) != 0) {
+ if((context & (1 << contextindex)) != 0) {
contexttext = contexts[contextindex];
break;
}
@@ -457,7 +472,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ",
(int)now.tv_sec, (int)now.tv_usec, contexttext);
- if (len >= buflen)
+ if(len >= buflen)
msglen = buflen - 1;
else {
buflen -= len;
@@ -468,7 +483,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
msglen += len < buflen ? len : buflen - 1;
}
- if (session->tracehandler)
+ if(session->tracehandler)
(session->tracehandler)(session, session->tracehandler_context, buffer,
msglen);
else
@@ -485,7 +500,7 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
}
LIBSSH2_API int
-libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
+libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
libssh2_trace_handler_func callback)
{
(void) session;
@@ -615,21 +630,20 @@ void _libssh2_list_insert(struct list_node *after, /* insert before this */
#define _W32_FT_OFFSET (116444736000000000)
int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp)
- {
- union {
- unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
- FILETIME ft;
- } _now;
- (void)tzp;
- if(tp)
- {
- GetSystemTimeAsFileTime (&_now.ft);
- tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 );
- tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
+{
+ union {
+ unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
+ FILETIME ft;
+ } _now;
+ (void)tzp;
+ if(tp) {
+ GetSystemTimeAsFileTime(&_now.ft);
+ tp->tv_usec = (long)((_now.ns100 / 10) % 1000000);
+ tp->tv_sec = (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
}
- /* Always return 0 as per Open Group Base Specifications Issue 6.
- Do not set errno on error. */
- return 0;
+ /* Always return 0 as per Open Group Base Specifications Issue 6.
+ Do not set errno on error. */
+ return 0;
}
@@ -643,3 +657,218 @@ void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size)
}
return p;
}
+
+/* XOR operation on buffers input1 and input2, result in output.
+ It is safe to use an input buffer as the output buffer. */
+void _libssh2_xor_data(unsigned char *output,
+ const unsigned char *input1,
+ const unsigned char *input2,
+ size_t length)
+{
+ size_t i;
+
+ for(i = 0; i < length; i++)
+ *output++ = *input1++ ^ *input2++;
+}
+
+/* Increments an AES CTR buffer to prepare it for use with the
+ next AES block. */
+void _libssh2_aes_ctr_increment(unsigned char *ctr,
+ size_t length)
+{
+ unsigned char *pc;
+ unsigned int val, carry;
+
+ pc = ctr + length - 1;
+ carry = 1;
+
+ while(pc >= ctr) {
+ val = (unsigned int)*pc + carry;
+ *pc-- = val & 0xFF;
+ carry = val >> 8;
+ }
+}
+
+#ifdef WIN32
+static void * (__cdecl * const volatile memset_libssh)(void *, int, size_t) =
+ memset;
+#else
+static void * (* const volatile memset_libssh)(void *, int, size_t) = memset;
+#endif
+
+void _libssh2_explicit_zero(void *buf, size_t size)
+{
+#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
+ SecureZeroMemory(buf, size);
+ (void)memset_libssh; /* Silence unused variable warning */
+#elif defined(HAVE_MEMSET_S)
+ (void)memset_s(buf, size, 0, size);
+ (void)memset_libssh; /* Silence unused variable warning */
+#else
+ memset_libssh(buf, 0, size);
+#endif
+}
+
+/* String buffer */
+
+struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session)
+{
+ struct string_buf *ret;
+
+ ret = _libssh2_calloc(session, sizeof(*ret));
+ if(ret == NULL)
+ return NULL;
+
+ return ret;
+}
+
+void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf)
+{
+ if(buf == NULL)
+ return;
+
+ if(buf->data != NULL)
+ LIBSSH2_FREE(session, buf->data);
+
+ LIBSSH2_FREE(session, buf);
+ buf = NULL;
+}
+
+int _libssh2_get_u32(struct string_buf *buf, uint32_t *out)
+{
+ if(!_libssh2_check_length(buf, 4)) {
+ return -1;
+ }
+
+ *out = _libssh2_ntohu32(buf->dataptr);
+ buf->dataptr += 4;
+ return 0;
+}
+
+int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out)
+{
+ if(!_libssh2_check_length(buf, 8)) {
+ return -1;
+ }
+
+ *out = _libssh2_ntohu64(buf->dataptr);
+ buf->dataptr += 8;
+ return 0;
+}
+
+int _libssh2_match_string(struct string_buf *buf, const char *match)
+{
+ unsigned char *out;
+ size_t len = 0;
+ if(_libssh2_get_string(buf, &out, &len) || len != strlen(match) ||
+ strncmp((char *)out, match, strlen(match)) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
+ size_t *outlen)
+{
+ uint32_t data_len;
+ if(_libssh2_get_u32(buf, &data_len) != 0) {
+ return -1;
+ }
+ if(!_libssh2_check_length(buf, data_len)) {
+ return -1;
+ }
+ *outbuf = buf->dataptr;
+ buf->dataptr += data_len;
+
+ if(outlen)
+ *outlen = (size_t)data_len;
+
+ return 0;
+}
+
+int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf,
+ unsigned char **outbuf, size_t *outlen)
+{
+ size_t str_len;
+ unsigned char *str;
+
+ if(_libssh2_get_string(buf, &str, &str_len)) {
+ return -1;
+ }
+
+ *outbuf = LIBSSH2_ALLOC(session, str_len);
+ if(*outbuf) {
+ memcpy(*outbuf, str, str_len);
+ }
+ else {
+ return -1;
+ }
+
+ if(outlen)
+ *outlen = str_len;
+
+ return 0;
+}
+
+int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
+ size_t *outlen)
+{
+ uint32_t data_len;
+ uint32_t bn_len;
+ unsigned char *bnptr;
+
+ if(_libssh2_get_u32(buf, &data_len)) {
+ return -1;
+ }
+ if(!_libssh2_check_length(buf, data_len)) {
+ return -1;
+ }
+
+ bn_len = data_len;
+ bnptr = buf->dataptr;
+
+ /* trim leading zeros */
+ while(bn_len > 0 && *bnptr == 0x00) {
+ bn_len--;
+ bnptr++;
+ }
+
+ *outbuf = bnptr;
+ buf->dataptr += data_len;
+
+ if(outlen)
+ *outlen = (size_t)bn_len;
+
+ return 0;
+}
+
+/* Given the current location in buf, _libssh2_check_length ensures
+ callers can read the next len number of bytes out of the buffer
+ before reading the buffer content */
+
+int _libssh2_check_length(struct string_buf *buf, size_t len)
+{
+ unsigned char *endp = &buf->data[buf->len];
+ size_t left = endp - buf->dataptr;
+ return ((len <= left) && (left <= buf->len));
+}
+
+/* Wrappers */
+
+int _libssh2_bcrypt_pbkdf(const char *pass,
+ size_t passlen,
+ const uint8_t *salt,
+ size_t saltlen,
+ uint8_t *key,
+ size_t keylen,
+ unsigned int rounds)
+{
+ /* defined in bcrypt_pbkdf.c */
+ return bcrypt_pbkdf(pass,
+ passlen,
+ salt,
+ saltlen,
+ key,
+ keylen,
+ rounds);
+}
diff --git a/libs/libssh2/src/misc.h b/libs/libssh2/src/misc.h
index 54ae5461d6..5481e666ca 100644
--- a/libs/libssh2/src/misc.h
+++ b/libs/libssh2/src/misc.h
@@ -1,6 +1,6 @@
#ifndef __LIBSSH2_MISC_H
#define __LIBSSH2_MISC_H
-/* Copyright (c) 2009-2014 by Daniel Stenberg
+/* Copyright (c) 2009-2019 by Daniel Stenberg
*
* All rights reserved.
*
@@ -49,8 +49,15 @@ struct list_node {
struct list_head *head;
};
-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);
+struct string_buf {
+ unsigned char *data;
+ unsigned char *dataptr;
+ size_t len;
+};
+
+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);
void _libssh2_list_init(struct list_head *head);
@@ -70,7 +77,7 @@ void *_libssh2_list_prev(struct list_node *node);
/* remove this node from the list */
void _libssh2_list_remove(struct list_node *entry);
-size_t _libssh2_base64_encode(struct _LIBSSH2_SESSION *session,
+size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
const char *inp, size_t insize, char **outptr);
unsigned int _libssh2_ntohu32(const unsigned char *buf);
@@ -78,7 +85,22 @@ 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_str(unsigned char **buf, const char *str, size_t len);
-void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size);
+void *_libssh2_calloc(LIBSSH2_SESSION *session, size_t size);
+void _libssh2_explicit_zero(void *buf, size_t size);
+
+struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session);
+void _libssh2_string_buf_free(LIBSSH2_SESSION *session,
+ struct string_buf *buf);
+int _libssh2_get_u32(struct string_buf *buf, uint32_t *out);
+int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out);
+int _libssh2_match_string(struct string_buf *buf, const char *match);
+int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
+ size_t *outlen);
+int _libssh2_copy_string(LIBSSH2_SESSION* session, struct string_buf *buf,
+ unsigned char **outbuf, size_t *outlen);
+int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
+ size_t *outlen);
+int _libssh2_check_length(struct string_buf *buf, size_t requested_len);
#if defined(LIBSSH2_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
/* provide a private one */
@@ -93,4 +115,11 @@ int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp);
#endif
#endif
+void _libssh2_xor_data(unsigned char *output,
+ const unsigned char *input1,
+ const unsigned char *input2,
+ size_t length);
+
+void _libssh2_aes_ctr_increment(unsigned char *ctr, size_t length);
+
#endif /* _LIBSSH2_MISC_H */
diff --git a/libs/libssh2/src/openssl.c b/libs/libssh2/src/openssl.c
index 4f63ef92bc..04d5ec2ffd 100644
--- a/libs/libssh2/src/openssl.c
+++ b/libs/libssh2/src/openssl.c
@@ -43,12 +43,38 @@
#ifdef LIBSSH2_OPENSSL /* compile only if we build with openssl */
#include <string.h>
+#include "misc.h"
#ifndef EVP_MAX_BLOCK_LENGTH
#define EVP_MAX_BLOCK_LENGTH 32
#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);
+
+static unsigned char *
+write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes)
+{
+ unsigned char *p = buf;
+
+ /* Left space for bn size which will be written below. */
+ p += 4;
+
+ *p = 0;
+ BN_bn2bin(bn, p + 1);
+ if(!(*(p + 1) & 0x80)) {
+ memmove(p, p + 1, --bn_bytes);
+ }
+ _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */
+
+ return p + bn_bytes;
+}
+
+int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
unsigned long elen,
@@ -81,7 +107,7 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
n = BN_new();
BN_bin2bn(ndata, nlen, n);
- if (ddata) {
+ if(ddata) {
d = BN_new();
BN_bin2bn(ddata, dlen, d);
@@ -107,6 +133,7 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
#else
(*rsa)->e = e;
(*rsa)->n = n;
+ (*rsa)->d = d;
#endif
#ifdef HAVE_OPAQUE_STRUCTS
@@ -135,7 +162,7 @@ _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx,
unsigned char hash[SHA_DIGEST_LENGTH];
int ret;
- if (_libssh2_sha1(m, m_len, hash))
+ if(_libssh2_sha1(m, m_len, hash))
return -1; /* failure */
ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
(unsigned char *) sig, sig_len, rsactx);
@@ -173,7 +200,7 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
pub_key = BN_new();
BN_bin2bn(y, y_len, pub_key);
- if (x_len) {
+ if(x_len) {
priv_key = BN_new();
BN_bin2bn(x, x_len, priv_key);
}
@@ -220,7 +247,7 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
dsasig->r = r;
dsasig->s = s;
#endif
- if (!_libssh2_sha1(m, m_len, hash))
+ if(!_libssh2_sha1(m, m_len, hash))
/* _libssh2_sha1() succeeded */
ret = DSA_do_verify(hash, SHA_DIGEST_LENGTH, dsasig, dsactx);
@@ -230,6 +257,147 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
}
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+
+/* _libssh2_ecdsa_key_get_curve_type
+ *
+ * returns key curve type that maps to libssh2_curve_type
+ *
+ */
+
+libssh2_curve_type
+_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key)
+{
+ const EC_GROUP *group = EC_KEY_get0_group(key);
+ return EC_GROUP_get_curve_name(group);
+}
+
+/* _libssh2_ecdsa_curve_type_from_name
+ *
+ * returns 0 for success, key curve type that maps to libssh2_curve_type
+ *
+ */
+
+int
+_libssh2_ecdsa_curve_type_from_name(const char *name,
+ libssh2_curve_type *out_type)
+{
+ int ret = 0;
+ libssh2_curve_type type;
+
+ if(name == NULL || strlen(name) != 19)
+ return -1;
+
+ if(strcmp(name, "ecdsa-sha2-nistp256") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP256;
+ else if(strcmp(name, "ecdsa-sha2-nistp384") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP384;
+ else if(strcmp(name, "ecdsa-sha2-nistp521") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP521;
+ else {
+ ret = -1;
+ }
+
+ if(ret == 0 && out_type) {
+ *out_type = type;
+ }
+
+ return ret;
+}
+
+/* _libssh2_ecdsa_curve_name_with_octal_new
+ *
+ * Creates a new public key given an octal string, length and type
+ *
+ */
+
+int
+_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;
+ EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve);
+ EC_POINT *point = NULL;
+
+ if(ec_key) {
+ 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 != NULL)
+ EC_POINT_free(point);
+
+ if(ec_ctx != NULL)
+ *ec_ctx = ec_key;
+ }
+
+ return (ret == 1) ? 0 : -1;
+}
+
+#define LIBSSH2_ECDSA_VERIFY(digest_type) \
+{ \
+ 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); \
+ \
+}
+
+int
+_libssh2_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 ret = 0;
+ EC_KEY *ec_key = (EC_KEY*)ctx;
+ libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_key);
+
+#ifdef HAVE_OPAQUE_STRUCTS
+ ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new();
+ BIGNUM *pr = BN_new();
+ BIGNUM *ps = BN_new();
+
+ BN_bin2bn(r, r_len, pr);
+ BN_bin2bn(s, s_len, ps);
+ ECDSA_SIG_set0(ecdsa_sig, pr, ps);
+
+#else
+ ECDSA_SIG ecdsa_sig_;
+ ECDSA_SIG *ecdsa_sig = &ecdsa_sig_;
+ ecdsa_sig_.r = BN_new();
+ BN_bin2bn(r, r_len, ecdsa_sig_.r);
+ ecdsa_sig_.s = BN_new();
+ BN_bin2bn(s, s_len, ecdsa_sig_.s);
+#endif
+
+ if(type == LIBSSH2_EC_CURVE_NISTP256) {
+ LIBSSH2_ECDSA_VERIFY(256);
+ }
+ else if(type == LIBSSH2_EC_CURVE_NISTP384) {
+ LIBSSH2_ECDSA_VERIFY(384);
+ }
+ else if(type == LIBSSH2_EC_CURVE_NISTP521) {
+ LIBSSH2_ECDSA_VERIFY(512);
+ }
+
+#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);
+#endif
+
+ return (ret == 1) ? 0 : -1;
+}
+
+#endif /* LIBSSH2_ECDSA */
+
int
_libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo),
@@ -259,7 +427,7 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
#else
ret = EVP_Cipher(ctx, buf, block, blocksize);
#endif
- if (ret == 1) {
+ if(ret == 1) {
memcpy(block, buf, blocksize);
}
return ret == 1 ? 0 : 1;
@@ -289,7 +457,7 @@ aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const EVP_CIPHER *aes_cipher;
(void) enc;
- switch (EVP_CIPHER_CTX_key_length(ctx)) {
+ switch(EVP_CIPHER_CTX_key_length(ctx)) {
case 16:
aes_cipher = EVP_aes_128_ecb();
break;
@@ -304,7 +472,7 @@ aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
}
c = malloc(sizeof(*c));
- if (c == NULL)
+ if(c == NULL)
return 0;
#ifdef HAVE_OPAQUE_STRUCTS
@@ -312,12 +480,12 @@ aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
#else
c->aes_ctx = malloc(sizeof(EVP_CIPHER_CTX));
#endif
- if (c->aes_ctx == NULL) {
+ if(c->aes_ctx == NULL) {
free(c);
return 0;
}
- if (EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) {
+ if(EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) {
#ifdef HAVE_OPAQUE_STRUCTS
EVP_CIPHER_CTX_free(c->aes_ctx);
#else
@@ -343,13 +511,12 @@ aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
{
aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx);
unsigned char b1[AES_BLOCK_SIZE];
- size_t i = 0;
int outlen = 0;
- if (inl != 16) /* libssh2 only ever encrypt one block */
+ if(inl != 16) /* libssh2 only ever encrypt one block */
return 0;
- if (c == NULL) {
+ if(c == NULL) {
return 0;
}
@@ -360,19 +527,13 @@ aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
the ciphertext block C1. The counter X is then incremented
*/
- if (EVP_EncryptUpdate(c->aes_ctx, b1, &outlen, c->ctr, AES_BLOCK_SIZE) != 1) {
+ if(EVP_EncryptUpdate(c->aes_ctx, b1, &outlen,
+ c->ctr, AES_BLOCK_SIZE) != 1) {
return 0;
}
- for (i = 0; i < 16; i++)
- *out++ = *in++ ^ b1[i];
-
- i = 15;
- while (c->ctr[i]++ == 0xFF) {
- if (i == 0)
- break;
- i--;
- }
+ _libssh2_xor_data(out, in, b1, AES_BLOCK_SIZE);
+ _libssh2_aes_ctr_increment(c->ctr, AES_BLOCK_SIZE);
return 1;
}
@@ -382,11 +543,11 @@ aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */
{
aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx);
- if (c == NULL) {
+ if(c == NULL) {
return 1;
}
- if (c->aes_ctx != NULL) {
+ if(c->aes_ctx != NULL) {
#ifdef HAVE_OPAQUE_STRUCTS
EVP_CIPHER_CTX_free(c->aes_ctx);
#else
@@ -401,27 +562,27 @@ aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */
}
static const EVP_CIPHER *
-make_ctr_evp (size_t keylen, EVP_CIPHER *aes_ctr_cipher, int type)
+make_ctr_evp (size_t keylen, EVP_CIPHER **aes_ctr_cipher, int type)
{
#ifdef HAVE_OPAQUE_STRUCTS
- aes_ctr_cipher = EVP_CIPHER_meth_new(type, 16, keylen);
- if (aes_ctr_cipher) {
- EVP_CIPHER_meth_set_iv_length(aes_ctr_cipher, 16);
- EVP_CIPHER_meth_set_init(aes_ctr_cipher, aes_ctr_init);
- EVP_CIPHER_meth_set_do_cipher(aes_ctr_cipher, aes_ctr_do_cipher);
- EVP_CIPHER_meth_set_cleanup(aes_ctr_cipher, aes_ctr_cleanup);
+ *aes_ctr_cipher = EVP_CIPHER_meth_new(type, 16, keylen);
+ if(*aes_ctr_cipher) {
+ EVP_CIPHER_meth_set_iv_length(*aes_ctr_cipher, 16);
+ EVP_CIPHER_meth_set_init(*aes_ctr_cipher, aes_ctr_init);
+ EVP_CIPHER_meth_set_do_cipher(*aes_ctr_cipher, aes_ctr_do_cipher);
+ EVP_CIPHER_meth_set_cleanup(*aes_ctr_cipher, aes_ctr_cleanup);
}
#else
- aes_ctr_cipher->nid = type;
- aes_ctr_cipher->block_size = 16;
- aes_ctr_cipher->key_len = keylen;
- aes_ctr_cipher->iv_len = 16;
- aes_ctr_cipher->init = aes_ctr_init;
- aes_ctr_cipher->do_cipher = aes_ctr_do_cipher;
- aes_ctr_cipher->cleanup = aes_ctr_cleanup;
+ (*aes_ctr_cipher)->nid = type;
+ (*aes_ctr_cipher)->block_size = 16;
+ (*aes_ctr_cipher)->key_len = keylen;
+ (*aes_ctr_cipher)->iv_len = 16;
+ (*aes_ctr_cipher)->init = aes_ctr_init;
+ (*aes_ctr_cipher)->do_cipher = aes_ctr_do_cipher;
+ (*aes_ctr_cipher)->cleanup = aes_ctr_cleanup;
#endif
- return aes_ctr_cipher;
+ return *aes_ctr_cipher;
}
const EVP_CIPHER *
@@ -429,12 +590,13 @@ _libssh2_EVP_aes_128_ctr(void)
{
#ifdef HAVE_OPAQUE_STRUCTS
static EVP_CIPHER * aes_ctr_cipher;
- return !aes_ctr_cipher?
- make_ctr_evp (16, aes_ctr_cipher, NID_aes_128_ctr) : aes_ctr_cipher;
+ return !aes_ctr_cipher ?
+ make_ctr_evp(16, &aes_ctr_cipher, NID_aes_128_ctr) : aes_ctr_cipher;
#else
static EVP_CIPHER aes_ctr_cipher;
- return !aes_ctr_cipher.key_len?
- make_ctr_evp (16, &aes_ctr_cipher, 0) : &aes_ctr_cipher;
+ static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
+ return !aes_ctr_cipher.key_len ?
+ make_ctr_evp(16, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher;
#endif
}
@@ -443,12 +605,13 @@ _libssh2_EVP_aes_192_ctr(void)
{
#ifdef HAVE_OPAQUE_STRUCTS
static EVP_CIPHER * aes_ctr_cipher;
- return !aes_ctr_cipher?
- make_ctr_evp (24, aes_ctr_cipher, NID_aes_192_ctr) : aes_ctr_cipher;
+ return !aes_ctr_cipher ?
+ make_ctr_evp(24, &aes_ctr_cipher, NID_aes_192_ctr) : aes_ctr_cipher;
#else
static EVP_CIPHER aes_ctr_cipher;
- return !aes_ctr_cipher.key_len?
- make_ctr_evp (24, &aes_ctr_cipher, 0) : &aes_ctr_cipher;
+ static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
+ return !aes_ctr_cipher.key_len ?
+ make_ctr_evp(24, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher;
#endif
}
@@ -457,25 +620,70 @@ _libssh2_EVP_aes_256_ctr(void)
{
#ifdef HAVE_OPAQUE_STRUCTS
static EVP_CIPHER * aes_ctr_cipher;
- return !aes_ctr_cipher?
- make_ctr_evp (32, aes_ctr_cipher, NID_aes_256_ctr) : aes_ctr_cipher;
+ return !aes_ctr_cipher ?
+ make_ctr_evp(32, &aes_ctr_cipher, NID_aes_256_ctr) : aes_ctr_cipher;
#else
static EVP_CIPHER aes_ctr_cipher;
- return !aes_ctr_cipher.key_len?
- make_ctr_evp (32, &aes_ctr_cipher, 0) : &aes_ctr_cipher;
+ static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
+ return !aes_ctr_cipher.key_len ?
+ make_ctr_evp(32, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher;
#endif
}
-void _libssh2_init_aes_ctr(void)
+#endif /* LIBSSH2_AES_CTR */
+
+#ifndef HAVE_EVP_AES_128_CTR
+static EVP_CIPHER * aes_128_ctr_cipher = NULL;
+static EVP_CIPHER * aes_192_ctr_cipher = NULL;
+static EVP_CIPHER * aes_256_ctr_cipher = NULL;
+#endif
+
+void _libssh2_openssl_crypto_init(void)
{
- _libssh2_EVP_aes_128_ctr();
- _libssh2_EVP_aes_192_ctr();
- _libssh2_EVP_aes_256_ctr();
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !defined(LIBRESSL_VERSION_NUMBER)
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_load_builtin_engines();
+ ENGINE_register_all_complete();
+#endif
+#else
+ OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_ciphers();
+ OpenSSL_add_all_digests();
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_load_builtin_engines();
+ ENGINE_register_all_complete();
+#endif
+#endif
+#ifndef HAVE_EVP_AES_128_CTR
+ aes_128_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_128_ctr();
+ aes_192_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_192_ctr();
+ aes_256_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_256_ctr();
+#endif
}
-#else
-void _libssh2_init_aes_ctr(void) {}
-#endif /* LIBSSH2_AES_CTR */
+void _libssh2_openssl_crypto_exit(void)
+{
+#ifndef HAVE_EVP_AES_128_CTR
+#ifdef HAVE_OPAQUE_STRUCTS
+ if(aes_128_ctr_cipher) {
+ EVP_CIPHER_meth_free(aes_128_ctr_cipher);
+ }
+
+ if(aes_192_ctr_cipher) {
+ EVP_CIPHER_meth_free(aes_192_ctr_cipher);
+ }
+
+ if(aes_256_ctr_cipher) {
+ EVP_CIPHER_meth_free(aes_256_ctr_cipher);
+ }
+#endif
+
+ aes_128_ctr_cipher = NULL;
+ aes_192_ctr_cipher = NULL;
+ aes_256_ctr_cipher = NULL;
+#endif
+}
/* TODO: Optionally call a passphrase callback specified by the
* calling program
@@ -486,7 +694,7 @@ passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
int passphrase_len = strlen(passphrase);
(void) rwflag;
- if (passphrase_len > (size - 1)) {
+ if(passphrase_len > (size - 1)) {
passphrase_len = size - 1;
}
memcpy(buf, passphrase, passphrase_len);
@@ -496,12 +704,12 @@ passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
}
typedef void * (*pem_read_bio_func)(BIO *, void **, pem_password_cb *,
- void * u);
+ void *u);
static int
-read_private_key_from_memory(void ** key_ctx,
+read_private_key_from_memory(void **key_ctx,
pem_read_bio_func read_private_key,
- const char * filedata,
+ const char *filedata,
size_t filedata_len,
unsigned const char *passphrase)
{
@@ -510,7 +718,7 @@ read_private_key_from_memory(void ** key_ctx,
*key_ctx = NULL;
bp = BIO_new_mem_buf((char *)filedata, filedata_len);
- if (!bp) {
+ if(!bp) {
return -1;
}
*key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb,
@@ -520,10 +728,12 @@ read_private_key_from_memory(void ** key_ctx,
return (*key_ctx) ? 0 : -1;
}
+
+
static int
-read_private_key_from_file(void ** key_ctx,
+read_private_key_from_file(void **key_ctx,
pem_read_bio_func read_private_key,
- const char * filename,
+ const char *filename,
unsigned const char *passphrase)
{
BIO * bp;
@@ -531,7 +741,7 @@ read_private_key_from_file(void ** key_ctx,
*key_ctx = NULL;
bp = BIO_new_file(filename, "r");
- if (!bp) {
+ if(!bp) {
return -1;
}
@@ -548,14 +758,350 @@ _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
const char *filedata, size_t filedata_len,
unsigned const char *passphrase)
{
+ int rc;
+
pem_read_bio_func read_rsa =
(pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
(void) session;
_libssh2_init_if_needed();
- return 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);
+ }
+
+return rc;
+}
+
+static unsigned char *
+gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa,
+ size_t *key_len)
+{
+ int e_bytes, n_bytes;
+ unsigned long len;
+ unsigned char *key;
+ unsigned char *p;
+ const BIGNUM * e;
+ const BIGNUM * n;
+#ifdef HAVE_OPAQUE_STRUCTS
+ RSA_get0_key(rsa, &n, &e, NULL);
+#else
+ e = rsa->e;
+ n = rsa->n;
+#endif
+ e_bytes = BN_num_bytes(e) + 1;
+ n_bytes = BN_num_bytes(n) + 1;
+
+ /* Key form is "ssh-rsa" + e + n. */
+ len = 4 + 7 + 4 + e_bytes + 4 + n_bytes;
+
+ key = LIBSSH2_ALLOC(session, len);
+ if(key == NULL) {
+ return NULL;
+ }
+
+ /* Process key encoding. */
+ p = key;
+
+ _libssh2_htonu32(p, 7); /* Key type. */
+ p += 4;
+ memcpy(p, "ssh-rsa", 7);
+ p += 7;
+
+ p = write_bn(p, e, e_bytes);
+ p = write_bn(p, n, n_bytes);
+
+ *key_len = (size_t)(p - key);
+ return key;
+}
+
+static int
+gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ EVP_PKEY *pk)
+{
+ RSA* rsa = NULL;
+ unsigned char *key;
+ unsigned char *method_buf = NULL;
+ size_t key_len;
+
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Computing public key from RSA private key envelop");
+
+ rsa = EVP_PKEY_get1_RSA(pk);
+ if(rsa == NULL) {
+ /* Assume memory allocation error... what else could it be ? */
+ goto __alloc_error;
+ }
+
+ method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-rsa. */
+ if(method_buf == NULL) {
+ goto __alloc_error;
+ }
+
+ key = gen_publickey_from_rsa(session, rsa, &key_len);
+ if(key == NULL) {
+ goto __alloc_error;
+ }
+ RSA_free(rsa);
+
+ memcpy(method_buf, "ssh-rsa", 7);
+ *method = method_buf;
+ *method_len = 7;
+ *pubkeydata = key;
+ *pubkeydata_len = key_len;
+ return 0;
+
+ __alloc_error:
+ if(rsa != NULL) {
+ RSA_free(rsa);
+ }
+ if(method_buf != NULL) {
+ LIBSSH2_FREE(session, method_buf);
+ }
+
+ return _libssh2_error(session,
+ LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for private key data");
+}
+
+static int _libssh2_rsa_new_additional_parameters(RSA *rsa)
+{
+ BN_CTX *ctx = NULL;
+ BIGNUM *aux = NULL;
+ BIGNUM *dmp1 = NULL;
+ BIGNUM *dmq1 = NULL;
+ const BIGNUM *p = NULL;
+ const BIGNUM *q = NULL;
+ const BIGNUM *d = NULL;
+ int rc = 0;
+
+#ifdef HAVE_OPAQUE_STRUCTS
+ RSA_get0_key(rsa, NULL, NULL, &d);
+ RSA_get0_factors(rsa, &p, &q);
+#else
+ d = (*rsa).d;
+ p = (*rsa).p;
+ q = (*rsa).q;
+#endif
+
+ ctx = BN_CTX_new();
+ if(ctx == NULL)
+ return -1;
+
+ aux = BN_new();
+ if(aux == NULL) {
+ rc = -1;
+ goto out;
+ }
+
+ dmp1 = BN_new();
+ if(dmp1 == NULL) {
+ rc = -1;
+ goto out;
+ }
+
+ dmq1 = BN_new();
+ if(dmq1 == NULL) {
+ rc = -1;
+ goto out;
+ }
+
+ if((BN_sub(aux, q, BN_value_one()) == 0) ||
+ (BN_mod(dmq1, d, aux, ctx) == 0) ||
+ (BN_sub(aux, p, BN_value_one()) == 0) ||
+ (BN_mod(dmp1, d, aux, ctx) == 0)) {
+ rc = -1;
+ goto out;
+ }
+
+#ifdef HAVE_OPAQUE_STRUCTS
+ RSA_set0_crt_params(rsa, dmp1, dmq1, NULL);
+#else
+ (*rsa).dmp1 = dmp1;
+ (*rsa).dmq1 = dmq1;
+#endif
+
+out:
+ if(aux)
+ BN_clear_free(aux);
+ BN_CTX_free(ctx);
+
+ if(rc != 0) {
+ if(dmp1)
+ BN_clear_free(dmp1);
+ if(dmq1)
+ BN_clear_free(dmq1);
+ }
+
+ return rc;
+}
+
+static int
+gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session,
+ struct string_buf *decrypted,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ libssh2_rsa_ctx **rsa_ctx)
+{
+ 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_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Computing RSA keys from private key data");
+
+ /* public key data */
+ if(_libssh2_get_bignum_bytes(decrypted, &n, &nlen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "RSA no n");
+ return -1;
+ }
+
+ if(_libssh2_get_bignum_bytes(decrypted, &e, &elen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "RSA no e");
+ return -1;
+ }
+
+ /* private key data */
+ if(_libssh2_get_bignum_bytes(decrypted, &d, &dlen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "RSA no d");
+ return -1;
+ }
+
+ if(_libssh2_get_bignum_bytes(decrypted, &coeff, &coefflen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "RSA no coeff");
+ return -1;
+ }
+
+ if(_libssh2_get_bignum_bytes(decrypted, &p, &plen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "RSA no p");
+ return -1;
+ }
+
+ if(_libssh2_get_bignum_bytes(decrypted, &q, &qlen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "RSA no q");
+ return -1;
+ }
+
+ if(_libssh2_get_string(decrypted, &comment, &commentlen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "RSA no comment");
+ return -1;
+ }
+
+ if((rc = _libssh2_rsa_new(&rsa, e, elen, n, nlen, d, dlen, p, plen,
+ q, qlen, NULL, 0, NULL, 0,
+ coeff, coefflen)) != 0) {
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Could not create RSA private key");
+ goto fail;
+ }
+
+ if(rsa != NULL)
+ rc = _libssh2_rsa_new_additional_parameters(rsa);
+
+ if(rsa != NULL && pubkeydata != NULL && method != NULL) {
+ EVP_PKEY *pk = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pk, rsa);
+
+ rc = gen_publickey_from_rsa_evp(session, method, method_len,
+ pubkeydata, pubkeydata_len,
+ pk);
+
+ if(pk)
+ EVP_PKEY_free(pk);
+ }
+
+ if(rsa_ctx != NULL)
+ *rsa_ctx = rsa;
+ else
+ RSA_free(rsa);
+
+ return rc;
+
+fail:
+
+ if(rsa != NULL)
+ RSA_free(rsa);
+
+ return _libssh2_error(session,
+ LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for private key data");
+}
+
+static int
+_libssh2_rsa_new_openssh_private(libssh2_rsa_ctx ** rsa,
+ LIBSSH2_SESSION * session,
+ const char *filename,
+ unsigned const char *passphrase)
+{
+ FILE *fp;
+ int rc;
+ unsigned char *buf = NULL;
+ struct string_buf *decrypted = NULL;
+
+ if(session == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Session is required");
+ return -1;
+ }
+
+ _libssh2_init_if_needed();
+
+ fp = fopen(filename, "r");
+ if(!fp) {
+ _libssh2_error(session, LIBSSH2_ERROR_FILE,
+ "Unable to open OpenSSH RSA private key file");
+ return -1;
+ }
+
+ rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted);
+ fclose(fp);
+ if(rc) {
+ return rc;
+ }
+
+ /* We have a new key file, now try and parse it using supported types */
+ rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+ if(rc != 0 || buf == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Public key type in decrypted key data not found");
+ return -1;
+ }
+
+ if(strcmp("ssh-rsa", (const char *)buf) == 0) {
+ rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted,
+ NULL, 0,
+ NULL, 0, rsa);
+ }
+ else {
+ rc = -1;
+ }
+
+ if(decrypted)
+ _libssh2_string_buf_free(session, decrypted);
+
+ return rc;
}
int
@@ -563,14 +1109,23 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
const char *filename, unsigned const char *passphrase)
{
+ int rc;
+
pem_read_bio_func read_rsa =
(pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
(void) session;
- _libssh2_init_if_needed ();
+ _libssh2_init_if_needed();
+
+ rc = read_private_key_from_file((void **) rsa, read_rsa,
+ filename, passphrase);
+
+ if(rc) {
+ rc = _libssh2_rsa_new_openssh_private(rsa, session,
+ filename, passphrase);
+ }
- return read_private_key_from_file((void **) rsa, read_rsa,
- filename, passphrase);
+ return rc;
}
#if LIBSSH2_DSA
@@ -580,14 +1135,275 @@ _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
const char *filedata, size_t filedata_len,
unsigned const char *passphrase)
{
+ int rc;
+
pem_read_bio_func read_dsa =
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
(void) session;
_libssh2_init_if_needed();
- return read_private_key_from_memory((void **) dsa, read_dsa,
- filedata, filedata_len, passphrase);
+ rc = read_private_key_from_memory((void **)dsa, read_dsa,
+ filedata, filedata_len, passphrase);
+
+ if(rc) {
+ rc = read_openssh_private_key_from_memory((void **)dsa, session,
+ "ssh-dsa", filedata, filedata_len, passphrase);
+ }
+
+ return rc;
+}
+
+static unsigned char *
+gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa,
+ size_t *key_len)
+{
+ int p_bytes, q_bytes, g_bytes, k_bytes;
+ unsigned long len;
+ unsigned char *key;
+ unsigned char *p;
+
+ const BIGNUM * p_bn;
+ const BIGNUM * q;
+ const BIGNUM * g;
+ const BIGNUM * pub_key;
+#ifdef HAVE_OPAQUE_STRUCTS
+ DSA_get0_pqg(dsa, &p_bn, &q, &g);
+#else
+ p_bn = dsa->p;
+ q = dsa->q;
+ g = dsa->g;
+#endif
+
+#ifdef HAVE_OPAQUE_STRUCTS
+ DSA_get0_key(dsa, &pub_key, NULL);
+#else
+ pub_key = dsa->pub_key;
+#endif
+ p_bytes = BN_num_bytes(p_bn) + 1;
+ q_bytes = BN_num_bytes(q) + 1;
+ g_bytes = BN_num_bytes(g) + 1;
+ k_bytes = BN_num_bytes(pub_key) + 1;
+
+ /* Key form is "ssh-dss" + p + q + g + pub_key. */
+ len = 4 + 7 + 4 + p_bytes + 4 + q_bytes + 4 + g_bytes + 4 + k_bytes;
+
+ key = LIBSSH2_ALLOC(session, len);
+ if(key == NULL) {
+ return NULL;
+ }
+
+ /* Process key encoding. */
+ p = key;
+
+ _libssh2_htonu32(p, 7); /* Key type. */
+ p += 4;
+ memcpy(p, "ssh-dss", 7);
+ p += 7;
+
+ p = write_bn(p, p_bn, p_bytes);
+ p = write_bn(p, q, q_bytes);
+ p = write_bn(p, g, g_bytes);
+ p = write_bn(p, pub_key, k_bytes);
+
+ *key_len = (size_t)(p - key);
+ return key;
+}
+
+static int
+gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ EVP_PKEY *pk)
+{
+ DSA* dsa = NULL;
+ unsigned char *key;
+ unsigned char *method_buf = NULL;
+ size_t key_len;
+
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Computing public key from DSA private key envelop");
+
+ dsa = EVP_PKEY_get1_DSA(pk);
+ if(dsa == NULL) {
+ /* Assume memory allocation error... what else could it be ? */
+ goto __alloc_error;
+ }
+
+ method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-dss. */
+ if(method_buf == NULL) {
+ goto __alloc_error;
+ }
+
+ key = gen_publickey_from_dsa(session, dsa, &key_len);
+ if(key == NULL) {
+ goto __alloc_error;
+ }
+ DSA_free(dsa);
+
+ memcpy(method_buf, "ssh-dss", 7);
+ *method = method_buf;
+ *method_len = 7;
+ *pubkeydata = key;
+ *pubkeydata_len = key_len;
+ return 0;
+
+ __alloc_error:
+ if(dsa != NULL) {
+ DSA_free(dsa);
+ }
+ if(method_buf != NULL) {
+ LIBSSH2_FREE(session, method_buf);
+ }
+
+ return _libssh2_error(session,
+ LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for private key data");
+}
+
+static int
+gen_publickey_from_dsa_openssh_priv_data(LIBSSH2_SESSION *session,
+ struct string_buf *decrypted,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ libssh2_dsa_ctx **dsa_ctx)
+{
+ 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_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Computing DSA keys from private key data");
+
+ if(_libssh2_get_bignum_bytes(decrypted, &p, &plen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "DSA no p");
+ return -1;
+ }
+
+ if(_libssh2_get_bignum_bytes(decrypted, &q, &qlen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "DSA no q");
+ return -1;
+ }
+
+ if(_libssh2_get_bignum_bytes(decrypted, &g, &glen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "DSA no g");
+ return -1;
+ }
+
+ if(_libssh2_get_bignum_bytes(decrypted, &pub_key, &pub_len)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "DSA no public key");
+ return -1;
+ }
+
+ if(_libssh2_get_bignum_bytes(decrypted, &priv_key, &priv_len)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "DSA no private key");
+ return -1;
+ }
+
+ rc = _libssh2_dsa_new(&dsa, p, plen, q, qlen, g, glen, pub_key, pub_len,
+ priv_key, priv_len);
+ if(rc != 0) {
+ _libssh2_debug(session,
+ LIBSSH2_ERROR_PROTO,
+ "Could not create DSA private key");
+ goto fail;
+ }
+
+ if(dsa != NULL && pubkeydata != NULL && method != NULL) {
+ EVP_PKEY *pk = EVP_PKEY_new();
+ EVP_PKEY_set1_DSA(pk, dsa);
+
+ rc = gen_publickey_from_dsa_evp(session, method, method_len,
+ pubkeydata, pubkeydata_len,
+ pk);
+
+ if(pk)
+ EVP_PKEY_free(pk);
+ }
+
+ if(dsa_ctx != NULL)
+ *dsa_ctx = dsa;
+ else
+ DSA_free(dsa);
+
+ return rc;
+
+fail:
+
+ if(dsa != NULL)
+ DSA_free(dsa);
+
+ return _libssh2_error(session,
+ LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for private key data");
+}
+
+static int
+_libssh2_dsa_new_openssh_private(libssh2_dsa_ctx ** dsa,
+ LIBSSH2_SESSION * session,
+ const char *filename,
+ unsigned const char *passphrase)
+{
+ FILE *fp;
+ int rc;
+ unsigned char *buf = NULL;
+ struct string_buf *decrypted = NULL;
+
+ if(session == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Session is required");
+ return -1;
+ }
+
+ _libssh2_init_if_needed();
+
+ fp = fopen(filename, "r");
+ if(!fp) {
+ _libssh2_error(session, LIBSSH2_ERROR_FILE,
+ "Unable to open OpenSSH DSA private key file");
+ return -1;
+ }
+
+ rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted);
+ fclose(fp);
+ if(rc) {
+ return rc;
+ }
+
+ /* We have a new key file, now try and parse it using supported types */
+ rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+ if(rc != 0 || buf == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Public key type in decrypted key data not found");
+ return -1;
+ }
+
+ if(strcmp("ssh-dss", (const char *)buf) == 0) {
+ rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted,
+ NULL, 0,
+ NULL, 0, dsa);
+ }
+ else {
+ rc = -1;
+ }
+
+ if(decrypted)
+ _libssh2_string_buf_free(session, decrypted);
+
+ return rc;
}
int
@@ -595,17 +1411,438 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
const char *filename, unsigned const char *passphrase)
{
+ int rc;
+
pem_read_bio_func read_dsa =
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
(void) session;
- _libssh2_init_if_needed ();
+ _libssh2_init_if_needed();
+
+ rc = read_private_key_from_file((void **) dsa, read_dsa,
+ filename, passphrase);
+
+ if(rc) {
+ rc = _libssh2_dsa_new_openssh_private(dsa, session,
+ filename, passphrase);
+ }
- return read_private_key_from_file((void **) dsa, read_dsa,
- filename, passphrase);
+ return rc;
}
+
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+
+int
+_libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filedata, size_t filedata_len,
+ unsigned const char *passphrase)
+{
+ int rc;
+
+ pem_read_bio_func read_ec =
+ (pem_read_bio_func) &PEM_read_bio_ECPrivateKey;
+ (void) session;
+
+ _libssh2_init_if_needed();
+
+ 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);
+ }
+
+ return rc;
+}
+
+#endif /* LIBSSH2_ECDSA */
+
+
+#if LIBSSH2_ED25519
+
+int
+_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_x25519_ctx **out_ctx,
+ unsigned char **out_public_key,
+ unsigned char **out_private_key)
+{
+ EVP_PKEY *key = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ PKCS8_PRIV_KEY_INFO *info = NULL;
+ ASN1_OCTET_STRING *oct = NULL;
+ X509_PUBKEY *pubkey = NULL;
+ libssh2_ed25519_ctx *ctx = NULL;
+ const unsigned char *pkcs, *priv, *pub;
+ int privLen, pubLen, pkcsLen;
+ int rc = -1;
+
+ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
+ if(pctx == NULL)
+ return -1;
+
+ EVP_PKEY_keygen_init(pctx);
+ EVP_PKEY_keygen(pctx, &key);
+ info = EVP_PKEY2PKCS8(key);
+
+ if(info == NULL || !PKCS8_pkey_get0(NULL, &pkcs, &pkcsLen, NULL, info))
+ goto cleanExit;
+
+ oct = d2i_ASN1_OCTET_STRING(NULL, &pkcs, pkcsLen);
+ if(oct == NULL) {
+ goto cleanExit;
+ }
+
+ priv = ASN1_STRING_get0_data(oct);
+ privLen = ASN1_STRING_length(oct);
+
+ if(privLen != LIBSSH2_ED25519_KEY_LEN)
+ goto cleanExit;
+
+ pubkey = X509_PUBKEY_new();
+ if(pubkey == NULL || !X509_PUBKEY_set(&pubkey, key))
+ goto cleanExit;
+
+ if(!X509_PUBKEY_get0_param(NULL, &pub, &pubLen, NULL, pubkey))
+ goto cleanExit;
+
+ if(pubLen != LIBSSH2_ED25519_KEY_LEN)
+ goto cleanExit;
+
+ if(out_private_key != NULL) {
+ *out_private_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN);
+ if(*out_private_key == NULL)
+ goto cleanExit;
+
+ memcpy(*out_private_key, priv, LIBSSH2_ED25519_KEY_LEN);
+ }
+
+ if(out_public_key != NULL) {
+ *out_public_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN);
+ if(*out_public_key == NULL)
+ goto cleanExit;
+
+ memcpy(*out_public_key, pub, LIBSSH2_ED25519_KEY_LEN);
+ }
+
+ if(out_ctx != NULL) {
+ ctx = malloc(sizeof(libssh2_x25519_ctx));
+ if(ctx == NULL)
+ goto cleanExit;
+
+ ctx->private_key =
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
+ (const unsigned char *)priv,
+ LIBSSH2_ED25519_KEY_LEN);
+
+ ctx->public_key =
+ EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
+ (const unsigned char *)pub,
+ LIBSSH2_ED25519_KEY_LEN);
+
+ if(ctx->public_key == NULL || ctx->private_key == NULL) {
+ _libssh2_x25519_free(ctx);
+ goto cleanExit;
+ }
+
+ *out_ctx = ctx;
+ }
+
+ /* success */
+ rc = 0;
+
+cleanExit:
+
+ if(info)
+ PKCS8_PRIV_KEY_INFO_free(info);
+ if(pctx)
+ EVP_PKEY_CTX_free(pctx);
+ if(oct)
+ ASN1_OCTET_STRING_free(oct);
+ if(pubkey)
+ X509_PUBKEY_free(pubkey);
+ if(key)
+ EVP_PKEY_free(key);
+
+ return rc;
+}
+
+static int
+gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session,
+ struct string_buf *decrypted,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ libssh2_ed25519_ctx **out_ctx)
+{
+ libssh2_ed25519_ctx *ctx = NULL;
+ unsigned char *method_buf = NULL;
+ unsigned char *key = NULL;
+ int i, ret = 0;
+ unsigned char *pub_key, *priv_key, *buf;
+ size_t key_len = 0, tmp_len = 0;
+ unsigned char *p;
+
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Computing ED25519 keys from private key data");
+
+ if(_libssh2_get_string(decrypted, &pub_key, &tmp_len) ||
+ tmp_len != LIBSSH2_ED25519_KEY_LEN) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Wrong public key length");
+ return -1;
+ }
+
+ if(_libssh2_get_string(decrypted, &priv_key, &tmp_len) ||
+ tmp_len != LIBSSH2_ED25519_PRIVATE_KEY_LEN) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Wrong private key length");
+ ret = -1;
+ goto clean_exit;
+ }
+
+ ctx = _libssh2_ed25519_new_ctx();
+ if(ctx == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for ed25519 key");
+ ret = -1;
+ goto clean_exit;
+ }
+
+ /* first 32 bytes of priv_key is the private key, the last 32 bytes are
+ the public key */
+ ctx->private_key =
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
+ (const unsigned char *)priv_key,
+ LIBSSH2_ED25519_KEY_LEN);
+
+ ctx->public_key =
+ EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
+ (const unsigned char *)pub_key,
+ LIBSSH2_ED25519_KEY_LEN);
+
+ /* comment */
+ if(_libssh2_get_string(decrypted, &buf, &tmp_len)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Unable to read comment");
+ ret = -1;
+ goto clean_exit;
+ }
+
+ if(tmp_len > 0) {
+ unsigned char *comment = LIBSSH2_CALLOC(session, tmp_len + 1);
+ if(comment != NULL) {
+ memcpy(comment, buf, tmp_len);
+ memcpy(comment + tmp_len, "\0", 1);
+
+ _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Key comment: %s",
+ comment);
+
+ LIBSSH2_FREE(session, comment);
+ }
+ }
+
+ /* Padding */
+ i = 1;
+ while(decrypted->dataptr < decrypted->data + decrypted->len) {
+ if(*decrypted->dataptr != i) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Wrong padding");
+ ret = -1;
+ goto clean_exit;
+ }
+ i++;
+ decrypted->dataptr++;
+ }
+
+ if(ret == 0) {
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Computing public key from ED25519 "
+ "private key envelop");
+
+ method_buf = LIBSSH2_ALLOC(session, 11); /* ssh-ed25519. */
+ if(method_buf == NULL) {
+ goto clean_exit;
+ }
+
+ /* Key form is: type_len(4) + type(11) + pub_key_len(4) +
+ pub_key(32). */
+ key_len = LIBSSH2_ED25519_KEY_LEN + 19;
+ key = LIBSSH2_CALLOC(session, key_len);
+ if(key == NULL) {
+ goto clean_exit;
+ }
+
+ p = key;
+
+ _libssh2_store_str(&p, "ssh-ed25519", 11);
+ _libssh2_store_str(&p, (const char *)pub_key, LIBSSH2_ED25519_KEY_LEN);
+
+ memcpy(method_buf, "ssh-ed25519", 11);
+
+ if(method != NULL)
+ *method = method_buf;
+ else
+ LIBSSH2_FREE(session, method_buf);
+
+ if(method_len != NULL)
+ *method_len = 11;
+
+ if(pubkeydata != NULL)
+ *pubkeydata = key;
+ else
+ LIBSSH2_FREE(session, key);
+
+ if(pubkeydata_len != NULL)
+ *pubkeydata_len = key_len;
+
+ if(out_ctx != NULL)
+ *out_ctx = ctx;
+ else if(ctx != NULL)
+ _libssh2_ed25519_free(ctx);
+
+ return 0;
+ }
+
+clean_exit:
+
+ if(ctx)
+ _libssh2_ed25519_free(ctx);
+
+ if(method_buf)
+ LIBSSH2_FREE(session, method_buf);
+
+ if(key)
+ LIBSSH2_FREE(session, key);
+
+ return -1;
+}
+
+int
+_libssh2_ed25519_new_private(libssh2_ed25519_ctx ** ed_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filename, const uint8_t *passphrase)
+{
+ int rc;
+ FILE *fp;
+ unsigned char *buf;
+ struct string_buf *decrypted = NULL;
+ libssh2_ed25519_ctx *ctx = NULL;
+
+ if(session == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Session is required");
+ return -1;
+ }
+
+ _libssh2_init_if_needed();
+
+ fp = fopen(filename, "r");
+ if(!fp) {
+ _libssh2_error(session, LIBSSH2_ERROR_FILE,
+ "Unable to open ED25519 private key file");
+ return -1;
+ }
+
+ rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted);
+ fclose(fp);
+ if(rc) {
+ return rc;
+ }
+
+ /* We have a new key file, now try and parse it using supported types */
+ rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+ if(rc != 0 || buf == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Public key type in decrypted key data not found");
+ return -1;
+ }
+
+ if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
+ rc = gen_publickey_from_ed25519_openssh_priv_data(session,
+ decrypted,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &ctx);
+ }
+ else {
+ rc = -1;
+ }
+
+ if(decrypted)
+ _libssh2_string_buf_free(session, decrypted);
+
+ if(rc == 0) {
+ if(ed_ctx != NULL)
+ *ed_ctx = ctx;
+ else if(ctx != NULL)
+ _libssh2_ed25519_free(ctx);
+ }
+
+ return rc;
+}
+
+int
+_libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx ** ed_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filedata,
+ size_t filedata_len,
+ unsigned const char *passphrase)
+{
+ return read_openssh_private_key_from_memory((void **)ed_ctx, session,
+ "ssh-ed25519",
+ filedata, filedata_len,
+ passphrase);
+}
+
+int
+_libssh2_ed25519_new_public(libssh2_ed25519_ctx ** ed_ctx,
+ LIBSSH2_SESSION * session,
+ const unsigned char *raw_pub_key,
+ const uint8_t key_len)
+{
+ libssh2_ed25519_ctx *ctx = NULL;
+ EVP_PKEY *public_key = NULL;
+
+ if(ed_ctx == NULL)
+ return -1;
+
+ public_key =
+ EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
+ (const unsigned char *)raw_pub_key,
+ key_len);
+ if(public_key == NULL) {
+ return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "could not create ED25519 public key");
+ }
+
+ ctx = _libssh2_ed25519_new_ctx();
+ if(ctx == NULL) {
+ return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "could not alloc public/private key");
+ }
+
+ ctx->public_key = public_key;
+
+ if(ed_ctx != NULL)
+ *ed_ctx = ctx;
+ else if(ctx != NULL)
+ _libssh2_ed25519_free(ctx);
+
+ return 0;
+}
+
+#endif /* LIBSSH2_ED25519 */
+
int
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx,
@@ -620,13 +1857,13 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
sig_len = RSA_size(rsactx);
sig = LIBSSH2_ALLOC(session, sig_len);
- if (!sig) {
+ if(!sig) {
return -1;
}
ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx);
- if (!ret) {
+ if(!ret) {
LIBSSH2_FREE(session, sig);
return -1;
}
@@ -650,7 +1887,7 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
(void) hash_len;
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
- if (!sig) {
+ if(!sig) {
return -1;
}
@@ -661,12 +1898,12 @@ _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 > 20) {
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 > 20) {
DSA_SIG_free(sig);
return -1;
}
@@ -682,16 +1919,79 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
}
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+
+int
+_libssh2_ecdsa_sign(LIBSSH2_SESSION * session, libssh2_ecdsa_ctx * ec_ctx,
+ const unsigned char *hash, unsigned long hash_len,
+ unsigned char **signature, size_t *signature_len)
+{
+ int r_len, s_len;
+ int rc = 0;
+ size_t out_buffer_len = 0;
+ unsigned char *sp;
+ const BIGNUM *pr = NULL, *ps = NULL;
+ unsigned char *temp_buffer = NULL;
+ unsigned char *out_buffer = NULL;
+
+ ECDSA_SIG *sig = ECDSA_do_sign(hash, hash_len, ec_ctx);
+ if(sig == NULL)
+ return -1;
+#ifdef HAVE_OPAQUE_STRUCTS
+ ECDSA_SIG_get0(sig, &pr, &ps);
+#else
+ pr = sig->r;
+ ps = sig->s;
+#endif
+
+ r_len = BN_num_bytes(pr) + 1;
+ s_len = BN_num_bytes(ps) + 1;
+
+ temp_buffer = malloc(r_len + s_len + 8);
+ if(temp_buffer == NULL) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ sp = temp_buffer;
+ sp = write_bn(sp, pr, r_len);
+ sp = write_bn(sp, ps, s_len);
+
+ out_buffer_len = (size_t)(sp - temp_buffer);
+
+ out_buffer = LIBSSH2_CALLOC(session, out_buffer_len);
+ if(out_buffer == NULL) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ memcpy(out_buffer, temp_buffer, out_buffer_len);
+
+ *signature = out_buffer;
+ *signature_len = out_buffer_len;
+
+clean_exit:
+
+ if(temp_buffer != NULL)
+ free(temp_buffer);
+
+ if(sig)
+ ECDSA_SIG_free(sig);
+
+ return rc;
+}
+#endif /* LIBSSH2_ECDSA */
+
int
_libssh2_sha1_init(libssh2_sha1_ctx *ctx)
{
#ifdef HAVE_OPAQUE_STRUCTS
*ctx = EVP_MD_CTX_new();
- if (*ctx == NULL)
+ if(*ctx == NULL)
return 0;
- if (EVP_DigestInit(*ctx, EVP_get_digestbyname("sha1")))
+ if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha1")))
return 1;
EVP_MD_CTX_free(*ctx);
@@ -711,10 +2011,10 @@ _libssh2_sha1(const unsigned char *message, unsigned long len,
#ifdef HAVE_OPAQUE_STRUCTS
EVP_MD_CTX * ctx = EVP_MD_CTX_new();
- if (ctx == NULL)
+ if(ctx == NULL)
return 1; /* error */
- if (EVP_DigestInit(ctx, EVP_get_digestbyname("sha1"))) {
+ if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha1"))) {
EVP_DigestUpdate(ctx, message, len);
EVP_DigestFinal(ctx, out, NULL);
EVP_MD_CTX_free(ctx);
@@ -725,7 +2025,7 @@ _libssh2_sha1(const unsigned char *message, unsigned long len,
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
- if (EVP_DigestInit(&ctx, EVP_get_digestbyname("sha1"))) {
+ if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha1"))) {
EVP_DigestUpdate(&ctx, message, len);
EVP_DigestFinal(&ctx, out, NULL);
return 0; /* success */
@@ -740,10 +2040,10 @@ _libssh2_sha256_init(libssh2_sha256_ctx *ctx)
#ifdef HAVE_OPAQUE_STRUCTS
*ctx = EVP_MD_CTX_new();
- if (*ctx == NULL)
+ if(*ctx == NULL)
return 0;
- if (EVP_DigestInit(*ctx, EVP_get_digestbyname("sha256")))
+ if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha256")))
return 1;
EVP_MD_CTX_free(*ctx);
@@ -763,7 +2063,7 @@ _libssh2_sha256(const unsigned char *message, unsigned long len,
#ifdef HAVE_OPAQUE_STRUCTS
EVP_MD_CTX * ctx = EVP_MD_CTX_new();
- if (ctx == NULL)
+ if(ctx == NULL)
return 1; /* error */
if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha256"))) {
@@ -787,15 +2087,15 @@ _libssh2_sha256(const unsigned char *message, unsigned long len,
}
int
-_libssh2_md5_init(libssh2_md5_ctx *ctx)
+_libssh2_sha384_init(libssh2_sha384_ctx *ctx)
{
#ifdef HAVE_OPAQUE_STRUCTS
*ctx = EVP_MD_CTX_new();
- if (*ctx == NULL)
+ if(*ctx == NULL)
return 0;
- if (EVP_DigestInit(*ctx, EVP_get_digestbyname("md5")))
+ if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha384")))
return 1;
EVP_MD_CTX_free(*ctx);
@@ -804,237 +2104,804 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx)
return 0;
#else
EVP_MD_CTX_init(ctx);
- return EVP_DigestInit(ctx, EVP_get_digestbyname("md5"));
+ return EVP_DigestInit(ctx, EVP_get_digestbyname("sha384"));
#endif
}
-static unsigned char *
-write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes)
+int
+_libssh2_sha384(const unsigned char *message, unsigned long len,
+ unsigned char *out)
{
- unsigned char *p = buf;
+#ifdef HAVE_OPAQUE_STRUCTS
+ EVP_MD_CTX * ctx = EVP_MD_CTX_new();
- /* Left space for bn size which will be written below. */
- p += 4;
+ if(ctx == NULL)
+ return 1; /* error */
- *p = 0;
- BN_bn2bin(bn, p + 1);
- if (!(*(p + 1) & 0x80)) {
- memmove(p, p + 1, --bn_bytes);
+ if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha384"))) {
+ EVP_DigestUpdate(ctx, message, len);
+ EVP_DigestFinal(ctx, out, NULL);
+ EVP_MD_CTX_free(ctx);
+ return 0; /* success */
}
- _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */
+ EVP_MD_CTX_free(ctx);
+#else
+ EVP_MD_CTX ctx;
- return p + bn_bytes;
+ EVP_MD_CTX_init(&ctx);
+ if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha384"))) {
+ EVP_DigestUpdate(&ctx, message, len);
+ EVP_DigestFinal(&ctx, out, NULL);
+ return 0; /* success */
+ }
+#endif
+ return 1; /* error */
}
-static unsigned char *
-gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa,
- size_t *key_len)
+int
+_libssh2_sha512_init(libssh2_sha512_ctx *ctx)
{
- int e_bytes, n_bytes;
- unsigned long len;
- unsigned char* key;
- unsigned char* p;
- const BIGNUM * e;
- const BIGNUM * n;
#ifdef HAVE_OPAQUE_STRUCTS
- RSA_get0_key(rsa, &n, &e, NULL);
-#else
- e = rsa->e;
- n = rsa->n;
-#endif
- e_bytes = BN_num_bytes(e) + 1;
- n_bytes = BN_num_bytes(n) + 1;
-
- /* Key form is "ssh-rsa" + e + n. */
- len = 4 + 7 + 4 + e_bytes + 4 + n_bytes;
-
- key = LIBSSH2_ALLOC(session, len);
- if (key == NULL) {
- return NULL;
- }
+ *ctx = EVP_MD_CTX_new();
- /* Process key encoding. */
- p = key;
+ if(*ctx == NULL)
+ return 0;
- _libssh2_htonu32(p, 7); /* Key type. */
- p += 4;
- memcpy(p, "ssh-rsa", 7);
- p += 7;
+ if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha512")))
+ return 1;
- p = write_bn(p, e, e_bytes);
- p = write_bn(p, n, n_bytes);
+ EVP_MD_CTX_free(*ctx);
+ *ctx = NULL;
- *key_len = (size_t)(p - key);
- return key;
+ return 0;
+#else
+ EVP_MD_CTX_init(ctx);
+ return EVP_DigestInit(ctx, EVP_get_digestbyname("sha512"));
+#endif
}
-#if LIBSSH2_DSA
-static unsigned char *
-gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa,
- size_t *key_len)
+int
+_libssh2_sha512(const unsigned char *message, unsigned long len,
+ unsigned char *out)
{
- int p_bytes, q_bytes, g_bytes, k_bytes;
- unsigned long len;
- unsigned char* key;
- unsigned char* p;
-
- const BIGNUM * p_bn;
- const BIGNUM * q;
- const BIGNUM * g;
- const BIGNUM * pub_key;
#ifdef HAVE_OPAQUE_STRUCTS
- DSA_get0_pqg(dsa, &p_bn, &q, &g);
+ EVP_MD_CTX * ctx = EVP_MD_CTX_new();
+
+ if(ctx == NULL)
+ return 1; /* error */
+
+ if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha512"))) {
+ EVP_DigestUpdate(ctx, message, len);
+ EVP_DigestFinal(ctx, out, NULL);
+ EVP_MD_CTX_free(ctx);
+ return 0; /* success */
+ }
+ EVP_MD_CTX_free(ctx);
#else
- p_bn = dsa->p;
- q = dsa->q;
- g = dsa->g;
+ EVP_MD_CTX ctx;
+
+ EVP_MD_CTX_init(&ctx);
+ if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha512"))) {
+ EVP_DigestUpdate(&ctx, message, len);
+ EVP_DigestFinal(&ctx, out, NULL);
+ return 0; /* success */
+ }
#endif
+ return 1; /* error */
+}
+int
+_libssh2_md5_init(libssh2_md5_ctx *ctx)
+{
#ifdef HAVE_OPAQUE_STRUCTS
- DSA_get0_key(dsa, &pub_key, NULL);
+ *ctx = EVP_MD_CTX_new();
+
+ if(*ctx == NULL)
+ return 0;
+
+ if(EVP_DigestInit(*ctx, EVP_get_digestbyname("md5")))
+ return 1;
+
+ EVP_MD_CTX_free(*ctx);
+ *ctx = NULL;
+
+ return 0;
#else
- pub_key = dsa->pub_key;
+ EVP_MD_CTX_init(ctx);
+ return EVP_DigestInit(ctx, EVP_get_digestbyname("md5"));
#endif
- p_bytes = BN_num_bytes(p_bn) + 1;
- q_bytes = BN_num_bytes(q) + 1;
- g_bytes = BN_num_bytes(g) + 1;
- k_bytes = BN_num_bytes(pub_key) + 1;
+}
- /* Key form is "ssh-dss" + p + q + g + pub_key. */
- len = 4 + 7 + 4 + p_bytes + 4 + q_bytes + 4 + g_bytes + 4 + k_bytes;
+#if LIBSSH2_ECDSA
- key = LIBSSH2_ALLOC(session, len);
- if (key == NULL) {
- return NULL;
+static int
+gen_publickey_from_ec_evp(LIBSSH2_SESSION *session,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ EVP_PKEY *pk)
+{
+ int rc = 0;
+ EC_KEY *ec = NULL;
+ unsigned char *p;
+ unsigned char *method_buf = NULL;
+ unsigned char *key;
+ size_t key_len = 0;
+ unsigned char *octal_value = NULL;
+ size_t octal_len;
+ const EC_POINT *public_key;
+ const EC_GROUP *group;
+ BN_CTX *bn_ctx;
+ libssh2_curve_type type;
+
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Computing public key from EC private key envelop");
+
+ bn_ctx = BN_CTX_new();
+ if(bn_ctx == NULL)
+ return -1;
+
+ ec = EVP_PKEY_get1_EC_KEY(pk);
+ if(ec == NULL) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ public_key = EC_KEY_get0_public_key(ec);
+ group = EC_KEY_get0_group(ec);
+ type = _libssh2_ecdsa_key_get_curve_type(ec);
+
+ method_buf = LIBSSH2_ALLOC(session, 19);
+ if(method_buf == NULL) {
+ return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "out of memory");
+ }
+
+ if(type == LIBSSH2_EC_CURVE_NISTP256)
+ memcpy(method_buf, "ecdsa-sha2-nistp256", 19);
+ else if(type == LIBSSH2_EC_CURVE_NISTP384)
+ memcpy(method_buf, "ecdsa-sha2-nistp384", 19);
+ else if(type == LIBSSH2_EC_CURVE_NISTP521)
+ memcpy(method_buf, "ecdsa-sha2-nistp521", 19);
+ else {
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_ERROR,
+ "Unsupported EC private key type");
+ rc = -1;
+ goto clean_exit;
+ }
+
+ /* get length */
+ octal_len = EC_POINT_point2oct(group, public_key,
+ POINT_CONVERSION_UNCOMPRESSED,
+ NULL, 0, bn_ctx);
+ if(octal_len > EC_MAX_POINT_LEN) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ octal_value = malloc(octal_len);
+ if(octal_value == NULL) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ /* convert to octal */
+ if(EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED,
+ octal_value, octal_len, bn_ctx) != octal_len) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ /* Key form is: type_len(4) + type(19) + domain_len(4) + domain(8) +
+ pub_key_len(4) + pub_key(~65). */
+ key_len = 4 + 19 + 4 + 8 + 4 + octal_len;
+ key = LIBSSH2_ALLOC(session, key_len);
+ if(key == NULL) {
+ rc = -1;
+ goto clean_exit;
}
/* Process key encoding. */
p = key;
- _libssh2_htonu32(p, 7); /* Key type. */
- p += 4;
- memcpy(p, "ssh-dss", 7);
- p += 7;
+ /* Key type */
+ _libssh2_store_str(&p, (const char *)method_buf, 19);
- p = write_bn(p, p_bn, p_bytes);
- p = write_bn(p, q, q_bytes);
- p = write_bn(p, g, g_bytes);
- p = write_bn(p, pub_key, k_bytes);
+ /* Name domain */
+ _libssh2_store_str(&p, (const char *)method_buf + 11, 8);
- *key_len = (size_t)(p - key);
- return key;
+ /* Public key */
+ _libssh2_store_str(&p, (const char *)octal_value, octal_len);
+
+ *method = method_buf;
+ *method_len = 19;
+ *pubkeydata = key;
+ *pubkeydata_len = key_len;
+
+clean_exit:
+
+ if(ec != NULL)
+ EC_KEY_free(ec);
+
+ if(bn_ctx != NULL) {
+ BN_CTX_free(bn_ctx);
+ }
+
+ if(octal_value != NULL)
+ free(octal_value);
+
+ if(rc == 0)
+ return 0;
+
+ if(method_buf != NULL)
+ LIBSSH2_FREE(session, method_buf);
+
+ return -1;
}
-#endif /* LIBSSH_DSA */
static int
-gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session,
- unsigned char **method,
- size_t *method_len,
- unsigned char **pubkeydata,
- size_t *pubkeydata_len,
- EVP_PKEY *pk)
+gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session,
+ libssh2_curve_type curve_type,
+ struct string_buf *decrypted,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ libssh2_ecdsa_ctx **ec_ctx)
{
- RSA* rsa = NULL;
- unsigned char* key;
- unsigned char* method_buf = NULL;
- size_t key_len;
+ int rc = 0;
+ size_t curvelen, exponentlen, pointlen;
+ unsigned char *curve, *exponent, *point_buf;
+ EC_KEY *ec_key = NULL;
+ BIGNUM *bn_exponent;
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
- "Computing public key from RSA private key envelop");
+ "Computing ECDSA keys from private key data");
- rsa = EVP_PKEY_get1_RSA(pk);
- if (rsa == NULL) {
- /* Assume memory allocation error... what else could it be ? */
- goto __alloc_error;
+ if(_libssh2_get_string(decrypted, &curve, &curvelen) ||
+ curvelen == 0) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "ECDSA no curve");
+ return -1;
}
- method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-rsa. */
- if (method_buf == NULL) {
- goto __alloc_error;
+ if(_libssh2_get_string(decrypted, &point_buf, &pointlen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "ECDSA no point");
+ return -1;
}
- key = gen_publickey_from_rsa(session, rsa, &key_len);
- if (key == NULL) {
- goto __alloc_error;
+ if(_libssh2_get_bignum_bytes(decrypted, &exponent, &exponentlen)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "ECDSA no exponent");
+ return -1;
}
- RSA_free(rsa);
- memcpy(method_buf, "ssh-rsa", 7);
- *method = method_buf;
- *method_len = 7;
- *pubkeydata = key;
- *pubkeydata_len = key_len;
- return 0;
+ if((rc = _libssh2_ecdsa_curve_name_with_octal_new(&ec_key, point_buf,
+ pointlen, curve_type)) != 0) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "ECDSA could not create key");
+ goto fail;
+ }
- __alloc_error:
- if (rsa != NULL) {
- RSA_free(rsa);
+ bn_exponent = BN_new();
+ if(bn_exponent == NULL) {
+ rc = -1;
+ goto fail;
}
- if (method_buf != NULL) {
- LIBSSH2_FREE(session, method_buf);
+
+ BN_bin2bn(exponent, exponentlen, bn_exponent);
+ rc = (EC_KEY_set_private_key(ec_key, bn_exponent) != 1);
+
+ if(rc == 0 && ec_key != NULL && pubkeydata != NULL && method != NULL) {
+ EVP_PKEY *pk = EVP_PKEY_new();
+ EVP_PKEY_set1_EC_KEY(pk, ec_key);
+
+ rc = gen_publickey_from_ec_evp(session, method, method_len,
+ pubkeydata, pubkeydata_len,
+ pk);
+
+ if(pk)
+ EVP_PKEY_free(pk);
}
+ if(ec_ctx != NULL)
+ *ec_ctx = ec_key;
+ else
+ EC_KEY_free(ec_key);
+
+ return rc;
+
+fail:
+
+ if(ec_key != NULL)
+ EC_KEY_free(ec_key);
+
return _libssh2_error(session,
LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for private key data");
+
+
}
-#if LIBSSH2_DSA
static int
-gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session,
- unsigned char **method,
- size_t *method_len,
- unsigned char **pubkeydata,
- size_t *pubkeydata_len,
- EVP_PKEY *pk)
+_libssh2_ecdsa_new_openssh_private(libssh2_ecdsa_ctx ** ec_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filename,
+ unsigned const char *passphrase)
{
- DSA* dsa = NULL;
- unsigned char* key;
- unsigned char* method_buf = NULL;
- size_t key_len;
+ FILE *fp;
+ int rc;
+ unsigned char *buf = NULL;
+ libssh2_curve_type type;
+ struct string_buf *decrypted = NULL;
+
+ if(session == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Session is required");
+ return -1;
+ }
- _libssh2_debug(session,
- LIBSSH2_TRACE_AUTH,
- "Computing public key from DSA private key envelop");
+ _libssh2_init_if_needed();
- dsa = EVP_PKEY_get1_DSA(pk);
- if (dsa == NULL) {
- /* Assume memory allocation error... what else could it be ? */
- goto __alloc_error;
+ fp = fopen(filename, "r");
+ if(!fp) {
+ _libssh2_error(session, LIBSSH2_ERROR_FILE,
+ "Unable to open OpenSSH ECDSA private key file");
+ return -1;
}
- method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-dss. */
- if (method_buf == NULL) {
- goto __alloc_error;
+ rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted);
+ fclose(fp);
+ if(rc) {
+ return rc;
}
- key = gen_publickey_from_dsa(session, dsa, &key_len);
- if (key == NULL) {
- goto __alloc_error;
+ /* We have a new key file, now try and parse it using supported types */
+ rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+ if(rc != 0 || buf == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Public key type in decrypted key data not found");
+ return -1;
}
- DSA_free(dsa);
- memcpy(method_buf, "ssh-dss", 7);
- *method = method_buf;
- *method_len = 7;
- *pubkeydata = key;
- *pubkeydata_len = key_len;
- return 0;
+ rc = _libssh2_ecdsa_curve_type_from_name((const char *)buf, &type);
- __alloc_error:
- if (dsa != NULL) {
- DSA_free(dsa);
+ if(rc == 0) {
+ rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type,
+ decrypted, NULL, 0,
+ NULL, 0, ec_ctx);
}
- if (method_buf != NULL) {
- LIBSSH2_FREE(session, method_buf);
+ else {
+ rc = -1;
}
- return _libssh2_error(session,
- LIBSSH2_ERROR_ALLOC,
- "Unable to allocate memory for private key data");
+ if(decrypted)
+ _libssh2_string_buf_free(session, decrypted);
+
+ return rc;
+}
+
+int
+_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filename, unsigned const char *passphrase)
+{
+ int rc;
+
+ pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey;
+ (void) session;
+
+ _libssh2_init_if_needed();
+
+ rc = read_private_key_from_file((void **) ec_ctx, read_ec,
+ filename, passphrase);
+
+ if(rc) {
+ return _libssh2_ecdsa_new_openssh_private(ec_ctx, session,
+ filename, passphrase);
+ }
+
+ return rc;
+}
+
+/*
+ * _libssh2_ecdsa_create_key
+ *
+ * Creates a local private key based on input curve
+ * and returns octal value and octal length
+ *
+ */
+
+int
+_libssh2_ecdsa_create_key(LIBSSH2_SESSION *session,
+ _libssh2_ec_key **out_private_key,
+ unsigned char **out_public_key_octal,
+ size_t *out_public_key_octal_len,
+ libssh2_curve_type curve_type)
+{
+ int ret = 1;
+ size_t octal_len = 0;
+ unsigned char octal_value[EC_MAX_POINT_LEN];
+ const EC_POINT *public_key = NULL;
+ EC_KEY *private_key = NULL;
+ const EC_GROUP *group = NULL;
+
+ /* create key */
+ BN_CTX *bn_ctx = BN_CTX_new();
+ if(!bn_ctx)
+ return -1;
+
+ private_key = EC_KEY_new_by_curve_name(curve_type);
+ group = EC_KEY_get0_group(private_key);
+
+ EC_KEY_generate_key(private_key);
+ public_key = EC_KEY_get0_public_key(private_key);
+
+ /* get length */
+ octal_len = EC_POINT_point2oct(group, public_key,
+ POINT_CONVERSION_UNCOMPRESSED,
+ NULL, 0, bn_ctx);
+ if(octal_len > EC_MAX_POINT_LEN) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ /* convert to octal */
+ if(EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED,
+ octal_value, octal_len, bn_ctx) != octal_len) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ if(out_private_key != NULL)
+ *out_private_key = private_key;
+
+ if(out_public_key_octal) {
+ *out_public_key_octal = LIBSSH2_ALLOC(session, octal_len);
+ if(*out_public_key_octal == NULL) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ memcpy(*out_public_key_octal, octal_value, octal_len);
+ }
+
+ if(out_public_key_octal_len != NULL)
+ *out_public_key_octal_len = octal_len;
+
+clean_exit:
+
+ if(bn_ctx)
+ BN_CTX_free(bn_ctx);
+
+ return (ret == 1) ? 0 : -1;
+}
+
+/* _libssh2_ecdh_gen_k
+ *
+ * Computes the shared secret K given a local private key,
+ * remote public key and length
+ */
+
+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)
+{
+ int ret = 0;
+ int rc;
+ 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();
+
+ if(!bn_ctx)
+ return -1;
+
+ if(k == NULL)
+ return -1;
+
+ private_key_group = EC_KEY_get0_group(private_key);
+
+ server_public_key_point = EC_POINT_new(private_key_group);
+ if(server_public_key_point == NULL)
+ return -1;
+
+ rc = EC_POINT_oct2point(private_key_group, server_public_key_point,
+ server_public_key, server_public_key_len, bn_ctx);
+ if(rc != 1) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ secret_len = (EC_GROUP_get_degree(private_key_group) + 7) / 8;
+ secret = malloc(secret_len);
+ if(!secret) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ secret_len = ECDH_compute_key(secret, secret_len, server_public_key_point,
+ private_key, NULL);
+
+ if(secret_len <= 0 || secret_len > EC_MAX_POINT_LEN) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ BN_bin2bn(secret, secret_len, *k);
+
+clean_exit:
+
+ if(server_public_key_point != NULL)
+ EC_POINT_free(server_public_key_point);
+
+ if(bn_ctx != NULL)
+ BN_CTX_free(bn_ctx);
+
+ if(secret != NULL)
+ free(secret);
+
+ return ret;
+}
+
+
+#endif /* LIBSSH2_ECDSA */
+
+#if LIBSSH2_ED25519
+
+int
+_libssh2_ed25519_sign(libssh2_ed25519_ctx *ctx, LIBSSH2_SESSION *session,
+ uint8_t **out_sig, size_t *out_sig_len,
+ const uint8_t *message, size_t message_len)
+{
+ int rc = -1;
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+ size_t sig_len = 0;
+ unsigned char *sig = NULL;
+
+ if(md_ctx != NULL) {
+ if(EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, ctx->private_key) != 1)
+ goto clean_exit;
+ if(EVP_DigestSign(md_ctx, NULL, &sig_len, message, message_len) != 1)
+ goto clean_exit;
+
+ if(sig_len != LIBSSH2_ED25519_SIG_LEN)
+ goto clean_exit;
+
+ sig = LIBSSH2_CALLOC(session, sig_len);
+ if(sig == NULL)
+ goto clean_exit;
+
+ rc = EVP_DigestSign(md_ctx, sig, &sig_len, message, message_len);
+ }
+
+ if(rc == 1) {
+ *out_sig = sig;
+ *out_sig_len = sig_len;
+ }
+ else {
+ *out_sig_len = 0;
+ *out_sig = NULL;
+ LIBSSH2_FREE(session, sig);
+ }
+
+clean_exit:
+
+ if(md_ctx)
+ EVP_MD_CTX_free(md_ctx);
+
+ return (rc == 1 ? 0 : -1);
+}
+
+int
+_libssh2_curve25519_gen_k(_libssh2_bn **k,
+ uint8_t private_key[LIBSSH2_ED25519_KEY_LEN],
+ uint8_t server_public_key[LIBSSH2_ED25519_KEY_LEN])
+{
+ int rc = -1;
+ unsigned char out_shared_key[LIBSSH2_ED25519_KEY_LEN];
+ EVP_PKEY *peer_key = NULL, *server_key = NULL;
+ EVP_PKEY_CTX *server_key_ctx = NULL;
+ BN_CTX *bn_ctx = NULL;
+ size_t out_len = 0;
+
+ if(k == NULL || *k == NULL)
+ return -1;
+
+ bn_ctx = BN_CTX_new();
+ if(bn_ctx == NULL)
+ return -1;
+
+ peer_key = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
+ server_public_key,
+ LIBSSH2_ED25519_KEY_LEN);
+
+ server_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
+ private_key,
+ LIBSSH2_ED25519_KEY_LEN);
+
+ if(peer_key == NULL || server_key == NULL) {
+ goto cleanExit;
+ }
+
+ server_key_ctx = EVP_PKEY_CTX_new(server_key, NULL);
+ if(server_key_ctx == NULL) {
+ goto cleanExit;
+ }
+
+ rc = EVP_PKEY_derive_init(server_key_ctx);
+ if(rc <= 0) goto cleanExit;
+
+ rc = EVP_PKEY_derive_set_peer(server_key_ctx, peer_key);
+ if(rc <= 0) goto cleanExit;
+
+ rc = EVP_PKEY_derive(server_key_ctx, NULL, &out_len);
+ if(rc <= 0) goto cleanExit;
+
+ if(out_len != LIBSSH2_ED25519_KEY_LEN) {
+ rc = -1;
+ goto cleanExit;
+ }
+
+ rc = EVP_PKEY_derive(server_key_ctx, out_shared_key, &out_len);
+
+ if(rc == 1 && out_len == LIBSSH2_ED25519_KEY_LEN) {
+ BN_bin2bn(out_shared_key, LIBSSH2_ED25519_KEY_LEN, *k);
+ }
+ else {
+ rc = -1;
+ }
+
+cleanExit:
+
+ if(server_key_ctx)
+ EVP_PKEY_CTX_free(server_key_ctx);
+ if(peer_key)
+ EVP_PKEY_free(peer_key);
+ if(server_key)
+ EVP_PKEY_free(server_key);
+ if(bn_ctx != NULL)
+ BN_CTX_free(bn_ctx);
+
+ return (rc == 1) ? 0 : -1;
+}
+
+
+int
+_libssh2_ed25519_verify(libssh2_ed25519_ctx *ctx, const uint8_t *s,
+ size_t s_len, const uint8_t *m, size_t m_len)
+{
+ int ret = -1;
+
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+ if(NULL == md_ctx)
+ return -1;
+
+ ret = EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, ctx->public_key);
+ if(ret != 1)
+ goto clean_exit;
+
+ ret = EVP_DigestVerify(md_ctx, s, s_len, m, m_len);
+
+ clean_exit:
+
+ EVP_MD_CTX_free(md_ctx);
+
+ return (ret == 1) ? 0 : -1;
+}
+
+#endif /* LIBSSH2_ED25519 */
+
+static int
+_libssh2_pub_priv_openssh_keyfile(LIBSSH2_SESSION *session,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ const char *privatekey,
+ const char *passphrase)
+{
+ FILE *fp;
+ unsigned char *buf = NULL;
+ struct string_buf *decrypted = NULL;
+ int rc = 0;
+
+ if(session == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Session is required");
+ return -1;
+ }
+
+ _libssh2_init_if_needed();
+
+ fp = fopen(privatekey, "r");
+ if(!fp) {
+ _libssh2_error(session, LIBSSH2_ERROR_FILE,
+ "Unable to open private key file");
+ return -1;
+ }
+
+ rc = _libssh2_openssh_pem_parse(session, (const unsigned char *)passphrase,
+ fp, &decrypted);
+ fclose(fp);
+ if(rc) {
+ _libssh2_error(session, LIBSSH2_ERROR_FILE,
+ "Not an OpenSSH key file");
+ return rc;
+ }
+
+ /* We have a new key file, now try and parse it using supported types */
+ rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+ if(rc != 0 || buf == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Public key type in decrypted key data not found");
+ return -1;
+ }
+
+ rc = -1;
+
+#if LIBSSH2_ED25519
+ if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
+ rc = gen_publickey_from_ed25519_openssh_priv_data(session, decrypted,
+ method, method_len,
+ pubkeydata,
+ pubkeydata_len,
+ NULL);
+ }
+#endif
+#if LIBSSH2_RSA
+ if(strcmp("ssh-rsa", (const char *)buf) == 0) {
+ rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted,
+ method, method_len,
+ pubkeydata,
+ pubkeydata_len,
+ NULL);
+ }
+#endif
+#if LIBSSH2_DSA
+ if(strcmp("ssh-dss", (const char *)buf) == 0) {
+ rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted,
+ method, method_len,
+ pubkeydata,
+ pubkeydata_len,
+ NULL);
+ }
+#endif
+#if LIBSSH2_ECDSA
+ {
+ libssh2_curve_type type;
+
+ if(_libssh2_ecdsa_curve_type_from_name((const char *)buf,
+ &type) == 0) {
+ rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type,
+ decrypted,
+ method, method_len,
+ pubkeydata,
+ pubkeydata_len,
+ NULL);
+ }
+ }
+#endif
+
+ if(decrypted)
+ _libssh2_string_buf_free(session, decrypted);
+
+ if(rc != 0) {
+ _libssh2_error(session, LIBSSH2_ERROR_FILE,
+ "Unsupported OpenSSH key type");
+ }
+
+ return rc;
}
-#endif /* LIBSSH_DSA */
int
_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
@@ -1049,6 +2916,7 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
BIO* bp;
EVP_PKEY* pk;
int pktype;
+ int rc;
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
@@ -1056,31 +2924,35 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
privatekey);
bp = BIO_new_file(privatekey, "r");
- if (bp == NULL) {
+ if(bp == NULL) {
return _libssh2_error(session,
LIBSSH2_ERROR_FILE,
"Unable to extract public key from private key "
"file: Unable to open private key file");
}
- if (!EVP_get_cipherbyname("des")) {
- /* If this cipher isn't loaded it's a pretty good indication that none
- * are. I have *NO DOUBT* that there's a better way to deal with this
- * ($#&%#$(%$#( Someone buy me an OpenSSL manual and I'll read up on
- * it.
- */
- OpenSSL_add_all_ciphers();
- }
+
BIO_reset(bp);
- pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void*)passphrase);
+ pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase);
BIO_free(bp);
- if (pk == NULL) {
- return _libssh2_error(session,
- LIBSSH2_ERROR_FILE,
- "Unable to extract public key "
- "from private key file: "
- "Wrong passphrase or invalid/unrecognized "
- "private key file format");
+ if(pk == NULL) {
+
+ /* Try OpenSSH format */
+ rc = _libssh2_pub_priv_openssh_keyfile(session,
+ method,
+ method_len,
+ pubkeydata, pubkeydata_len,
+ privatekey, passphrase);
+ if(rc != 0) {
+ return _libssh2_error(session,
+ LIBSSH2_ERROR_FILE,
+ "Unable to extract public key "
+ "from private key file: "
+ "Wrong passphrase or invalid/unrecognized "
+ "private key file format");
+ }
+
+ return 0;
}
#ifdef HAVE_OPAQUE_STRUCTS
@@ -1089,7 +2961,7 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
pktype = pk->type;
#endif
- switch (pktype) {
+ switch(pktype) {
case EVP_PKEY_RSA :
st = gen_publickey_from_rsa_evp(
session, method, method_len, pubkeydata, pubkeydata_len, pk);
@@ -1102,6 +2974,13 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
break;
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+ case EVP_PKEY_EC :
+ st = gen_publickey_from_ec_evp(
+ session, method, method_len, pubkeydata, pubkeydata_len, pk);
+ break;
+#endif
+
default :
st = _libssh2_error(session,
LIBSSH2_ERROR_FILE,
@@ -1115,6 +2994,129 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
return st;
}
+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)
+{
+ int rc;
+ unsigned char *buf = NULL;
+ struct string_buf *decrypted = NULL;
+
+ if(key_ctx != NULL)
+ *key_ctx = NULL;
+
+ if(session == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Session is required");
+ return -1;
+ }
+
+ if(key_type != NULL && (strlen(key_type) > 11 || strlen(key_type) < 7)) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "type is invalid");
+ return -1;
+ }
+
+ _libssh2_init_if_needed();
+
+ rc = _libssh2_openssh_pem_parse_memory(session, passphrase,
+ privatekeydata,
+ privatekeydata_len, &decrypted);
+
+ if(rc) {
+ return rc;
+ }
+
+ /* We have a new key file, now try and parse it using supported types */
+ rc = _libssh2_get_string(decrypted, &buf, NULL);
+
+ if(rc != 0 || buf == NULL) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Public key type in decrypted key data not found");
+ return -1;
+ }
+
+ rc = -1;
+
+#if LIBSSH2_ED25519
+ if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
+ if(key_type == NULL || strcmp("ssh-ed25519", key_type) == 0) {
+ rc = gen_publickey_from_ed25519_openssh_priv_data(session,
+ decrypted,
+ method,
+ method_len,
+ pubkeydata,
+ pubkeydata_len,
+ (libssh2_ed25519_ctx**)key_ctx);
+ }
+ }
+#endif
+#if LIBSSH2_RSA
+ if(strcmp("ssh-rsa", (const char *)buf) == 0) {
+ if(key_type == NULL || strcmp("ssh-rsa", key_type) == 0) {
+ rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted,
+ method, method_len,
+ pubkeydata,
+ pubkeydata_len,
+ (libssh2_rsa_ctx**)key_ctx);
+ }
+ }
+#endif
+#if LIBSSH2_DSA
+ if(strcmp("ssh-dss", (const char *)buf) == 0) {
+ if(key_type == NULL || strcmp("ssh-dss", key_type) == 0) {
+ rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted,
+ method, method_len,
+ pubkeydata,
+ pubkeydata_len,
+ (libssh2_dsa_ctx**)key_ctx);
+ }
+ }
+#endif
+#if LIBSSH2_ECDSA
+{
+ libssh2_curve_type type;
+
+ if(_libssh2_ecdsa_curve_type_from_name((const char *)buf, &type) == 0) {
+ if(key_type == NULL || strcmp("ssh-ecdsa", key_type) == 0) {
+ rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type,
+ decrypted,
+ method, method_len,
+ pubkeydata,
+ pubkeydata_len,
+ (libssh2_ecdsa_ctx**)key_ctx);
+ }
+ }
+}
+#endif
+
+ if(decrypted)
+ _libssh2_string_buf_free(session, decrypted);
+
+ 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);
+}
+
int
_libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
unsigned char **method,
@@ -1135,28 +3137,34 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
"Computing public key from private key.");
bp = BIO_new_mem_buf((char *)privatekeydata, privatekeydata_len);
- if (!bp) {
+ if(!bp) {
return -1;
}
- if (!EVP_get_cipherbyname("des")) {
- /* If this cipher isn't loaded it's a pretty good indication that none
- * are. I have *NO DOUBT* that there's a better way to deal with this
- * ($#&%#$(%$#( Someone buy me an OpenSSL manual and I'll read up on
- * it.
- */
- OpenSSL_add_all_ciphers();
- }
+
BIO_reset(bp);
- pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void*)passphrase);
+ pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase);
BIO_free(bp);
- if (pk == NULL) {
- return _libssh2_error(session,
- LIBSSH2_ERROR_FILE,
- "Unable to extract public key "
- "from private key file: "
- "Wrong passphrase or invalid/unrecognized "
- "private key file format");
+ if(pk == NULL) {
+ /* Try OpenSSH format */
+ st = _libssh2_pub_priv_openssh_keyfilememory(session, NULL, NULL,
+ method,
+ method_len,
+ pubkeydata,
+ pubkeydata_len,
+ privatekeydata,
+ privatekeydata_len,
+ (unsigned const char *)passphrase);
+ if(st != 0) {
+ return _libssh2_error(session,
+ LIBSSH2_ERROR_FILE,
+ "Unable to extract public key "
+ "from private key file: "
+ "Wrong passphrase or invalid/unrecognized "
+ "private key file format");
+ }
+
+ return 0;
}
#ifdef HAVE_OPAQUE_STRUCTS
@@ -1165,7 +3173,7 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
pktype = pk->type;
#endif
- switch (pktype) {
+ switch(pktype) {
case EVP_PKEY_RSA :
st = gen_publickey_from_rsa_evp(session, method, method_len,
pubkeydata, pubkeydata_len, pk);
@@ -1176,6 +3184,12 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
pubkeydata, pubkeydata_len, pk);
break;
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+ case EVP_PKEY_EC :
+ st = gen_publickey_from_ec_evp(session, method, method_len,
+ pubkeydata, pubkeydata_len, pk);
+ break;
+#endif /* LIBSSH2_ECDSA */
default :
st = _libssh2_error(session,
LIBSSH2_ERROR_FILE,
@@ -1189,4 +3203,38 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
return st;
}
+void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
+{
+ *dhctx = BN_new(); /* Random from client */
+}
+
+int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+ _libssh2_bn *g, _libssh2_bn *p, int group_order,
+ _libssh2_bn_ctx *bnctx)
+{
+ /* Generate x and e */
+ BN_rand(*dhctx, group_order * 8 - 1, 0, -1);
+ BN_mod_exp(public, g, *dhctx, p, bnctx);
+ return 0;
+}
+
+int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+ _libssh2_bn *f, _libssh2_bn *p,
+ _libssh2_bn_ctx *bnctx)
+{
+ /* Compute the shared secret */
+ BN_mod_exp(secret, f, *dhctx, p, bnctx);
+ return 0;
+}
+
+void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
+{
+ BN_clear_free(*dhctx);
+ *dhctx = NULL;
+}
+
#endif /* LIBSSH2_OPENSSL */
diff --git a/libs/libssh2/src/openssl.h b/libs/libssh2/src/openssl.h
index 3ca71fa8a4..15518e0a66 100644
--- a/libs/libssh2/src/openssl.h
+++ b/libs/libssh2/src/openssl.h
@@ -40,7 +40,9 @@
#include <openssl/opensslconf.h>
#include <openssl/sha.h>
#include <openssl/rsa.h>
+#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
+#endif
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
@@ -70,6 +72,20 @@
# define LIBSSH2_DSA 1
#endif
+#ifdef OPENSSL_NO_ECDSA
+# define LIBSSH2_ECDSA 0
+#else
+# define LIBSSH2_ECDSA 1
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && \
+!defined(LIBRESSL_VERSION_NUMBER)
+# define LIBSSH2_ED25519 1
+#else
+# define LIBSSH2_ED25519 0
+#endif
+
+
#ifdef OPENSSL_NO_MD5
# define LIBSSH2_MD5 0
#else
@@ -117,6 +133,8 @@
# define LIBSSH2_3DES 1
#endif
+#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
+
#define _libssh2_random(buf, len) RAND_bytes ((buf), (len))
#define libssh2_prepare_iovec(vec, len) /* Empty. */
@@ -160,7 +178,8 @@ int _libssh2_sha256_init(libssh2_sha256_ctx *ctx);
EVP_MD_CTX_free(ctx); \
} while(0)
#else
-#define libssh2_sha256_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len)
+#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(const unsigned char *message, unsigned long len,
@@ -168,6 +187,54 @@ int _libssh2_sha256(const unsigned char *message, unsigned long len,
#define libssh2_sha256(x,y,z) _libssh2_sha256(x,y,z)
#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha384_ctx EVP_MD_CTX *
+#else
+#define libssh2_sha384_ctx EVP_MD_CTX
+#endif
+
+/* 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(const unsigned char *message, unsigned long len,
+ unsigned char *out);
+#define libssh2_sha384(x,y,z) _libssh2_sha384(x,y,z)
+
+#ifdef HAVE_OPAQUE_STRUCTS
+#define libssh2_sha512_ctx EVP_MD_CTX *
+#else
+#define libssh2_sha512_ctx EVP_MD_CTX
+#endif
+
+/* 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(const unsigned char *message, unsigned long len,
+ unsigned char *out);
+#define libssh2_sha512(x,y,z) _libssh2_sha512(x,y,z)
+
+#ifdef HAVE_OPAQUE_STRUCTS
#define libssh2_md5_ctx EVP_MD_CTX *
#else
#define libssh2_md5_ctx EVP_MD_CTX
@@ -226,12 +293,10 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx);
#define libssh2_hmac_cleanup(ctx) HMAC_cleanup(ctx)
#endif
-#define libssh2_crypto_init() \
- OpenSSL_add_all_algorithms(); \
- ENGINE_load_builtin_engines(); \
- ENGINE_register_all_complete()
-
-#define libssh2_crypto_exit()
+extern void _libssh2_openssl_crypto_init(void);
+extern void _libssh2_openssl_crypto_exit(void);
+#define libssh2_crypto_init() _libssh2_openssl_crypto_init()
+#define libssh2_crypto_exit() _libssh2_openssl_crypto_exit()
#define libssh2_rsa_ctx RSA
@@ -239,9 +304,46 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx);
#define libssh2_dsa_ctx DSA
-
#define _libssh2_dsa_free(dsactx) DSA_free(dsactx)
+#ifdef LIBSSH2_ECDSA
+#define libssh2_ecdsa_ctx EC_KEY
+#define _libssh2_ecdsa_free(ecdsactx) EC_KEY_free(ecdsactx)
+#define _libssh2_ec_key EC_KEY
+
+typedef enum {
+ LIBSSH2_EC_CURVE_NISTP256 = NID_X9_62_prime256v1,
+ LIBSSH2_EC_CURVE_NISTP384 = NID_secp384r1,
+ LIBSSH2_EC_CURVE_NISTP521 = NID_secp521r1
+}
+libssh2_curve_type;
+#else
+#define _libssh2_ec_key void
+#endif /* LIBSSH2_ECDSA */
+
+#ifdef LIBSSH2_ED25519
+
+typedef struct {
+ EVP_PKEY *public_key;
+ EVP_PKEY *private_key;
+} libssh2_curve25519_keys;
+
+#define libssh2_ed25519_ctx libssh2_curve25519_keys
+#define libssh2_x25519_ctx libssh2_curve25519_keys
+
+#define _libssh2_ed25519_new_ctx() calloc(1, sizeof(libssh2_ed25519_ctx))
+#define _libssh2_ed25519_free(ctx) do { \
+ if(ctx) { \
+ if(ctx->public_key) EVP_PKEY_free(ctx->public_key); \
+ if(ctx->private_key) EVP_PKEY_free(ctx->private_key); \
+ free(ctx); \
+ } \
+} while(0)
+
+#define _libssh2_x25519_free(ctx) _libssh2_ed25519_free(ctx)
+
+#endif /* ED25519 */
+
#define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void)
#ifdef HAVE_OPAQUE_STRUCTS
#define _libssh2_cipher_ctx EVP_CIPHER_CTX *
@@ -267,7 +369,7 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx);
#define _libssh2_cipher_3des EVP_des_ede3_cbc
#ifdef HAVE_OPAQUE_STRUCTS
-#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_reset(*(ctx))
+#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_free(*(ctx))
#else
#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx)
#endif
@@ -278,8 +380,6 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx);
#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_rand(bn, bits, top, bottom) BN_rand(bn, bits, top, bottom)
-#define _libssh2_bn_mod_exp(r, a, p, m, ctx) BN_mod_exp(r, a, p, m, ctx)
#define _libssh2_bn_set_word(bn, val) BN_set_word(bn, val)
#define _libssh2_bn_from_bin(bn, len, val) BN_bin2bn(val, len, bn)
#define _libssh2_bn_to_bin(bn, val) BN_bn2bin(bn, val)
@@ -287,7 +387,23 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx);
#define _libssh2_bn_bits(bn) BN_num_bits(bn)
#define _libssh2_bn_free(bn) BN_clear_free(bn)
+#define _libssh2_dh_ctx BIGNUM *
+#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
+ _libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
+ _libssh2_dh_secret(dhctx, secret, f, p, bnctx)
+#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx)
+extern void _libssh2_dh_init(_libssh2_dh_ctx *dhctx);
+extern int _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+ _libssh2_bn *g, _libssh2_bn *p,
+ int group_order,
+ _libssh2_bn_ctx *bnctx);
+extern int _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+ _libssh2_bn *f, _libssh2_bn *p,
+ _libssh2_bn_ctx *bnctx);
+extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
+
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);
-
diff --git a/libs/libssh2/src/packet.c b/libs/libssh2/src/packet.c
index c950b5dcfa..38ab62944a 100644
--- a/libs/libssh2/src/packet.c
+++ b/libs/libssh2/src/packet.c
@@ -87,7 +87,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
(void) datalen;
- if (listen_state->state == libssh2_NB_state_idle) {
+ if(listen_state->state == libssh2_NB_state_idle) {
unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5;
listen_state->sender_channel = _libssh2_ntohu32(s);
s += 4;
@@ -118,9 +118,9 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
listen_state->state = libssh2_NB_state_allocated;
}
- if (listen_state->state != libssh2_NB_state_sent) {
- while (listn) {
- if ((listn->port == (int) listen_state->port) &&
+ if(listen_state->state != libssh2_NB_state_sent) {
+ 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)) {
@@ -128,8 +128,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_CHANNEL *channel = NULL;
listen_state->channel = NULL;
- if (listen_state->state == libssh2_NB_state_allocated) {
- if (listn->queue_maxsize &&
+ if(listen_state->state == libssh2_NB_state_allocated) {
+ if(listn->queue_maxsize &&
(listn->queue_maxsize <= listn->queue_size)) {
/* Queue is full */
failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
@@ -140,7 +140,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
}
channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
- if (!channel) {
+ if(!channel) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a channel for "
"new connection");
@@ -156,7 +156,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
channel->
channel_type_len +
1);
- if (!channel->channel_type) {
+ if(!channel->channel_type) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a channel for new"
" connection");
@@ -203,12 +203,12 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
listen_state->state = libssh2_NB_state_created;
}
- if (listen_state->state == libssh2_NB_state_created) {
+ if(listen_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, listen_state->packet,
17, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
- else if (rc) {
+ else if(rc) {
listen_state->state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send channel "
@@ -216,7 +216,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
}
/* Link the channel into the end of the queue list */
- if (listen_state->channel) {
+ if(listen_state->channel) {
_libssh2_list_add(&listn->queue,
&listen_state->channel->node);
listn->queue_size++;
@@ -243,9 +243,10 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
rc = _libssh2_transport_send(session, listen_state->packet,
packet_len, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
listen_state->state = libssh2_NB_state_idle;
return _libssh2_error(session, rc, "Unable to send open failure");
@@ -273,7 +274,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
(void) datalen;
- if (x11open_state->state == libssh2_NB_state_idle) {
+ if(x11open_state->state == libssh2_NB_state_idle) {
unsigned char *s = data + (sizeof("x11") - 1) + 5;
x11open_state->sender_channel = _libssh2_ntohu32(s);
s += 4;
@@ -295,10 +296,10 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
x11open_state->state = libssh2_NB_state_allocated;
}
- if (session->x11) {
- if (x11open_state->state == libssh2_NB_state_allocated) {
+ if(session->x11) {
+ if(x11open_state->state == libssh2_NB_state_allocated) {
channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
- if (!channel) {
+ if(!channel) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"allocate a channel for new connection");
failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
@@ -310,7 +311,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
channel->channel_type = LIBSSH2_ALLOC(session,
channel->channel_type_len +
1);
- if (!channel->channel_type) {
+ if(!channel->channel_type) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"allocate a channel for new connection");
LIBSSH2_FREE(session, channel);
@@ -350,12 +351,13 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
x11open_state->state = libssh2_NB_state_created;
}
- if (x11open_state->state == libssh2_NB_state_created) {
+ if(x11open_state->state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, x11open_state->packet, 17,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
x11open_state->state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel open "
@@ -389,9 +391,10 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
rc = _libssh2_transport_send(session, x11open_state->packet, packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
x11open_state->state = libssh2_NB_state_idle;
return _libssh2_error(session, rc, "Unable to send open failure");
}
@@ -416,10 +419,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
size_t datalen, int macstate)
{
int rc = 0;
- char *message=NULL;
- char *language=NULL;
- size_t message_len=0;
- size_t language_len=0;
+ char *message = NULL;
+ char *language = NULL;
+ size_t message_len = 0;
+ size_t language_len = 0;
LIBSSH2_CHANNEL *channelp = NULL;
size_t data_head = 0;
unsigned char msg = data[0];
@@ -430,7 +433,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
"Packet type %d received, length=%d",
(int) msg, (int) datalen);
- if ((macstate == LIBSSH2_MAC_INVALID) &&
+ if((macstate == LIBSSH2_MAC_INVALID) &&
(!session->macerror ||
LIBSSH2_MACERROR(session, (char *) data, datalen))) {
/* Bad MAC input, but no callback set or non-zero return from the
@@ -456,9 +459,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
break;
}
- if (session->packAdd_state == libssh2_NB_state_allocated) {
+ if(session->packAdd_state == libssh2_NB_state_allocated) {
/* A couple exceptions to the packet adding rule: */
- switch (msg) {
+ switch(msg) {
/*
byte SSH_MSG_DISCONNECT
@@ -478,7 +481,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
/* 9 = packet_type(1) + reason(4) + message_len(4) */
message = (char *) data + 9;
- language_len = _libssh2_ntohu32(data + 9 + message_len);
+ language_len =
+ _libssh2_ntohu32(data + 9 + message_len);
language = (char *) data + 9 + message_len + 4;
if(language_len > (datalen-13-message_len)) {
@@ -489,9 +493,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
}
else
/* bad size, clear it */
- message_len=0;
+ message_len = 0;
}
- if (session->ssh_msg_disconnect) {
+ if(session->ssh_msg_disconnect) {
LIBSSH2_DISCONNECT(session, reason, message,
message_len, language, language_len);
}
@@ -511,11 +515,12 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
*/
case SSH_MSG_IGNORE:
- if (datalen >= 2) {
- if (session->ssh_msg_ignore) {
+ if(datalen >= 2) {
+ if(session->ssh_msg_ignore) {
LIBSSH2_IGNORE(session, (char *) data + 1, datalen - 1);
}
- } else if (session->ssh_msg_ignore) {
+ }
+ else if(session->ssh_msg_ignore) {
LIBSSH2_IGNORE(session, "", 0);
}
LIBSSH2_FREE(session, data);
@@ -531,7 +536,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
case SSH_MSG_DEBUG:
if(datalen >= 2) {
- int always_display= data[1];
+ int always_display = data[1];
if(datalen >= 6) {
message_len = _libssh2_ntohu32(data + 2);
@@ -539,14 +544,15 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
if(message_len <= (datalen - 10)) {
/* 6 = packet_type(1) + display(1) + message_len(4) */
message = (char *) data + 6;
- language_len = _libssh2_ntohu32(data + 6 + message_len);
+ language_len = _libssh2_ntohu32(data + 6 +
+ message_len);
if(language_len <= (datalen - 10 - message_len))
language = (char *) data + 10 + message_len;
}
}
- if (session->ssh_msg_debug) {
+ if(session->ssh_msg_debug) {
LIBSSH2_DEBUG(session, always_display, message,
message_len, language, language_len);
}
@@ -570,8 +576,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
case SSH_MSG_GLOBAL_REQUEST:
if(datalen >= 5) {
- uint32_t len =0;
- unsigned char want_reply=0;
+ uint32_t len = 0;
+ unsigned char want_reply = 0;
len = _libssh2_ntohu32(data + 1);
if(datalen >= (6 + len)) {
want_reply = data[5 + len];
@@ -582,13 +588,13 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
}
- if (want_reply) {
+ if(want_reply) {
static const unsigned char packet =
SSH_MSG_REQUEST_FAILURE;
libssh2_packet_add_jump_point5:
session->packAdd_state = libssh2_NB_state_jump5;
rc = _libssh2_transport_send(session, &packet, 1, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
}
}
@@ -624,7 +630,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
_libssh2_channel_locate(session,
_libssh2_ntohu32(data + 1));
- if (!channelp) {
+ if(!channelp) {
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
"Packet received for unknown channel");
LIBSSH2_FREE(session, data);
@@ -634,7 +640,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
#ifdef LIBSSH2DEBUG
{
uint32_t stream_id = 0;
- if (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)
+ if(msg == SSH_MSG_CHANNEL_EXTENDED_DATA)
stream_id = _libssh2_ntohu32(data + 5);
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
@@ -645,7 +651,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
stream_id);
}
#endif
- if ((channelp->remote.extended_data_ignore_mode ==
+ if((channelp->remote.extended_data_ignore_mode ==
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) &&
(msg == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
/* Pretend we didn't receive this */
@@ -654,14 +660,15 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Ignoring extended data and refunding %d bytes",
(int) (datalen - 13));
- if (channelp->read_avail + datalen - data_head >=
+ if(channelp->read_avail + datalen - data_head >=
channelp->remote.window_size)
datalen = channelp->remote.window_size -
channelp->read_avail + data_head;
channelp->remote.window_size -= datalen - data_head;
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
- "shrinking window size by %lu bytes to %lu, read_avail %lu",
+ "shrinking window size by %lu bytes to %lu, "
+ "read_avail %lu",
datalen - data_head,
channelp->remote.window_size,
channelp->read_avail);
@@ -675,7 +682,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
packAdd_channelp,
datalen - 13,
1, NULL);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
session->packAdd_state = libssh2_NB_state_idle;
@@ -686,7 +693,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
* REMEMBER! remote means remote as source of data,
* NOT remote window!
*/
- if (channelp->remote.packet_size < (datalen - data_head)) {
+ if(channelp->remote.packet_size < (datalen - data_head)) {
/*
* Spec says we MAY ignore bytes sent beyond
* packet_size
@@ -697,7 +704,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
" to receive, truncating");
datalen = channelp->remote.packet_size + data_head;
}
- if (channelp->remote.window_size <= channelp->read_avail) {
+ if(channelp->remote.window_size <= channelp->read_avail) {
/*
* Spec says we MAY ignore bytes sent beyond
* window_size
@@ -713,7 +720,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
/* Reset EOF status */
channelp->remote.eof = 0;
- if (channelp->read_avail + datalen - data_head >
+ if(channelp->read_avail + datalen - data_head >
channelp->remote.window_size) {
_libssh2_error(session,
LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
@@ -746,7 +753,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
channelp =
_libssh2_channel_locate(session,
_libssh2_ntohu32(data + 1));
- if (!channelp)
+ if(!channelp)
/* We may have freed already, just quietly ignore this... */
;
else {
@@ -783,7 +790,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
"Channel %d received request type %.*s (wr %X)",
channel, len, data + 9, want_reply);
- if (len == sizeof("exit-status") - 1
+ if(len == sizeof("exit-status") - 1
&& (sizeof("exit-status") - 1 + 9) <= datalen
&& !memcmp("exit-status", data + 9,
sizeof("exit-status") - 1)) {
@@ -793,7 +800,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
channelp =
_libssh2_channel_locate(session, channel);
- if (channelp && (sizeof("exit-status") + 13) <= datalen) {
+ if(channelp && (sizeof("exit-status") + 13) <= datalen) {
channelp->exit_status =
_libssh2_ntohu32(data + 9 + sizeof("exit-status"));
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
@@ -805,7 +812,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
}
}
- else if (len == sizeof("exit-signal") - 1
+ else if(len == sizeof("exit-signal") - 1
&& (sizeof("exit-signal") - 1 + 9) <= datalen
&& !memcmp("exit-signal", data + 9,
sizeof("exit-signal") - 1)) {
@@ -813,7 +820,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
if(datalen >= 20)
channelp = _libssh2_channel_locate(session, channel);
- if (channelp && (sizeof("exit-signal") + 13) <= datalen) {
+ if(channelp && (sizeof("exit-signal") + 13) <= datalen) {
/* set signal name (without SIG prefix) */
uint32_t namelen =
_libssh2_ntohu32(data + 9 + sizeof("exit-signal"));
@@ -826,10 +833,11 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
channelp->exit_signal = NULL;
}
- if (!channelp->exit_signal)
+ if(!channelp->exit_signal)
rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"memory for signal name");
- else if ((sizeof("exit-signal") + 13 + namelen <= datalen)) {
+ else if((sizeof("exit-signal") + 13 + namelen <=
+ datalen)) {
memcpy(channelp->exit_signal,
data + 13 + sizeof("exit-signal"), namelen);
channelp->exit_signal[namelen] = '\0';
@@ -845,14 +853,14 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
}
- if (want_reply) {
+ if(want_reply) {
unsigned char packet[5];
libssh2_packet_add_jump_point4:
session->packAdd_state = libssh2_NB_state_jump4;
packet[0] = SSH_MSG_CHANNEL_FAILURE;
- memcpy(&packet[1], data+1, 4);
+ memcpy(&packet[1], data + 1, 4);
rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
}
}
@@ -870,7 +878,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
channelp =
_libssh2_channel_locate(session,
_libssh2_ntohu32(data + 1));
- if (!channelp) {
+ if(!channelp) {
/* We may have freed already, just quietly ignore this... */
LIBSSH2_FREE(session, data);
session->packAdd_state = libssh2_NB_state_idle;
@@ -899,7 +907,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
case SSH_MSG_CHANNEL_OPEN:
if(datalen < 17)
;
- else if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
+ else if((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
((sizeof("forwarded-tcpip") - 1) ==
_libssh2_ntohu32(data + 1))
&&
@@ -915,7 +923,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
rc = packet_queue_listener(session, data, datalen,
&session->packAdd_Qlstn_state);
}
- else if ((datalen >= (sizeof("x11") + 4)) &&
+ else if((datalen >= (sizeof("x11") + 4)) &&
((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) &&
(memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) {
@@ -928,7 +936,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
rc = packet_x11_open(session, data, datalen,
&session->packAdd_x11open_state);
}
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
LIBSSH2_FREE(session, data);
@@ -970,10 +978,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
session->packAdd_state = libssh2_NB_state_sent;
}
- if (session->packAdd_state == libssh2_NB_state_sent) {
+ if(session->packAdd_state == libssh2_NB_state_sent) {
LIBSSH2_PACKET *packetp =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
- if (!packetp) {
+ if(!packetp) {
_libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
"memory for packet");
LIBSSH2_FREE(session, data);
@@ -989,10 +997,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
session->packAdd_state = libssh2_NB_state_sent1;
}
- if ((msg == SSH_MSG_KEXINIT &&
+ if((msg == SSH_MSG_KEXINIT &&
!(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) ||
(session->packAdd_state == libssh2_NB_state_sent2)) {
- if (session->packAdd_state == libssh2_NB_state_sent1) {
+ if(session->packAdd_state == libssh2_NB_state_sent1) {
/*
* Remote wants new keys
* Well, it's already in the brigade,
@@ -1021,7 +1029,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
* send NEWKEYS yet, otherwise remote will drop us like a rock
*/
rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
}
@@ -1046,8 +1054,8 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Looking for packet of type: %d", (int) packet_type);
- while (packet) {
- if (packet->data[0] == packet_type
+ while(packet) {
+ if(packet->data[0] == packet_type
&& (packet->data_len >= (match_ofs + match_len))
&& (!match_buf ||
(memcmp(packet->data + match_ofs, match_buf,
@@ -1084,7 +1092,7 @@ _libssh2_packet_askv(LIBSSH2_SESSION * session,
int i, packet_types_len = strlen((char *) packet_types);
for(i = 0; i < packet_types_len; i++) {
- if (0 == _libssh2_packet_ask(session, packet_types[i], data,
+ if(0 == _libssh2_packet_ask(session, packet_types[i], data,
data_len, match_ofs,
match_buf, match_len)) {
return 0;
@@ -1111,8 +1119,8 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
size_t match_len,
packet_require_state_t *state)
{
- if (state->start == 0) {
- if (_libssh2_packet_ask(session, packet_type, data, data_len,
+ if(state->start == 0) {
+ if(_libssh2_packet_ask(session, packet_type, data, data_len,
match_ofs, match_buf,
match_len) == 0) {
/* A packet was available in the packet brigade */
@@ -1122,26 +1130,28 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
state->start = time(NULL);
}
- while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+ while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
int ret = _libssh2_transport_read(session);
- if (ret == LIBSSH2_ERROR_EAGAIN)
+ if(ret == LIBSSH2_ERROR_EAGAIN)
return ret;
- else if (ret < 0) {
+ else if(ret < 0) {
state->start = 0;
/* an error which is not just because of blocking */
return ret;
- } else if (ret == packet_type) {
+ }
+ else if(ret == packet_type) {
/* Be lazy, let packet_ask pull it out of the brigade */
ret = _libssh2_packet_ask(session, packet_type, data, data_len,
match_ofs, match_buf, match_len);
state->start = 0;
return ret;
- } else if (ret == 0) {
+ }
+ else if(ret == 0) {
/* nothing available, wait until data arrives or we time out */
long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) -
state->start);
- if (left <= 0) {
+ if(left <= 0) {
state->start = 0;
return LIBSSH2_ERROR_TIMEOUT;
}
@@ -1169,13 +1179,13 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
unsigned char i, all_packets[255];
int ret;
- if (*state == libssh2_NB_state_idle) {
+ if(*state == libssh2_NB_state_idle) {
for(i = 1; i < 255; i++) {
all_packets[i - 1] = i;
}
all_packets[254] = 0;
- if (_libssh2_packet_askv(session, all_packets, &data, &data_len, 0,
+ if(_libssh2_packet_askv(session, all_packets, &data, &data_len, 0,
NULL, 0) == 0) {
i = data[0];
/* A packet was available in the packet brigade, burn it */
@@ -1188,20 +1198,22 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session,
*state = libssh2_NB_state_created;
}
- while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+ while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
ret = _libssh2_transport_read(session);
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
- } else if (ret < 0) {
+ }
+ else if(ret < 0) {
*state = libssh2_NB_state_idle;
return ret;
- } else if (ret == 0) {
+ }
+ else if(ret == 0) {
/* FIXME: this might busyloop */
continue;
}
/* Be lazy, let packet_ask pull it out of the brigade */
- if (0 ==
+ if(0 ==
_libssh2_packet_ask(session, (unsigned char)ret,
&data, &data_len, 0, NULL, 0)) {
/* Smoke 'em if you got 'em */
@@ -1231,37 +1243,37 @@ _libssh2_packet_requirev(LIBSSH2_SESSION *session,
const unsigned char *match_buf, size_t match_len,
packet_requirev_state_t * state)
{
- if (_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs,
+ if(_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs,
match_buf, match_len) == 0) {
/* One of the packets listed was available in the packet brigade */
state->start = 0;
return 0;
}
- if (state->start == 0) {
+ if(state->start == 0) {
state->start = time(NULL);
}
- while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
+ while(session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
int ret = _libssh2_transport_read(session);
- if ((ret < 0) && (ret != LIBSSH2_ERROR_EAGAIN)) {
+ if((ret < 0) && (ret != LIBSSH2_ERROR_EAGAIN)) {
state->start = 0;
return ret;
}
- if (ret <= 0) {
+ if(ret <= 0) {
long left = LIBSSH2_READ_TIMEOUT -
(long)(time(NULL) - state->start);
- if (left <= 0) {
+ if(left <= 0) {
state->start = 0;
return LIBSSH2_ERROR_TIMEOUT;
}
- else if (ret == LIBSSH2_ERROR_EAGAIN) {
+ else if(ret == LIBSSH2_ERROR_EAGAIN) {
return ret;
}
}
- if (strchr((char *) packet_types, ret)) {
+ if(strchr((char *) packet_types, ret)) {
/* Be lazy, let packet_ask pull it out of the brigade */
return _libssh2_packet_askv(session, packet_types, data,
data_len, match_ofs, match_buf,
diff --git a/libs/libssh2/src/pem.c b/libs/libssh2/src/pem.c
index 9f51bba3b5..53f58c2ef1 100644
--- a/libs/libssh2/src/pem.c
+++ b/libs/libssh2/src/pem.c
@@ -43,23 +43,23 @@ readline(char *line, int line_size, FILE * fp)
{
size_t len;
- if (!line) {
+ if(!line) {
return -1;
}
- if (!fgets(line, line_size, fp)) {
+ if(!fgets(line, line_size, fp)) {
return -1;
}
- if (*line) {
+ if(*line) {
len = strlen(line);
- if (len > 0 && line[len - 1] == '\n') {
+ if(len > 0 && line[len - 1] == '\n') {
line[len - 1] = '\0';
}
}
- if (*line) {
+ if(*line) {
len = strlen(line);
- if (len > 0 && line[len - 1] == '\r') {
+ if(len > 0 && line[len - 1] == '\r') {
line[len - 1] = '\0';
}
}
@@ -76,14 +76,14 @@ readline_memory(char *line, size_t line_size,
off = *filedata_offset;
- for (len = 0; off + len < filedata_len && len < line_size; len++) {
- if (filedata[off + len] == '\n' ||
+ for(len = 0; off + len < filedata_len && len < line_size - 1; len++) {
+ if(filedata[off + len] == '\n' ||
filedata[off + len] == '\r') {
break;
}
}
- if (len) {
+ if(len) {
memcpy(line, filedata + off, len);
*filedata_offset += len;
}
@@ -96,36 +96,86 @@ readline_memory(char *line, size_t line_size,
#define LINE_SIZE 128
+static const char *crypt_annotation = "Proc-Type: 4,ENCRYPTED";
+
+static unsigned char hex_decode(char digit)
+{
+ return (digit >= 'A') ? 0xA + (digit - 'A') : (digit - '0');
+}
+
int
_libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin,
const char *headerend,
+ const unsigned char *passphrase,
FILE * fp, unsigned char **data, unsigned int *datalen)
{
char line[LINE_SIZE];
+ unsigned char iv[LINE_SIZE];
char *b64data = NULL;
unsigned int b64datalen = 0;
int ret;
+ const LIBSSH2_CRYPT_METHOD *method = NULL;
do {
*line = '\0';
- if (readline(line, LINE_SIZE, fp)) {
+ if(readline(line, LINE_SIZE, fp)) {
return -1;
}
}
- while (strcmp(line, headerbegin) != 0);
+ while(strcmp(line, headerbegin) != 0);
- *line = '\0';
+ if(readline(line, LINE_SIZE, fp)) {
+ return -1;
+ }
+
+ if(passphrase &&
+ memcmp(line, crypt_annotation, strlen(crypt_annotation)) == 0) {
+ const LIBSSH2_CRYPT_METHOD **all_methods, *cur_method;
+ int i;
+
+ if(readline(line, LINE_SIZE, fp)) {
+ ret = -1;
+ goto out;
+ }
+
+ all_methods = libssh2_crypt_methods();
+ while((cur_method = *all_methods++)) {
+ if(*cur_method->pem_annotation &&
+ memcmp(line, cur_method->pem_annotation,
+ strlen(cur_method->pem_annotation)) == 0) {
+ method = cur_method;
+ memcpy(iv, line + strlen(method->pem_annotation) + 1,
+ 2*method->iv_len);
+ }
+ }
+
+ /* None of the available crypt methods were able to decrypt the key */
+ if(method == NULL)
+ return -1;
+
+ /* Decode IV from hex */
+ for(i = 0; i < method->iv_len; ++i) {
+ iv[i] = hex_decode(iv[2*i]) << 4;
+ iv[i] |= hex_decode(iv[2*i + 1]);
+ }
+
+ /* skip to the next line */
+ if(readline(line, LINE_SIZE, fp)) {
+ ret = -1;
+ goto out;
+ }
+ }
do {
- if (*line) {
+ if(*line) {
char *tmp;
size_t linelen;
linelen = strlen(line);
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
- if (!tmp) {
+ if(!tmp) {
ret = -1;
goto out;
}
@@ -136,25 +186,102 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session,
*line = '\0';
- if (readline(line, LINE_SIZE, fp)) {
+ if(readline(line, LINE_SIZE, fp)) {
ret = -1;
goto out;
}
- } while (strcmp(line, headerend) != 0);
+ } while(strcmp(line, headerend) != 0);
- if (!b64data) {
+ if(!b64data) {
return -1;
}
- if (libssh2_base64_decode(session, (char**) data, datalen,
+ if(libssh2_base64_decode(session, (char **) data, datalen,
b64data, b64datalen)) {
ret = -1;
goto out;
}
+ if(method) {
+ /* Set up decryption */
+ int free_iv = 0, free_secret = 0, len_decrypted = 0, padding = 0;
+ int blocksize = method->blocksize;
+ void *abstract;
+ unsigned char secret[2*MD5_DIGEST_LENGTH];
+ libssh2_md5_ctx fingerprint_ctx;
+
+ /* Perform key derivation (PBKDF1/MD5) */
+ if(!libssh2_md5_init(&fingerprint_ctx)) {
+ 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)) {
+ 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 */
+ if(method->init(session, method, iv, &free_iv, secret,
+ &free_secret, 0, &abstract)) {
+ _libssh2_explicit_zero((char *)secret, sizeof(secret));
+ LIBSSH2_FREE(session, data);
+ ret = -1;
+ goto out;
+ }
+
+ if(free_secret) {
+ _libssh2_explicit_zero((char *)secret, sizeof(secret));
+ }
+
+ /* Do the actual decryption */
+ if((*datalen % blocksize) != 0) {
+ _libssh2_explicit_zero((char *)secret, sizeof(secret));
+ method->dtor(session, &abstract);
+ _libssh2_explicit_zero(*data, *datalen);
+ LIBSSH2_FREE(session, *data);
+ ret = -1;
+ goto out;
+ }
+
+ while(len_decrypted <= (int)*datalen - blocksize) {
+ if(method->crypt(session, *data + len_decrypted, blocksize,
+ &abstract)) {
+ 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;
+ }
+
+ /* Account for padding */
+ padding = (*data)[*datalen - 1];
+ memset(&(*data)[*datalen-padding], 0, padding);
+ *datalen -= padding;
+
+ /* Clean up */
+ _libssh2_explicit_zero((char *)secret, sizeof(secret));
+ method->dtor(session, &abstract);
+ }
+
ret = 0;
out:
- if (b64data) {
+ if(b64data) {
+ _libssh2_explicit_zero(b64data, b64datalen);
LIBSSH2_FREE(session, b64data);
}
return ret;
@@ -176,22 +303,22 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
do {
*line = '\0';
- if (readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+ if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
return -1;
}
}
- while (strcmp(line, headerbegin) != 0);
+ while(strcmp(line, headerbegin) != 0);
*line = '\0';
do {
- if (*line) {
+ if(*line) {
char *tmp;
size_t linelen;
linelen = strlen(line);
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
- if (!tmp) {
+ if(!tmp) {
ret = -1;
goto out;
}
@@ -202,17 +329,17 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
*line = '\0';
- if (readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+ if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
ret = -1;
goto out;
}
- } while (strcmp(line, headerend) != 0);
+ } while(strcmp(line, headerend) != 0);
- if (!b64data) {
+ if(!b64data) {
return -1;
}
- if (libssh2_base64_decode(session, (char**) data, datalen,
+ if(libssh2_base64_decode(session, (char **) data, datalen,
b64data, b64datalen)) {
ret = -1;
goto out;
@@ -220,12 +347,462 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
ret = 0;
out:
- if (b64data) {
+ if(b64data) {
+ _libssh2_explicit_zero(b64data, b64datalen);
+ LIBSSH2_FREE(session, b64data);
+ }
+ return ret;
+}
+
+/* OpenSSH formatted keys */
+#define AUTH_MAGIC "openssh-key-v1"
+#define OPENSSH_HEADER_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----"
+#define OPENSSH_HEADER_END "-----END OPENSSH PRIVATE KEY-----"
+
+static int
+_libssh2_openssh_pem_parse_data(LIBSSH2_SESSION * session,
+ const unsigned char *passphrase,
+ const char *b64data, size_t b64datalen,
+ struct string_buf **decrypted_buf)
+{
+ const LIBSSH2_CRYPT_METHOD *method = NULL;
+ struct string_buf decoded, decrypted, kdf_buf;
+ unsigned char *ciphername = NULL;
+ unsigned char *kdfname = NULL;
+ unsigned char *kdf = NULL;
+ unsigned char *buf = NULL;
+ unsigned char *salt = NULL;
+ uint32_t nkeys, check1, check2;
+ uint32_t rounds = 0;
+ unsigned char *key = NULL;
+ unsigned char *key_part = NULL;
+ unsigned char *iv_part = NULL;
+ unsigned char *f = NULL;
+ unsigned int f_len = 0;
+ int ret = 0, keylen = 0, ivlen = 0, total_len = 0;
+ size_t kdf_len = 0, tmp_len = 0, salt_len = 0;
+
+ if(decrypted_buf)
+ *decrypted_buf = NULL;
+
+ /* decode file */
+ if(libssh2_base64_decode(session, (char **)&f, &f_len,
+ b64data, b64datalen)) {
+ ret = -1;
+ goto out;
+ }
+
+ /* Parse the file */
+ decoded.data = (unsigned char *)f;
+ decoded.dataptr = (unsigned char *)f;
+ decoded.len = f_len;
+
+ if(decoded.len < strlen(AUTH_MAGIC)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, "key too short");
+ goto out;
+ }
+
+ if(strncmp((char *) decoded.dataptr, AUTH_MAGIC,
+ strlen(AUTH_MAGIC)) != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "key auth magic mismatch");
+ goto out;
+ }
+
+ decoded.dataptr += strlen(AUTH_MAGIC) + 1;
+
+ if(_libssh2_get_string(&decoded, &ciphername, &tmp_len) ||
+ tmp_len == 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "ciphername is missing");
+ goto out;
+ }
+
+ if(_libssh2_get_string(&decoded, &kdfname, &tmp_len) ||
+ tmp_len == 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "kdfname is missing");
+ goto out;
+ }
+
+ if(_libssh2_get_string(&decoded, &kdf, &kdf_len)) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "kdf is missing");
+ goto out;
+ }
+ else {
+ kdf_buf.data = kdf;
+ kdf_buf.dataptr = kdf;
+ kdf_buf.len = kdf_len;
+ }
+
+ if((passphrase == NULL || strlen((const char *)passphrase) == 0) &&
+ strcmp((const char *)ciphername, "none") != 0) {
+ /* passphrase required */
+ ret = LIBSSH2_ERROR_KEYFILE_AUTH_FAILED;
+ goto out;
+ }
+
+ if(strcmp((const char *)kdfname, "none") != 0 &&
+ strcmp((const char *)kdfname, "bcrypt") != 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "unknown cipher");
+ goto out;
+ }
+
+ if(!strcmp((const char *)kdfname, "none") &&
+ strcmp((const char *)ciphername, "none") != 0) {
+ ret =_libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "invalid format");
+ goto out;
+ }
+
+ if(_libssh2_get_u32(&decoded, &nkeys) != 0 || nkeys != 1) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Multiple keys are unsupported");
+ goto out;
+ }
+
+ /* unencrypted public key */
+
+ if(_libssh2_get_string(&decoded, &buf, &tmp_len) || tmp_len == 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Invalid private key; "
+ "expect embedded public key");
+ goto out;
+ }
+
+ if(_libssh2_get_string(&decoded, &buf, &tmp_len) || tmp_len == 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Private key data not found");
+ goto out;
+ }
+
+ /* decode encrypted private key */
+ decrypted.data = decrypted.dataptr = buf;
+ decrypted.len = tmp_len;
+
+ if(ciphername && strcmp((const char *)ciphername, "none") != 0) {
+ const LIBSSH2_CRYPT_METHOD **all_methods, *cur_method;
+
+ all_methods = libssh2_crypt_methods();
+ while((cur_method = *all_methods++)) {
+ if(*cur_method->name &&
+ memcmp(ciphername, cur_method->name,
+ strlen(cur_method->name)) == 0) {
+ method = cur_method;
+ }
+ }
+
+ /* None of the available crypt methods were able to decrypt the key */
+
+ if(method == NULL) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "No supported cipher found");
+ goto out;
+ }
+ }
+
+ if(method) {
+ int free_iv = 0, free_secret = 0, len_decrypted = 0;
+ int blocksize;
+ void *abstract = NULL;
+
+ keylen = method->secret_len;
+ ivlen = method->iv_len;
+ total_len = keylen + ivlen;
+
+ key = LIBSSH2_CALLOC(session, total_len);
+ if(key == NULL) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Could not alloc key");
+ goto out;
+ }
+
+ if(strcmp((const char *)kdfname, "bcrypt") == 0 &&
+ passphrase != NULL) {
+ if((_libssh2_get_string(&kdf_buf, &salt, &salt_len)) ||
+ (_libssh2_get_u32(&kdf_buf, &rounds) != 0) ) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "kdf contains unexpected values");
+ LIBSSH2_FREE(session, key);
+ goto out;
+ }
+
+ if(_libssh2_bcrypt_pbkdf((const char *)passphrase,
+ strlen((const char *)passphrase),
+ salt, salt_len, key,
+ keylen + ivlen, rounds) < 0) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_DECRYPT,
+ "invalid format");
+ LIBSSH2_FREE(session, key);
+ goto out;
+ }
+ }
+ else {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_KEYFILE_AUTH_FAILED,
+ "bcrypted without passphrase");
+ LIBSSH2_FREE(session, key);
+ goto out;
+ }
+
+ /* Set up decryption */
+ blocksize = method->blocksize;
+
+ key_part = LIBSSH2_CALLOC(session, keylen);
+ if(key_part == NULL) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Could not alloc key part");
+ goto out;
+ }
+
+ iv_part = LIBSSH2_CALLOC(session, ivlen);
+ if(iv_part == NULL) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Could not alloc iv part");
+ goto out;
+ }
+
+ memcpy(key_part, key, keylen);
+ memcpy(iv_part, key + keylen, ivlen);
+
+ /* Initialize the decryption */
+ if(method->init(session, method, iv_part, &free_iv, key_part,
+ &free_secret, 0, &abstract)) {
+ ret = LIBSSH2_ERROR_DECRYPT;
+ goto out;
+ }
+
+ /* Do the actual decryption */
+ if((decrypted.len % blocksize) != 0) {
+ method->dtor(session, &abstract);
+ ret = LIBSSH2_ERROR_DECRYPT;
+ goto out;
+ }
+
+ while((size_t)len_decrypted <= decrypted.len - blocksize) {
+ if(method->crypt(session, decrypted.data + len_decrypted,
+ blocksize,
+ &abstract)) {
+ ret = LIBSSH2_ERROR_DECRYPT;
+ method->dtor(session, &abstract);
+ goto out;
+ }
+
+ len_decrypted += blocksize;
+ }
+
+ /* No padding */
+
+ method->dtor(session, &abstract);
+ }
+
+ /* Check random bytes match */
+
+ if(_libssh2_get_u32(&decrypted, &check1) != 0 ||
+ _libssh2_get_u32(&decrypted, &check2) != 0 ||
+ check1 != check2) {
+ _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+ "Private key unpack failed (correct password?)");
+ ret = LIBSSH2_ERROR_KEYFILE_AUTH_FAILED;
+ goto out;
+ }
+
+ if(decrypted_buf != NULL) {
+ /* copy data to out-going buffer */
+ struct string_buf *out_buf = _libssh2_string_buf_new(session);
+ if(!out_buf) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for "
+ "decrypted struct");
+ goto out;
+ }
+
+ out_buf->data = LIBSSH2_CALLOC(session, decrypted.len);
+ if(out_buf->data == NULL) {
+ ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for "
+ "decrypted struct");
+ _libssh2_string_buf_free(session, out_buf);
+ goto out;
+ }
+ memcpy(out_buf->data, decrypted.data, decrypted.len);
+ out_buf->dataptr = out_buf->data +
+ (decrypted.dataptr - decrypted.data);
+ out_buf->len = decrypted.len;
+
+ *decrypted_buf = out_buf;
+ }
+
+out:
+
+ /* Clean up */
+ if(key) {
+ _libssh2_explicit_zero(key, total_len);
+ LIBSSH2_FREE(session, key);
+ }
+ if(key_part) {
+ _libssh2_explicit_zero(key_part, keylen);
+ LIBSSH2_FREE(session, key_part);
+ }
+ if(iv_part) {
+ _libssh2_explicit_zero(iv_part, ivlen);
+ LIBSSH2_FREE(session, iv_part);
+ }
+ if(f) {
+ _libssh2_explicit_zero(f, f_len);
+ LIBSSH2_FREE(session, f);
+ }
+
+ return ret;
+}
+
+int
+_libssh2_openssh_pem_parse(LIBSSH2_SESSION * session,
+ const unsigned char *passphrase,
+ FILE * fp, struct string_buf **decrypted_buf)
+{
+ char line[LINE_SIZE];
+ char *b64data = NULL;
+ unsigned int b64datalen = 0;
+ int ret = 0;
+
+ /* read file */
+
+ do {
+ *line = '\0';
+
+ if(readline(line, LINE_SIZE, fp)) {
+ return -1;
+ }
+ }
+ while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0);
+
+ if(readline(line, LINE_SIZE, fp)) {
+ return -1;
+ }
+
+ do {
+ if(*line) {
+ char *tmp;
+ size_t linelen;
+
+ linelen = strlen(line);
+ tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
+ if(!tmp) {
+ ret = -1;
+ goto out;
+ }
+ memcpy(tmp + b64datalen, line, linelen);
+ b64data = tmp;
+ b64datalen += linelen;
+ }
+
+ *line = '\0';
+
+ if(readline(line, LINE_SIZE, fp)) {
+ ret = -1;
+ goto out;
+ }
+ } while(strcmp(line, OPENSSH_HEADER_END) != 0);
+
+ if(!b64data) {
+ return -1;
+ }
+
+ ret = _libssh2_openssh_pem_parse_data(session,
+ passphrase,
+ (const char *)b64data,
+ (size_t)b64datalen,
+ decrypted_buf);
+
+ if(b64data) {
+ _libssh2_explicit_zero(b64data, b64datalen);
LIBSSH2_FREE(session, b64data);
}
+
+out:
+
return ret;
}
+int
+_libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
+ const unsigned char *passphrase,
+ const char *filedata, size_t filedata_len,
+ struct string_buf **decrypted_buf)
+{
+ char line[LINE_SIZE];
+ char *b64data = NULL;
+ unsigned int b64datalen = 0;
+ size_t off = 0;
+ int ret;
+
+ if(filedata == NULL || filedata_len <= 0) {
+ return -1;
+ }
+
+ do {
+
+ *line = '\0';
+
+ if(off >= filedata_len) {
+ return -1;
+ }
+
+ if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+ return -1;
+ }
+ }
+ while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0);
+
+ *line = '\0';
+
+ do {
+ if (*line) {
+ char *tmp;
+ size_t linelen;
+
+ linelen = strlen(line);
+ tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
+ if(!tmp) {
+ ret = -1;
+ goto out;
+ }
+ memcpy(tmp + b64datalen, line, linelen);
+ b64data = tmp;
+ b64datalen += linelen;
+ }
+
+ *line = '\0';
+
+ if(off >= filedata_len) {
+ ret = -1;
+ goto out;
+ }
+
+ if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+ ret = -1;
+ goto out;
+ }
+ } while(strcmp(line, OPENSSH_HEADER_END) != 0);
+
+ if(!b64data) {
+ return -1;
+ }
+
+ ret = _libssh2_openssh_pem_parse_data(session, passphrase, b64data,
+ b64datalen, decrypted_buf);
+
+out:
+ if(b64data) {
+ _libssh2_explicit_zero(b64data, b64datalen);
+ LIBSSH2_FREE(session, b64data);
+ }
+ return ret;
+
+}
+
static int
read_asn1_length(const unsigned char *data,
unsigned int datalen, unsigned int *len)
@@ -233,27 +810,28 @@ read_asn1_length(const unsigned char *data,
unsigned int lenlen;
int nextpos;
- if (datalen < 1) {
+ if(datalen < 1) {
return -1;
}
*len = data[0];
- if (*len >= 0x80) {
+ if(*len >= 0x80) {
lenlen = *len & 0x7F;
*len = data[1];
- if (1 + lenlen > datalen) {
+ if(1 + lenlen > datalen) {
return -1;
}
- if (lenlen > 1) {
+ if(lenlen > 1) {
*len <<= 8;
*len |= data[2];
}
- } else {
+ }
+ else {
lenlen = 0;
}
nextpos = 1 + lenlen;
- if (lenlen > 2 || 1 + lenlen + *len > datalen) {
+ if(lenlen > 2 || 1 + lenlen + *len > datalen) {
return -1;
}
@@ -266,11 +844,11 @@ _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen)
unsigned int len;
int lenlen;
- if (*datalen < 1) {
+ if(*datalen < 1) {
return -1;
}
- if ((*data)[0] != '\x30') {
+ if((*data)[0] != '\x30') {
return -1;
}
@@ -278,7 +856,7 @@ _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen)
(*datalen)--;
lenlen = read_asn1_length(*data, *datalen, &len);
- if (lenlen < 0 || lenlen + len != *datalen) {
+ if(lenlen < 0 || lenlen + len != *datalen) {
return -1;
}
@@ -295,11 +873,11 @@ _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
unsigned int len;
int lenlen;
- if (*datalen < 1) {
+ if(*datalen < 1) {
return -1;
}
- if ((*data)[0] != '\x02') {
+ if((*data)[0] != '\x02') {
return -1;
}
@@ -307,7 +885,7 @@ _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
(*datalen)--;
lenlen = read_asn1_length(*data, *datalen, &len);
- if (lenlen < 0 || lenlen + len > *datalen) {
+ if(lenlen < 0 || lenlen + len > *datalen) {
return -1;
}
diff --git a/libs/libssh2/src/publickey.c b/libs/libssh2/src/publickey.c
index bfee0a8420..f26c6327dc 100644
--- a/libs/libssh2/src/publickey.c
+++ b/libs/libssh2/src/publickey.c
@@ -60,7 +60,7 @@ static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_response_codes[] =
{LIBSSH2_PUBLICKEY_RESPONSE_STATUS, "status", sizeof("status") - 1},
{LIBSSH2_PUBLICKEY_RESPONSE_VERSION, "version", sizeof("version") - 1},
{LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY, "publickey",
- sizeof("publickey") - 1} ,
+ sizeof("publickey") - 1},
{0, NULL, 0}
};
@@ -78,13 +78,13 @@ static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_response_codes[] =
#define LIBSSH2_PUBLICKEY_STATUS_CODE_MAX 8
static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_status_codes[] = {
- {LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1} ,
+ {LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1},
{LIBSSH2_PUBLICKEY_ACCESS_DENIED, "access denied",
sizeof("access denied") - 1},
{LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED, "storage exceeded",
- sizeof("storage exceeded") - 1} ,
+ sizeof("storage exceeded") - 1},
{LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED, "version not supported",
- sizeof("version not supported") - 1} ,
+ sizeof("version not supported") - 1},
{LIBSSH2_PUBLICKEY_KEY_NOT_FOUND, "key not found",
sizeof("key not found") - 1},
{LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED, "key not supported",
@@ -110,13 +110,14 @@ publickey_status_error(const LIBSSH2_PUBLICKEY *pkey,
const char *msg;
/* GENERAL_FAILURE got remapped between version 1 and 2 */
- if (status == 6 && pkey && pkey->version == 1) {
+ if(status == 6 && pkey && pkey->version == 1) {
status = 7;
}
- if (status < 0 || status > LIBSSH2_PUBLICKEY_STATUS_CODE_MAX) {
+ if(status < 0 || status > LIBSSH2_PUBLICKEY_STATUS_CODE_MAX) {
msg = "unknown";
- } else {
+ }
+ else {
msg = publickey_status_codes[status].name;
}
@@ -139,11 +140,12 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
*data = NULL; /* default to nothing returned */
*data_len = 0;
- if (pkey->receive_state == libssh2_NB_state_idle) {
+ if(pkey->receive_state == libssh2_NB_state_idle) {
rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc != 4) {
+ }
+ else if(rc != 4) {
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid response from publickey subsystem");
}
@@ -151,7 +153,7 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
pkey->receive_packet_len = _libssh2_ntohu32(buffer);
pkey->receive_packet =
LIBSSH2_ALLOC(session, pkey->receive_packet_len);
- if (!pkey->receive_packet) {
+ if(!pkey->receive_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate publickey response "
"buffer");
@@ -160,12 +162,13 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
pkey->receive_state = libssh2_NB_state_sent;
}
- if (pkey->receive_state == libssh2_NB_state_sent) {
+ if(pkey->receive_state == libssh2_NB_state_sent) {
rc = _libssh2_channel_read(channel, 0, (char *) pkey->receive_packet,
pkey->receive_packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc != (int)pkey->receive_packet_len) {
+ }
+ else if(rc != (int)pkey->receive_packet_len) {
LIBSSH2_FREE(session, pkey->receive_packet);
pkey->receive_packet = NULL;
pkey->receive_state = libssh2_NB_state_idle;
@@ -195,20 +198,20 @@ publickey_response_id(unsigned char **pdata, size_t data_len)
unsigned char *data = *pdata;
const LIBSSH2_PUBLICKEY_CODE_LIST *codes = publickey_response_codes;
- if (data_len < 4) {
+ if(data_len < 4) {
/* Malformed response */
return -1;
}
response_len = _libssh2_ntohu32(data);
data += 4;
data_len -= 4;
- if (data_len < response_len) {
+ if(data_len < response_len) {
/* Malformed response */
return -1;
}
- while (codes->name) {
- if ((unsigned long)codes->name_len == response_len &&
+ while(codes->name) {
+ if((unsigned long)codes->name_len == response_len &&
strncmp(codes->name, (char *) data, response_len) == 0) {
*pdata = data + response_len;
return codes->code;
@@ -231,28 +234,41 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
size_t data_len;
int response;
- while (1) {
+ while(1) {
int rc = publickey_packet_receive(pkey, &data, &data_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
}
+ if(data_len < 4) {
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "Publickey response too small");
+ }
+
s = data;
response = publickey_response_id(&s, data_len);
- switch (response) {
+ switch(response) {
case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
/* Error, or processing complete */
{
- unsigned long status = _libssh2_ntohu32(s);
+ unsigned long status = 0;
+
+ if(data_len < 8) {
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "Publickey response too small");
+ }
+
+ status = _libssh2_ntohu32(s);
LIBSSH2_FREE(session, data);
- if (status == LIBSSH2_PUBLICKEY_SUCCESS)
+ if(status == LIBSSH2_PUBLICKEY_SUCCESS)
return 0;
publickey_status_error(pkey, session, status);
@@ -260,7 +276,7 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
}
default:
LIBSSH2_FREE(session, data);
- if (response < 0) {
+ if(response < 0) {
return _libssh2_error(session,
LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response");
@@ -289,7 +305,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
int response;
int rc;
- if (session->pkeyInit_state == libssh2_NB_state_idle) {
+ if(session->pkeyInit_state == libssh2_NB_state_idle) {
session->pkeyInit_data = NULL;
session->pkeyInit_pkey = NULL;
session->pkeyInit_channel = NULL;
@@ -300,7 +316,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_state = libssh2_NB_state_allocated;
}
- if (session->pkeyInit_state == libssh2_NB_state_allocated) {
+ if(session->pkeyInit_state == libssh2_NB_state_allocated) {
session->pkeyInit_channel =
_libssh2_channel_open(session, "session",
@@ -308,8 +324,8 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
0);
- if (!session->pkeyInit_channel) {
- if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)
+ if(!session->pkeyInit_channel) {
+ if(libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)
/* The error state is already set, so leave it */
return NULL;
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
@@ -320,17 +336,18 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_state = libssh2_NB_state_sent;
}
- if (session->pkeyInit_state == libssh2_NB_state_sent) {
+ if(session->pkeyInit_state == libssh2_NB_state_sent) {
rc = _libssh2_channel_process_startup(session->pkeyInit_channel,
"subsystem",
sizeof("subsystem") - 1,
"publickey",
sizeof("publickey") - 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickey subsystem");
return NULL;
- } else if (rc) {
+ }
+ else if(rc) {
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Unable to request publickey subsystem");
goto err_exit;
@@ -339,11 +356,11 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_state = libssh2_NB_state_sent1;
}
- if (session->pkeyInit_state == libssh2_NB_state_sent1) {
+ if(session->pkeyInit_state == libssh2_NB_state_sent1) {
unsigned char *s;
rc = _libssh2_channel_extended_data(session->pkeyInit_channel,
- LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickey subsystem");
return NULL;
@@ -351,7 +368,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_pkey =
LIBSSH2_CALLOC(session, sizeof(LIBSSH2_PUBLICKEY));
- if (!session->pkeyInit_pkey) {
+ if(!session->pkeyInit_pkey) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a new publickey structure");
goto err_exit;
@@ -377,15 +394,16 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_state = libssh2_NB_state_sent2;
}
- if (session->pkeyInit_state == libssh2_NB_state_sent2) {
+ if(session->pkeyInit_state == libssh2_NB_state_sent2) {
rc = _libssh2_channel_write(session->pkeyInit_channel, 0,
session->pkeyInit_buffer,
19 - session->pkeyInit_buffer_sent);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending publickey version packet");
return NULL;
- } else if (rc < 0) {
+ }
+ else if(rc < 0) {
_libssh2_error(session, rc,
"Unable to send publickey version packet");
goto err_exit;
@@ -400,18 +418,19 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
session->pkeyInit_state = libssh2_NB_state_sent3;
}
- if (session->pkeyInit_state == libssh2_NB_state_sent3) {
- while (1) {
+ if(session->pkeyInit_state == libssh2_NB_state_sent3) {
+ while(1) {
unsigned char *s;
rc = publickey_packet_receive(session->pkeyInit_pkey,
&session->pkeyInit_data,
&session->pkeyInit_data_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from "
"publickey subsystem");
return NULL;
- } else if (rc) {
+ }
+ else if(rc) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
@@ -419,31 +438,62 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
}
s = session->pkeyInit_data;
- if ((response =
+ if((response =
publickey_response_id(&s, session->pkeyInit_data_len)) < 0) {
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Invalid publickey subsystem response code");
goto err_exit;
}
- switch (response) {
+ if(session->pkeyInit_data_len < 4) {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "Public key init data too small");
+ goto err_exit;
+ }
+
+ switch(response) {
case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
/* Error */
{
unsigned long status, descr_len, lang_len;
- status = _libssh2_ntohu32(s);
- s += 4;
- descr_len = _libssh2_ntohu32(s);
- s += 4;
- /* description starts here */
- s += descr_len;
- lang_len = _libssh2_ntohu32(s);
- s += 4;
- /* lang starts here */
- s += lang_len;
-
- if (s >
+ if(session->pkeyInit_data_len >= 8) {
+ status = _libssh2_ntohu32(s);
+ s += 4;
+ descr_len = _libssh2_ntohu32(s);
+ s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "Public key init data too small");
+ goto err_exit;
+ }
+
+ if(s + descr_len + 4 <=
+ session->pkeyInit_data + session->pkeyInit_data_len) {
+ /* description starts here */
+ s += descr_len;
+ lang_len = _libssh2_ntohu32(s);
+ s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "Public key init data too small");
+ goto err_exit;
+ }
+
+ if(s + lang_len <=
+ session->pkeyInit_data + session->pkeyInit_data_len) {
+ /* lang starts here */
+ s += lang_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "Public key init data too small");
+ goto err_exit;
+ }
+
+ if(s >
session->pkeyInit_data + session->pkeyInit_data_len) {
_libssh2_error(session,
LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
@@ -459,10 +509,11 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
case LIBSSH2_PUBLICKEY_RESPONSE_VERSION:
/* What we want */
session->pkeyInit_pkey->version = _libssh2_ntohu32(s);
- if (session->pkeyInit_pkey->version >
+ if(session->pkeyInit_pkey->version >
LIBSSH2_PUBLICKEY_VERSION) {
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY,
- "Truncate remote publickey version from %lu",
+ "Truncate remote publickey version "
+ "from %lu",
session->pkeyInit_pkey->version);
session->pkeyInit_pkey->version =
LIBSSH2_PUBLICKEY_VERSION;
@@ -489,19 +540,19 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session)
/* Never reached except by direct goto */
err_exit:
session->pkeyInit_state = libssh2_NB_state_sent4;
- if (session->pkeyInit_channel) {
+ if(session->pkeyInit_channel) {
rc = _libssh2_channel_close(session->pkeyInit_channel);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block closing channel");
return NULL;
}
}
- if (session->pkeyInit_pkey) {
+ if(session->pkeyInit_pkey) {
LIBSSH2_FREE(session, session->pkeyInit_pkey);
session->pkeyInit_pkey = NULL;
}
- if (session->pkeyInit_data) {
+ if(session->pkeyInit_data) {
LIBSSH2_FREE(session, session->pkeyInit_data);
session->pkeyInit_data = NULL;
}
@@ -553,16 +604,16 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
channel = pkey->channel;
session = channel->session;
- if (pkey->add_state == libssh2_NB_state_idle) {
+ if(pkey->add_state == libssh2_NB_state_idle) {
pkey->add_packet = NULL;
_libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, "Adding %s publickey",
name);
- if (pkey->version == 1) {
+ if(pkey->version == 1) {
for(i = 0; i < num_attrs; i++) {
/* Search for a comment attribute */
- if (attrs[i].name_len == (sizeof("comment") - 1) &&
+ if(attrs[i].name_len == (sizeof("comment") - 1) &&
strncmp(attrs[i].name, "comment",
sizeof("comment") - 1) == 0) {
comment = (unsigned char *) attrs[i].value;
@@ -571,7 +622,8 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
}
}
packet_len += 4 + comment_len;
- } else {
+ }
+ else {
packet_len += 5; /* overwrite(1) + attribute_count(4) */
for(i = 0; i < num_attrs; i++) {
packet_len += 9 + attrs[i].name_len + attrs[i].value_len;
@@ -580,7 +632,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
}
pkey->add_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!pkey->add_packet) {
+ if(!pkey->add_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey \"add\" packet");
@@ -593,10 +645,10 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
pkey->add_s += 4;
memcpy(pkey->add_s, "add", sizeof("add") - 1);
pkey->add_s += sizeof("add") - 1;
- if (pkey->version == 1) {
+ if(pkey->version == 1) {
_libssh2_htonu32(pkey->add_s, comment_len);
pkey->add_s += 4;
- if (comment) {
+ if(comment) {
memcpy(pkey->add_s, comment, comment_len);
pkey->add_s += comment_len;
}
@@ -609,7 +661,8 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
pkey->add_s += 4;
memcpy(pkey->add_s, blob, blob_len);
pkey->add_s += blob_len;
- } else {
+ }
+ else {
/* Version == 2 */
_libssh2_htonu32(pkey->add_s, name_len);
@@ -644,12 +697,13 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
pkey->add_state = libssh2_NB_state_created;
}
- if (pkey->add_state == libssh2_NB_state_created) {
+ if(pkey->add_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, pkey->add_packet,
(pkey->add_s - pkey->add_packet));
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if ((pkey->add_s - pkey->add_packet) != rc) {
+ }
+ else if((pkey->add_s - pkey->add_packet) != rc) {
LIBSSH2_FREE(session, pkey->add_packet);
pkey->add_packet = NULL;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
@@ -662,7 +716,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name,
}
rc = publickey_response_success(pkey);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
@@ -693,11 +747,11 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
channel = pkey->channel;
session = channel->session;
- if (pkey->remove_state == libssh2_NB_state_idle) {
+ if(pkey->remove_state == libssh2_NB_state_idle) {
pkey->remove_packet = NULL;
pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!pkey->remove_packet) {
+ if(!pkey->remove_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey \"remove\" packet");
@@ -727,12 +781,13 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
pkey->remove_state = libssh2_NB_state_created;
}
- if (pkey->remove_state == libssh2_NB_state_created) {
+ if(pkey->remove_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, pkey->remove_packet,
(pkey->remove_s - pkey->remove_packet));
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if ((pkey->remove_s - pkey->remove_packet) != rc) {
+ }
+ else if((pkey->remove_s - pkey->remove_packet) != rc) {
LIBSSH2_FREE(session, pkey->remove_packet);
pkey->remove_packet = NULL;
pkey->remove_state = libssh2_NB_state_idle;
@@ -746,7 +801,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
}
rc = publickey_response_success(pkey);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
@@ -776,7 +831,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
channel = pkey->channel;
session = channel->session;
- if (pkey->listFetch_state == libssh2_NB_state_idle) {
+ if(pkey->listFetch_state == libssh2_NB_state_idle) {
pkey->listFetch_data = NULL;
pkey->listFetch_s = pkey->listFetch_buffer;
@@ -793,14 +848,15 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
pkey->listFetch_state = libssh2_NB_state_created;
}
- if (pkey->listFetch_state == libssh2_NB_state_created) {
+ if(pkey->listFetch_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0,
pkey->listFetch_buffer,
(pkey->listFetch_s -
pkey->listFetch_buffer));
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
+ }
+ else if((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
pkey->listFetch_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send publickey list packet");
@@ -809,12 +865,13 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
pkey->listFetch_state = libssh2_NB_state_sent;
}
- while (1) {
+ while(1) {
rc = publickey_packet_receive(pkey, &pkey->listFetch_data,
&pkey->listFetch_data_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (rc) {
+ }
+ else if(rc) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for response from "
"publickey subsystem");
@@ -822,7 +879,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
}
pkey->listFetch_s = pkey->listFetch_data;
- if ((response =
+ if((response =
publickey_response_id(&pkey->listFetch_s,
pkey->listFetch_data_len)) < 0) {
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
@@ -830,31 +887,57 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
goto err_exit;
}
- switch (response) {
+ switch(response) {
case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
/* Error, or processing complete */
{
unsigned long status, descr_len, lang_len;
- status = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- descr_len = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- /* description starts at pkey->listFetch_s */
- pkey->listFetch_s += descr_len;
- lang_len = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- /* lang starts at pkey->listFetch_s */
- pkey->listFetch_s += lang_len;
-
- if (pkey->listFetch_s >
+ if(pkey->listFetch_s + 8 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ status = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ descr_len = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + descr_len + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ /* description starts at pkey->listFetch_s */
+ pkey->listFetch_s += descr_len;
+ lang_len = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + lang_len <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ /* lang starts at pkey->listFetch_s */
+ pkey->listFetch_s += lang_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s >
pkey->listFetch_data + pkey->listFetch_data_len) {
_libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
"Malformed publickey subsystem packet");
goto err_exit;
}
- if (status == LIBSSH2_PUBLICKEY_SUCCESS) {
+ if(status == LIBSSH2_PUBLICKEY_SUCCESS) {
LIBSSH2_FREE(session, pkey->listFetch_data);
pkey->listFetch_data = NULL;
*pkey_list = list;
@@ -868,7 +951,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
}
case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY:
/* What we want */
- if (keys >= max_keys) {
+ if(keys >= max_keys) {
libssh2_publickey_list *newlist;
/* Grow the key list if necessary */
max_keys += 8;
@@ -876,7 +959,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
LIBSSH2_REALLOC(session, list,
(max_keys +
1) * sizeof(libssh2_publickey_list));
- if (!newlist) {
+ if(!newlist) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey list");
@@ -884,17 +967,26 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
}
list = newlist;
}
- if (pkey->version == 1) {
+ if(pkey->version == 1) {
unsigned long comment_len;
- comment_len = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- if (comment_len) {
+ if(pkey->listFetch_s + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ comment_len = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(comment_len) {
list[keys].num_attrs = 1;
list[keys].attrs =
LIBSSH2_ALLOC(session,
sizeof(libssh2_publickey_attribute));
- if (!list[keys].attrs) {
+ if(!list[keys].attrs) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey attributes");
@@ -907,57 +999,184 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
list[keys].attrs[0].mandatory = 0;
pkey->listFetch_s += comment_len;
- } else {
+ }
+ else {
list[keys].num_attrs = 0;
list[keys].attrs = NULL;
}
- list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- list[keys].name = pkey->listFetch_s;
- pkey->listFetch_s += list[keys].name_len;
- list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- list[keys].blob = pkey->listFetch_s;
- pkey->listFetch_s += list[keys].blob_len;
- } else {
+
+ if(pkey->listFetch_s + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + list[keys].name_len <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].name = pkey->listFetch_s;
+ pkey->listFetch_s += list[keys].name_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + list[keys].blob_len <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].blob = pkey->listFetch_s;
+ pkey->listFetch_s += list[keys].blob_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+ }
+ else {
/* Version == 2 */
- list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- list[keys].name = pkey->listFetch_s;
- pkey->listFetch_s += list[keys].name_len;
- list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- list[keys].blob = pkey->listFetch_s;
- pkey->listFetch_s += list[keys].blob_len;
- list[keys].num_attrs = _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- if (list[keys].num_attrs) {
+
+ if(pkey->listFetch_s + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + list[keys].name_len <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].name = pkey->listFetch_s;
+ pkey->listFetch_s += list[keys].name_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + list[keys].blob_len <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].blob = pkey->listFetch_s;
+ pkey->listFetch_s += list[keys].blob_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].num_attrs = _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(list[keys].num_attrs) {
list[keys].attrs =
LIBSSH2_ALLOC(session,
list[keys].num_attrs *
sizeof(libssh2_publickey_attribute));
- if (!list[keys].attrs) {
+ if(!list[keys].attrs) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"publickey attributes");
goto err_exit;
}
for(i = 0; i < list[keys].num_attrs; i++) {
- list[keys].attrs[i].name_len =
- _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- list[keys].attrs[i].name = (char *) pkey->listFetch_s;
- pkey->listFetch_s += list[keys].attrs[i].name_len;
- list[keys].attrs[i].value_len =
- _libssh2_ntohu32(pkey->listFetch_s);
- pkey->listFetch_s += 4;
- list[keys].attrs[i].value = (char *) pkey->listFetch_s;
- pkey->listFetch_s += list[keys].attrs[i].value_len;
+ if(pkey->listFetch_s + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].attrs[i].name_len =
+ _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session,
+ LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + list[keys].attrs[i].name_len <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].attrs[i].name =
+ (char *) pkey->listFetch_s;
+ pkey->listFetch_s += list[keys].attrs[i].name_len;
+ }
+ else {
+ _libssh2_error(session,
+ LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s + 4 <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].attrs[i].value_len =
+ _libssh2_ntohu32(pkey->listFetch_s);
+ pkey->listFetch_s += 4;
+ }
+ else {
+ _libssh2_error(session,
+ LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
+
+ if(pkey->listFetch_s +
+ list[keys].attrs[i].value_len <=
+ pkey->listFetch_data + pkey->listFetch_data_len) {
+ list[keys].attrs[i].value =
+ (char *) pkey->listFetch_s;
+ pkey->listFetch_s += list[keys].attrs[i].value_len;
+ }
+ else {
+ _libssh2_error(session,
+ LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "ListFetch data too short");
+ goto err_exit;
+ }
/* actually an ignored value */
list[keys].attrs[i].mandatory = 0;
}
- } else {
+ }
+ else {
list[keys].attrs = NULL;
}
}
@@ -979,11 +1198,11 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
/* Only reached via explicit goto */
err_exit:
- if (pkey->listFetch_data) {
+ if(pkey->listFetch_data) {
LIBSSH2_FREE(session, pkey->listFetch_data);
pkey->listFetch_data = NULL;
}
- if (list) {
+ if(list) {
libssh2_publickey_list_free(pkey, list);
}
pkey->listFetch_state = libssh2_NB_state_idle;
@@ -1005,8 +1224,8 @@ libssh2_publickey_list_free(LIBSSH2_PUBLICKEY * pkey,
session = pkey->channel->session;
- while (p->packet) {
- if (p->attrs) {
+ while(p->packet) {
+ if(p->attrs) {
LIBSSH2_FREE(session, p->attrs);
}
LIBSSH2_FREE(session, p->packet);
@@ -1033,25 +1252,25 @@ libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey)
/*
* Make sure all memory used in the state variables are free
*/
- if (pkey->receive_packet) {
+ if(pkey->receive_packet) {
LIBSSH2_FREE(session, pkey->receive_packet);
pkey->receive_packet = NULL;
}
- if (pkey->add_packet) {
+ if(pkey->add_packet) {
LIBSSH2_FREE(session, pkey->add_packet);
pkey->add_packet = NULL;
}
- if (pkey->remove_packet) {
+ if(pkey->remove_packet) {
LIBSSH2_FREE(session, pkey->remove_packet);
pkey->remove_packet = NULL;
}
- if (pkey->listFetch_data) {
+ if(pkey->listFetch_data) {
LIBSSH2_FREE(session, pkey->listFetch_data);
pkey->listFetch_data = NULL;
}
rc = _libssh2_channel_free(pkey->channel);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
LIBSSH2_FREE(session, pkey);
diff --git a/libs/libssh2/src/scp.c b/libs/libssh2/src/scp.c
index 22778dd38a..a9d2db5354 100644
--- a/libs/libssh2/src/scp.c
+++ b/libs/libssh2/src/scp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010 by Daniel Stenberg
+/* Copyright (c) 2009-2019 by Daniel Stenberg
* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
@@ -141,9 +141,9 @@ shell_quotearg(const char *path, unsigned char *buf,
endp = &buf[bufsize];
src = path;
dst = buf;
- while (*src && dst < endp - 1) {
+ while(*src && dst < endp - 1) {
- switch (*src) {
+ switch(*src) {
/*
* Special handling for apostrophe.
* An apostrophe is always written in quotation marks, e.g.
@@ -151,16 +151,16 @@ shell_quotearg(const char *path, unsigned char *buf,
*/
case '\'':
- switch (state) {
+ switch(state) {
case UQSTRING: /* Unquoted string */
- if (dst+1 >= endp)
+ if(dst + 1 >= endp)
return 0;
*dst++ = '"';
break;
case QSTRING: /* Continue quoted string */
break;
case SQSTRING: /* Close single quoted string */
- if (dst+2 >= endp)
+ if(dst + 2 >= endp)
return 0;
*dst++ = '\'';
*dst++ = '"';
@@ -179,20 +179,20 @@ shell_quotearg(const char *path, unsigned char *buf,
*/
case '!':
- switch (state) {
+ switch(state) {
case UQSTRING:
- if (dst+1 >= endp)
+ if(dst + 1 >= endp)
return 0;
*dst++ = '\\';
break;
case QSTRING:
- if (dst+2 >= endp)
+ if(dst + 2 >= endp)
return 0;
*dst++ = '"'; /* Closing quotation mark */
*dst++ = '\\';
break;
case SQSTRING: /* Close single quoted string */
- if (dst+2 >= endp)
+ if(dst + 2 >= endp)
return 0;
*dst++ = '\'';
*dst++ = '\\';
@@ -208,14 +208,14 @@ shell_quotearg(const char *path, unsigned char *buf,
*/
default:
- switch (state) {
+ switch(state) {
case UQSTRING:
- if (dst+1 >= endp)
+ if(dst + 1 >= endp)
return 0;
*dst++ = '\'';
break;
case QSTRING:
- if (dst+2 >= endp)
+ if(dst + 2 >= endp)
return 0;
*dst++ = '"'; /* Closing quotation mark */
*dst++ = '\'';
@@ -229,21 +229,21 @@ shell_quotearg(const char *path, unsigned char *buf,
break;
}
- if (dst+1 >= endp)
+ if(dst + 1 >= endp)
return 0;
*dst++ = *src++;
}
- switch (state) {
+ switch(state) {
case UQSTRING:
break;
case QSTRING: /* Close quoted string */
- if (dst+1 >= endp)
+ if(dst + 1 >= endp)
return 0;
*dst++ = '"';
break;
case SQSTRING: /* Close single quoted string */
- if (dst+1 >= endp)
+ if(dst + 1 >= endp)
return 0;
*dst++ = '\'';
break;
@@ -251,7 +251,7 @@ shell_quotearg(const char *path, unsigned char *buf,
break;
}
- if (dst+1 >= endp)
+ if(dst + 1 >= endp)
return 0;
*dst = '\0';
@@ -275,7 +275,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
int tmp_err_code;
const char *tmp_err_msg;
- if (session->scpRecv_state == libssh2_NB_state_idle) {
+ if(session->scpRecv_state == libssh2_NB_state_idle) {
session->scpRecv_mode = 0;
session->scpRecv_size = 0;
session->scpRecv_mtime = 0;
@@ -287,7 +287,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_command =
LIBSSH2_ALLOC(session, session->scpRecv_command_len);
- if (!session->scpRecv_command) {
+ if(!session->scpRecv_command) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a command buffer for "
"SCP session");
@@ -303,8 +303,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
&session->scpRecv_command[cmd_len],
session->scpRecv_command_len - cmd_len);
- session->scpRecv_command[cmd_len] = '\0';
- session->scpRecv_command_len = cmd_len + 1;
+ /* the command to exec should _not_ be NUL-terminated */
+ session->scpRecv_command_len = cmd_len;
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"Opening channel for SCP receive");
@@ -312,7 +312,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_state = libssh2_NB_state_created;
}
- if (session->scpRecv_state == libssh2_NB_state_created) {
+ if(session->scpRecv_state == libssh2_NB_state_created) {
/* Allocate a channel */
session->scpRecv_channel =
_libssh2_channel_open(session, "session",
@@ -320,8 +320,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
0);
- if (!session->scpRecv_channel) {
- if (libssh2_session_last_errno(session) !=
+ if(!session->scpRecv_channel) {
+ if(libssh2_session_last_errno(session) !=
LIBSSH2_ERROR_EAGAIN) {
LIBSSH2_FREE(session, session->scpRecv_command);
session->scpRecv_command = NULL;
@@ -337,17 +337,18 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_state = libssh2_NB_state_sent;
}
- if (session->scpRecv_state == libssh2_NB_state_sent) {
+ if(session->scpRecv_state == libssh2_NB_state_sent) {
/* Request SCP for the desired file */
rc = _libssh2_channel_process_startup(session->scpRecv_channel, "exec",
sizeof("exec") - 1,
- (char *) session->scpRecv_command,
+ (char *)session->scpRecv_command,
session->scpRecv_command_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting SCP startup");
return NULL;
- } else if (rc) {
+ }
+ else if(rc) {
LIBSSH2_FREE(session, session->scpRecv_command);
session->scpRecv_command = NULL;
goto scp_recv_error;
@@ -362,14 +363,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_state = libssh2_NB_state_sent1;
}
- if (session->scpRecv_state == libssh2_NB_state_sent1) {
+ if(session->scpRecv_state == libssh2_NB_state_sent1) {
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
session->scpRecv_response, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending initial wakeup");
return NULL;
- } else if (rc != 1) {
+ }
+ else if(rc != 1) {
goto scp_recv_error;
}
@@ -379,23 +381,23 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_state = libssh2_NB_state_sent2;
}
- if ((session->scpRecv_state == libssh2_NB_state_sent2)
+ if((session->scpRecv_state == libssh2_NB_state_sent2)
|| (session->scpRecv_state == libssh2_NB_state_sent3)) {
- while (sb && (session->scpRecv_response_len <
+ while(sb && (session->scpRecv_response_len <
LIBSSH2_SCP_RESPONSE_BUFLEN)) {
unsigned char *s, *p;
- if (session->scpRecv_state == libssh2_NB_state_sent2) {
+ if(session->scpRecv_state == libssh2_NB_state_sent2) {
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response");
return NULL;
}
- else if (rc < 0) {
+ else if(rc < 0) {
/* error, give up */
_libssh2_error(session, rc, "Failed reading SCP response");
goto scp_recv_error;
@@ -405,7 +407,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_response_len++;
- if (session->scpRecv_response[0] != 'T') {
+ if(session->scpRecv_response[0] != 'T') {
size_t err_len;
char *err_msg;
@@ -419,7 +421,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
_libssh2_channel_packet_data_len(session->
scpRecv_channel, 0);
err_msg = LIBSSH2_ALLOC(session, err_len + 1);
- if (!err_msg) {
+ if(!err_msg) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Failed to get memory ");
goto scp_recv_error;
@@ -431,7 +433,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
/* If it failed for any reason, we ignore it anyway. */
/* zero terminate the error */
- err_msg[err_len]=0;
+ err_msg[err_len] = 0;
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"got %02x %s", session->scpRecv_response[0],
@@ -444,7 +446,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
goto scp_recv_error;
}
- if ((session->scpRecv_response_len > 1) &&
+ if((session->scpRecv_response_len > 1) &&
((session->
scpRecv_response[session->scpRecv_response_len - 1] <
'0')
@@ -465,15 +467,16 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
goto scp_recv_error;
}
- if ((session->scpRecv_response_len < 9)
+ if((session->scpRecv_response_len < 9)
|| (session->
scpRecv_response[session->scpRecv_response_len - 1] !=
'\n')) {
- if (session->scpRecv_response_len ==
+ if(session->scpRecv_response_len ==
LIBSSH2_SCP_RESPONSE_BUFLEN) {
/* You had your chance */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Unterminated response from SCP server");
+ "Unterminated response from "
+ "SCP server");
goto scp_recv_error;
}
/* Way too short to be an SCP response, or not done yet,
@@ -483,7 +486,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
/* We're guaranteed not to go under response_len == 0 by the
logic above */
- while ((session->
+ while((session->
scpRecv_response[session->scpRecv_response_len - 1] ==
'\r')
|| (session->
@@ -493,18 +496,18 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_response[session->scpRecv_response_len] =
'\0';
- if (session->scpRecv_response_len < 8) {
+ if(session->scpRecv_response_len < 8) {
/* EOL came too soon */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, "
- "too short" );
+ "too short");
goto scp_recv_error;
}
s = session->scpRecv_response + 1;
p = (unsigned char *) strchr((char *) s, ' ');
- if (!p || ((p - s) <= 0)) {
+ if(!p || ((p - s) <= 0)) {
/* No spaces or space in the wrong spot */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, "
@@ -517,20 +520,22 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_mtime = strtol((char *) s, NULL, 10);
s = (unsigned char *) strchr((char *) p, ' ');
- if (!s || ((s - p) <= 0)) {
+ if(!s || ((s - p) <= 0)) {
/* No spaces or space in the wrong spot */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Invalid response from SCP server, malformed mtime.usec");
+ "Invalid response from SCP server, "
+ "malformed mtime.usec");
goto scp_recv_error;
}
/* Ignore mtime.usec */
s++;
p = (unsigned char *) strchr((char *) s, ' ');
- if (!p || ((p - s) <= 0)) {
+ if(!p || ((p - s) <= 0)) {
/* No spaces or space in the wrong spot */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Invalid response from SCP server, too short or malformed");
+ "Invalid response from SCP server, "
+ "too short or malformed");
goto scp_recv_error;
}
@@ -544,14 +549,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_state = libssh2_NB_state_sent3;
}
- if (session->scpRecv_state == libssh2_NB_state_sent3) {
+ if(session->scpRecv_state == libssh2_NB_state_sent3) {
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
session->scpRecv_response, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting to send SCP ACK");
return NULL;
- } else if (rc != 1) {
+ }
+ else if(rc != 1) {
goto scp_recv_error;
}
@@ -568,28 +574,28 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_state = libssh2_NB_state_sent4;
}
- if (session->scpRecv_state == libssh2_NB_state_sent4) {
+ if(session->scpRecv_state == libssh2_NB_state_sent4) {
session->scpRecv_response_len = 0;
session->scpRecv_state = libssh2_NB_state_sent5;
}
- if ((session->scpRecv_state == libssh2_NB_state_sent5)
+ if((session->scpRecv_state == libssh2_NB_state_sent5)
|| (session->scpRecv_state == libssh2_NB_state_sent6)) {
- while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) {
+ while(session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) {
char *s, *p, *e = NULL;
- if (session->scpRecv_state == libssh2_NB_state_sent5) {
+ if(session->scpRecv_state == libssh2_NB_state_sent5) {
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
(char *) session->
scpRecv_response +
session->scpRecv_response_len, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response");
return NULL;
}
- else if (rc < 0) {
+ else if(rc < 0) {
/* error, bail out*/
_libssh2_error(session, rc, "Failed reading SCP response");
goto scp_recv_error;
@@ -599,13 +605,13 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_response_len++;
- if (session->scpRecv_response[0] != 'C') {
+ if(session->scpRecv_response[0] != 'C') {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server");
goto scp_recv_error;
}
- if ((session->scpRecv_response_len > 1) &&
+ if((session->scpRecv_response_len > 1) &&
(session->
scpRecv_response[session->scpRecv_response_len - 1] !=
'\r')
@@ -621,15 +627,16 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
goto scp_recv_error;
}
- if ((session->scpRecv_response_len < 7)
+ if((session->scpRecv_response_len < 7)
|| (session->
scpRecv_response[session->scpRecv_response_len - 1] !=
'\n')) {
- if (session->scpRecv_response_len ==
+ if(session->scpRecv_response_len ==
LIBSSH2_SCP_RESPONSE_BUFLEN) {
/* You had your chance */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Unterminated response from SCP server");
+ "Unterminated response "
+ "from SCP server");
goto scp_recv_error;
}
/* Way too short to be an SCP response, or not done yet,
@@ -639,7 +646,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
/* We're guaranteed not to go under response_len == 0 by the
logic above */
- while ((session->
+ while((session->
scpRecv_response[session->scpRecv_response_len - 1] ==
'\r')
|| (session->
@@ -650,20 +657,22 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_response[session->scpRecv_response_len] =
'\0';
- if (session->scpRecv_response_len < 6) {
+ if(session->scpRecv_response_len < 6) {
/* EOL came too soon */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Invalid response from SCP server, too short");
+ "Invalid response from SCP server, "
+ "too short");
goto scp_recv_error;
}
s = (char *) session->scpRecv_response + 1;
p = strchr(s, ' ');
- if (!p || ((p - s) <= 0)) {
+ if(!p || ((p - s) <= 0)) {
/* No spaces or space in the wrong spot */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Invalid response from SCP server, malformed mode");
+ "Invalid response from SCP server, "
+ "malformed mode");
goto scp_recv_error;
}
@@ -671,26 +680,29 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
/* Make sure we don't get fooled by leftover values */
session->scpRecv_mode = strtol(s, &e, 8);
- if (e && *e) {
+ if(e && *e) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Invalid response from SCP server, invalid mode");
+ "Invalid response from SCP server, "
+ "invalid mode");
goto scp_recv_error;
}
s = strchr(p, ' ');
- if (!s || ((s - p) <= 0)) {
+ if(!s || ((s - p) <= 0)) {
/* No spaces or space in the wrong spot */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Invalid response from SCP server, too short or malformed");
+ "Invalid response from SCP server, "
+ "too short or malformed");
goto scp_recv_error;
}
*s = '\0';
/* Make sure we don't get fooled by leftover values */
session->scpRecv_size = scpsize_strtol(p, &e, 10);
- if (e && *e) {
+ if(e && *e) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
- "Invalid response from SCP server, invalid size");
+ "Invalid response from SCP server, "
+ "invalid size");
goto scp_recv_error;
}
@@ -700,14 +712,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_state = libssh2_NB_state_sent6;
}
- if (session->scpRecv_state == libssh2_NB_state_sent6) {
+ if(session->scpRecv_state == libssh2_NB_state_sent6) {
rc = _libssh2_channel_write(session->scpRecv_channel, 0,
session->scpRecv_response, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending SCP ACK");
return NULL;
- } else if (rc != 1) {
+ }
+ else if(rc != 1) {
goto scp_recv_error;
}
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
@@ -723,7 +736,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
session->scpRecv_state = libssh2_NB_state_sent7;
}
- if (sb) {
+ if(sb) {
memset(sb, 0, sizeof(libssh2_struct_stat));
sb->st_mtime = session->scpRecv_mtime;
@@ -747,7 +760,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
scp_recv_error:
tmp_err_code = session->err_code;
tmp_err_msg = session->err_msg;
- while (libssh2_channel_free(session->scpRecv_channel) ==
+ while(libssh2_channel_free(session->scpRecv_channel) ==
LIBSSH2_ERROR_EAGAIN);
session->err_code = tmp_err_code;
session->err_msg = tmp_err_msg;
@@ -761,9 +774,9 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb)
*
* DEPRECATED
*
- * Open a channel and request a remote file via SCP. This receives files larger
- * than 2 GB, but is unable to report the proper size on platforms where the
- * st_size member of struct stat is limited to 2 GB (e.g. windows).
+ * Open a channel and request a remote file via SCP. This receives files
+ * larger than 2 GB, but is unable to report the proper size on platforms
+ * where the st_size member of struct stat is limited to 2 GB (e.g. windows).
*
*/
LIBSSH2_API LIBSSH2_CHANNEL *
@@ -771,15 +784,17 @@ libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb)
{
LIBSSH2_CHANNEL *ptr;
- /* scp_recv uses libssh2_struct_stat, so pass one if the caller gave us a struct to populate... */
+ /* scp_recv uses libssh2_struct_stat, so pass one if the caller gave us a
+ struct to populate... */
libssh2_struct_stat sb_intl;
libssh2_struct_stat *sb_ptr;
+ memset(&sb_intl, 0, sizeof(sb_intl));
sb_ptr = sb ? &sb_intl : NULL;
BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb_ptr));
/* ...and populate the caller's with as much info as fits. */
- if (sb) {
+ if(sb) {
memset(sb, 0, sizeof(struct stat));
sb->st_mtime = sb_intl.st_mtime;
@@ -799,7 +814,8 @@ libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb)
*
*/
LIBSSH2_API LIBSSH2_CHANNEL *
-libssh2_scp_recv2(LIBSSH2_SESSION *session, const char *path, libssh2_struct_stat * sb)
+libssh2_scp_recv2(LIBSSH2_SESSION *session, const char *path,
+ libssh2_struct_stat *sb)
{
LIBSSH2_CHANNEL *ptr;
BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb));
@@ -821,7 +837,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
int tmp_err_code;
const char *tmp_err_msg;
- if (session->scpSend_state == libssh2_NB_state_idle) {
+ if(session->scpSend_state == libssh2_NB_state_idle) {
session->scpSend_command_len =
_libssh2_shell_quotedsize(path) + sizeof("scp -t ") +
((mtime || atime)?1:0);
@@ -829,7 +845,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_command =
LIBSSH2_ALLOC(session, session->scpSend_command_len);
- if (!session->scpSend_command) {
+ if(!session->scpSend_command) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a command buffer for "
"SCP session");
@@ -845,8 +861,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
&session->scpSend_command[cmd_len],
session->scpSend_command_len - cmd_len);
- session->scpSend_command[cmd_len] = '\0';
- session->scpSend_command_len = cmd_len + 1;
+ /* the command to exec should _not_ be NUL-terminated */
+ session->scpSend_command_len = cmd_len;
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"Opening channel for SCP send");
@@ -855,13 +871,13 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_state = libssh2_NB_state_created;
}
- if (session->scpSend_state == libssh2_NB_state_created) {
+ if(session->scpSend_state == libssh2_NB_state_created) {
session->scpSend_channel =
_libssh2_channel_open(session, "session", sizeof("session") - 1,
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
- if (!session->scpSend_channel) {
- if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
+ if(!session->scpSend_channel) {
+ if(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
/* previous call set libssh2_session_last_error(), pass it
through */
LIBSSH2_FREE(session, session->scpSend_command);
@@ -878,18 +894,18 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_state = libssh2_NB_state_sent;
}
- if (session->scpSend_state == libssh2_NB_state_sent) {
+ if(session->scpSend_state == libssh2_NB_state_sent) {
/* Request SCP for the desired file */
rc = _libssh2_channel_process_startup(session->scpSend_channel, "exec",
sizeof("exec") - 1,
- (char *) session->scpSend_command,
+ (char *)session->scpSend_command,
session->scpSend_command_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting SCP startup");
return NULL;
}
- else if (rc) {
+ else if(rc) {
/* previous call set libssh2_session_last_error(), pass it
through */
LIBSSH2_FREE(session, session->scpSend_command);
@@ -904,28 +920,28 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_state = libssh2_NB_state_sent1;
}
- if (session->scpSend_state == libssh2_NB_state_sent1) {
+ if(session->scpSend_state == libssh2_NB_state_sent1) {
/* Wait for ACK */
rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from remote");
return NULL;
}
- else if (rc < 0) {
+ else if(rc < 0) {
_libssh2_error(session, rc, "SCP failure");
goto scp_send_error;
}
else if(!rc)
/* remain in the same state */
goto scp_send_empty_channel;
- else if (session->scpSend_response[0] != 0) {
+ else if(session->scpSend_response[0] != 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
goto scp_send_error;
}
- if (mtime || atime) {
+ if(mtime || atime) {
/* Send mtime and atime to be used for file */
session->scpSend_response_len =
snprintf((char *) session->scpSend_response,
@@ -939,16 +955,17 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
}
/* Send mtime and atime to be used for file */
- if (mtime || atime) {
- if (session->scpSend_state == libssh2_NB_state_sent2) {
+ if(mtime || atime) {
+ if(session->scpSend_state == libssh2_NB_state_sent2) {
rc = _libssh2_channel_write(session->scpSend_channel, 0,
session->scpSend_response,
session->scpSend_response_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending time data for SCP file");
return NULL;
- } else if (rc != (int)session->scpSend_response_len) {
+ }
+ else if(rc != (int)session->scpSend_response_len) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send time data for SCP file");
goto scp_send_error;
@@ -957,23 +974,23 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_state = libssh2_NB_state_sent3;
}
- if (session->scpSend_state == libssh2_NB_state_sent3) {
+ if(session->scpSend_state == libssh2_NB_state_sent3) {
/* Wait for ACK */
rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response");
return NULL;
}
- else if (rc < 0) {
+ else if(rc < 0) {
_libssh2_error(session, rc, "SCP failure");
goto scp_send_error;
}
else if(!rc)
/* remain in the same state */
goto scp_send_empty_channel;
- else if (session->scpSend_response[0] != 0) {
+ else if(session->scpSend_response[0] != 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid SCP ACK response");
goto scp_send_error;
@@ -981,16 +998,17 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_state = libssh2_NB_state_sent4;
}
- } else {
- if (session->scpSend_state == libssh2_NB_state_sent2) {
+ }
+ else {
+ if(session->scpSend_state == libssh2_NB_state_sent2) {
session->scpSend_state = libssh2_NB_state_sent4;
}
}
- if (session->scpSend_state == libssh2_NB_state_sent4) {
+ if(session->scpSend_state == libssh2_NB_state_sent4) {
/* Send mode, size, and basename */
const char *base = strrchr(path, '/');
- if (base)
+ if(base)
base++;
else
base = path;
@@ -1006,15 +1024,16 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_state = libssh2_NB_state_sent5;
}
- if (session->scpSend_state == libssh2_NB_state_sent5) {
+ if(session->scpSend_state == libssh2_NB_state_sent5) {
rc = _libssh2_channel_write(session->scpSend_channel, 0,
session->scpSend_response,
session->scpSend_response_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block send core file data for SCP file");
return NULL;
- } else if (rc != (int)session->scpSend_response_len) {
+ }
+ else if(rc != (int)session->scpSend_response_len) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send core file data for SCP file");
goto scp_send_error;
@@ -1023,31 +1042,31 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
session->scpSend_state = libssh2_NB_state_sent6;
}
- if (session->scpSend_state == libssh2_NB_state_sent6) {
+ if(session->scpSend_state == libssh2_NB_state_sent6) {
/* Wait for ACK */
rc = _libssh2_channel_read(session->scpSend_channel, 0,
(char *) session->scpSend_response, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response");
return NULL;
}
- else if (rc < 0) {
+ else if(rc < 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
goto scp_send_error;
}
- else if (rc == 0)
+ else if(rc == 0)
goto scp_send_empty_channel;
- else if (session->scpSend_response[0] != 0) {
+ else if(session->scpSend_response[0] != 0) {
size_t err_len;
char *err_msg;
err_len =
_libssh2_channel_packet_data_len(session->scpSend_channel, 0);
err_msg = LIBSSH2_ALLOC(session, err_len + 1);
- if (!err_msg) {
+ if(!err_msg) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"failed to get memory");
goto scp_send_error;
@@ -1056,8 +1075,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
/* Read the remote error message */
rc = _libssh2_channel_read(session->scpSend_channel, 0,
err_msg, err_len);
- if (rc > 0) {
- err_msg[err_len]=0;
+ if(rc > 0) {
+ err_msg[err_len] = 0;
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
"got %02x %s", session->scpSend_response[0],
err_msg);
@@ -1085,8 +1104,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
scp_send_error:
tmp_err_code = session->err_code;
tmp_err_msg = session->err_msg;
- while (libssh2_channel_free(session->scpSend_channel) ==
- LIBSSH2_ERROR_EAGAIN);
+ while(libssh2_channel_free(session->scpSend_channel) ==
+ LIBSSH2_ERROR_EAGAIN);
session->err_code = tmp_err_code;
session->err_msg = tmp_err_msg;
session->scpSend_channel = NULL;
diff --git a/libs/libssh2/src/session.c b/libs/libssh2/src/session.c
index b5a83ddd67..e439acde57 100644
--- a/libs/libssh2/src/session.c
+++ b/libs/libssh2/src/session.c
@@ -99,15 +99,16 @@ banner_receive(LIBSSH2_SESSION * session)
int ret;
int banner_len;
- if (session->banner_TxRx_state == libssh2_NB_state_idle) {
+ if(session->banner_TxRx_state == libssh2_NB_state_idle) {
banner_len = 0;
session->banner_TxRx_state = libssh2_NB_state_created;
- } else {
+ }
+ else {
banner_len = session->banner_TxRx_total_send;
}
- while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) &&
+ while((banner_len < (int) sizeof(session->banner_TxRx_banner)) &&
((banner_len == 0)
|| (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
char c = '\0';
@@ -117,7 +118,7 @@ banner_receive(LIBSSH2_SESSION * session)
ret = LIBSSH2_RECV(session, &c, 1,
LIBSSH2_SOCKET_RECV_FLAGS(session));
- if (ret < 0) {
+ if(ret < 0) {
if(session->api_block_mode || (ret != -EAGAIN))
/* ignore EAGAIN when non-blocking */
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
@@ -127,8 +128,8 @@ banner_receive(LIBSSH2_SESSION * session)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Recved %d bytes banner", ret);
- if (ret < 0) {
- if (ret == -EAGAIN) {
+ if(ret < 0) {
+ if(ret == -EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_INBOUND;
session->banner_TxRx_total_send = banner_len;
@@ -141,12 +142,12 @@ banner_receive(LIBSSH2_SESSION * session)
return LIBSSH2_ERROR_SOCKET_RECV;
}
- if (ret == 0) {
+ if(ret == 0) {
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
- if (c == '\0') {
+ if(c == '\0') {
/* NULLs are not allowed in SSH banners */
session->banner_TxRx_state = libssh2_NB_state_idle;
session->banner_TxRx_total_send = 0;
@@ -156,7 +157,7 @@ banner_receive(LIBSSH2_SESSION * session)
session->banner_TxRx_banner[banner_len++] = c;
}
- while (banner_len &&
+ while(banner_len &&
((session->banner_TxRx_banner[banner_len - 1] == '\n') ||
(session->banner_TxRx_banner[banner_len - 1] == '\r'))) {
banner_len--;
@@ -166,11 +167,14 @@ banner_receive(LIBSSH2_SESSION * session)
session->banner_TxRx_state = libssh2_NB_state_idle;
session->banner_TxRx_total_send = 0;
- if (!banner_len)
+ if(!banner_len)
return LIBSSH2_ERROR_BANNER_RECV;
+ if(session->remote.banner)
+ LIBSSH2_FREE(session, session->remote.banner);
+
session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
- if (!session->remote.banner) {
+ if(!session->remote.banner) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Error allocating space for remote banner");
}
@@ -201,18 +205,19 @@ banner_send(LIBSSH2_SESSION * session)
char banner_dup[256];
#endif
- if (session->banner_TxRx_state == libssh2_NB_state_idle) {
- if (session->local.banner) {
+ if(session->banner_TxRx_state == libssh2_NB_state_idle) {
+ if(session->local.banner) {
/* setopt_string will have given us our \r\n characters */
banner_len = strlen((char *) session->local.banner);
banner = (char *) session->local.banner;
}
#ifdef LIBSSH2DEBUG
/* Hack and slash to avoid sending CRLF in debug output */
- if (banner_len < 256) {
+ if(banner_len < 256) {
memcpy(banner_dup, banner, banner_len - 2);
banner_dup[banner_len - 2] = '\0';
- } else {
+ }
+ else {
memcpy(banner_dup, banner, 255);
banner[255] = '\0';
}
@@ -231,7 +236,7 @@ banner_send(LIBSSH2_SESSION * session)
banner + session->banner_TxRx_total_send,
banner_len - session->banner_TxRx_total_send,
LIBSSH2_SOCKET_SEND_FLAGS(session));
- if (ret < 0)
+ if(ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d",
banner_len - session->banner_TxRx_total_send, -ret);
@@ -241,12 +246,12 @@ banner_send(LIBSSH2_SESSION * session)
banner_len - session->banner_TxRx_total_send,
banner, session->banner_TxRx_total_send);
- if (ret != (banner_len - session->banner_TxRx_total_send)) {
- if (ret >= 0 || ret == -EAGAIN) {
+ if(ret != (banner_len - session->banner_TxRx_total_send)) {
+ if(ret >= 0 || ret == -EAGAIN) {
/* the whole packet could not be sent, save the what was */
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
- if (ret > 0)
+ if(ret > 0)
session->banner_TxRx_total_send += ret;
return LIBSSH2_ERROR_EAGAIN;
}
@@ -278,7 +283,7 @@ session_nonblock(libssh2_socket_t sockfd, /* operate on this */
int flags;
flags = fcntl(sockfd, F_GETFL, 0);
- if (nonblock)
+ if(nonblock)
return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
else
return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
@@ -327,7 +332,7 @@ session_nonblock(libssh2_socket_t sockfd, /* operate on this */
#define SETBLOCK 6
#endif
-#if (SETBLOCK == 0)
+#if(SETBLOCK == 0)
#error "no non-blocking method was found/used/set"
#endif
}
@@ -344,9 +349,9 @@ get_socket_nonblocking(int sockfd)
#define GETBLOCK 0
#ifdef HAVE_O_NONBLOCK
/* most recent unix versions */
- int flags;
+ int flags = fcntl(sockfd, F_GETFL, 0);
- if ((flags = fcntl(sockfd, F_GETFL, 0)) == -1) {
+ if(flags == -1) {
/* Assume blocking on error */
return 1;
}
@@ -360,7 +365,7 @@ get_socket_nonblocking(int sockfd)
unsigned int option_value;
socklen_t option_len = sizeof(option_value);
- if (getsockopt
+ if(getsockopt
(sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) {
/* Assume blocking on error */
return 1;
@@ -373,7 +378,7 @@ get_socket_nonblocking(int sockfd)
#if defined(HAVE_SO_NONBLOCK) && (GETBLOCK == 0)
/* BeOS */
long b;
- if (getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) {
+ if(getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) {
/* Assume blocking on error */
return 1;
}
@@ -382,19 +387,19 @@ get_socket_nonblocking(int sockfd)
#define GETBLOCK 5
#endif
-#if defined(SO_STATE) && defined( __VMS ) && (GETBLOCK == 0)
+#if defined(SO_STATE) && defined(__VMS) && (GETBLOCK == 0)
/* VMS TCP/IP Services */
size_t sockstat = 0;
int callstat = 0;
- size_t size = sizeof( int );
+ size_t size = sizeof(int);
callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE,
(char *)&sockstat, &size);
- if ( callstat == -1 ) return(0);
- if ( (sockstat&SS_NBIO) )return(1);
- return(0);
+ if(callstat == -1) return 0;
+ if((sockstat&SS_NBIO) != 0) return 1;
+ return 0;
#undef GETBLOCK
#define GETBLOCK 6
@@ -406,7 +411,7 @@ get_socket_nonblocking(int sockfd)
#define GETBLOCK 7
#endif
-#if (GETBLOCK == 0)
+#if(GETBLOCK == 0)
#error "no non-blocking method was found/used/get"
#endif
}
@@ -419,16 +424,16 @@ libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner)
{
size_t banner_len = banner ? strlen(banner) : 0;
- if (session->local.banner) {
+ if(session->local.banner) {
LIBSSH2_FREE(session, session->local.banner);
session->local.banner = NULL;
}
- if (!banner_len)
+ if(!banner_len)
return 0;
session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
- if (!session->local.banner) {
+ if(!session->local.banner) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for local banner");
}
@@ -474,18 +479,18 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc;
LIBSSH2_SESSION *session;
- if (my_alloc) {
+ if(my_alloc) {
local_alloc = my_alloc;
}
- if (my_free) {
+ if(my_free) {
local_free = my_free;
}
- if (my_realloc) {
+ if(my_realloc) {
local_realloc = my_realloc;
}
session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract);
- if (session) {
+ if(session) {
memset(session, 0, sizeof(LIBSSH2_SESSION));
session->alloc = local_alloc;
session->free = local_free;
@@ -497,7 +502,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
session->api_block_mode = 1; /* blocking API by default */
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"New session resource allocated");
- _libssh2_init_if_needed ();
+ _libssh2_init_if_needed();
}
return session;
}
@@ -508,16 +513,18 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
* Set (or reset) a callback function
* Returns the prior address
*
- * FIXME: this function relies on that we can typecast function pointers
+ * ALERT: this function relies on that we can typecast function pointers
* to void pointers, which isn't allowed in ISO C!
*/
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
LIBSSH2_API void *
libssh2_session_callback_set(LIBSSH2_SESSION * session,
int cbtype, void *callback)
{
void *oldcb;
- switch (cbtype) {
+ switch(cbtype) {
case LIBSSH2_CALLBACK_IGNORE:
oldcb = session->ssh_msg_ignore;
session->ssh_msg_ignore = callback;
@@ -553,10 +560,12 @@ libssh2_session_callback_set(LIBSSH2_SESSION * session,
session->recv = callback;
return oldcb;
}
- _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", cbtype);
+ _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d",
+ cbtype);
return NULL;
}
+#pragma GCC diagnostic pop
/*
* _libssh2_wait_socket()
@@ -579,8 +588,8 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
being stored as error when a blocking function has returned */
session->err_code = LIBSSH2_ERROR_NONE;
- rc = libssh2_keepalive_send (session, &seconds_to_next);
- if (rc < 0)
+ rc = libssh2_keepalive_send(session, &seconds_to_next);
+ if(rc < 0)
return rc;
ms_to_next = seconds_to_next * 1000;
@@ -597,19 +606,19 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
ms_to_next = 1000;
}
- if (session->api_timeout > 0 &&
+ if(session->api_timeout > 0 &&
(seconds_to_next == 0 ||
ms_to_next > session->api_timeout)) {
- time_t now = time (NULL);
+ time_t now = time(NULL);
elapsed_ms = (long)(1000*difftime(now, start_time));
- if (elapsed_ms > session->api_timeout) {
+ if(elapsed_ms > session->api_timeout) {
return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
"API timeout expired");
}
ms_to_next = (session->api_timeout - elapsed_ms);
has_timeout = 1;
}
- else if (ms_to_next > 0) {
+ else if(ms_to_next > 0) {
has_timeout = 1;
}
else
@@ -675,10 +684,10 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
{
int rc;
- if (session->startup_state == libssh2_NB_state_idle) {
+ if(session->startup_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"session_startup for socket %d", sock);
- if (LIBSSH2_INVALID_SOCKET == sock) {
+ if(LIBSSH2_INVALID_SOCKET == sock) {
/* Did we forget something? */
return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET,
"Bad socket provided");
@@ -688,10 +697,10 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
session->socket_prev_blockstate =
!get_socket_nonblocking(session->socket_fd);
- if (session->socket_prev_blockstate) {
+ if(session->socket_prev_blockstate) {
/* If in blocking state change to non-blocking */
rc = session_nonblock(session->socket_fd, 1);
- if (rc) {
+ if(rc) {
return _libssh2_error(session, rc,
"Failed changing socket's "
"blocking state to non-blocking");
@@ -701,9 +710,11 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
session->startup_state = libssh2_NB_state_created;
}
- if (session->startup_state == libssh2_NB_state_created) {
+ if(session->startup_state == libssh2_NB_state_created) {
rc = banner_send(session);
- if (rc) {
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return rc;
+ else if(rc) {
return _libssh2_error(session, rc,
"Failed sending banner");
}
@@ -711,10 +722,12 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
session->banner_TxRx_state = libssh2_NB_state_idle;
}
- if (session->startup_state == libssh2_NB_state_sent) {
+ if(session->startup_state == libssh2_NB_state_sent) {
do {
rc = banner_receive(session);
- if (rc)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return rc;
+ else if(rc)
return _libssh2_error(session, rc,
"Failed getting banner");
} while(strncmp("SSH-", (char *)session->remote.banner, 4));
@@ -722,16 +735,18 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
session->startup_state = libssh2_NB_state_sent1;
}
- if (session->startup_state == libssh2_NB_state_sent1) {
+ if(session->startup_state == libssh2_NB_state_sent1) {
rc = _libssh2_kex_exchange(session, 0, &session->startup_key_state);
- if (rc)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return rc;
+ else if(rc)
return _libssh2_error(session, rc,
"Unable to exchange encryption keys");
session->startup_state = libssh2_NB_state_sent2;
}
- if (session->startup_state == libssh2_NB_state_sent2) {
+ if(session->startup_state == libssh2_NB_state_sent2) {
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Requesting userauth service");
@@ -745,11 +760,13 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
session->startup_state = libssh2_NB_state_sent3;
}
- if (session->startup_state == libssh2_NB_state_sent3) {
+ if(session->startup_state == libssh2_NB_state_sent3) {
rc = _libssh2_transport_send(session, session->startup_service,
sizeof("ssh-userauth") + 5 - 1,
NULL, 0);
- if (rc) {
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return rc;
+ else if(rc) {
return _libssh2_error(session, rc,
"Unable to ask for ssh-userauth service");
}
@@ -757,12 +774,12 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
session->startup_state = libssh2_NB_state_sent4;
}
- if (session->startup_state == libssh2_NB_state_sent4) {
+ if(session->startup_state == libssh2_NB_state_sent4) {
rc = _libssh2_packet_require(session, SSH_MSG_SERVICE_ACCEPT,
&session->startup_data,
&session->startup_data_len, 0, NULL, 0,
&session->startup_req_state);
- if (rc)
+ if(rc)
return rc;
if(session->startup_data_len < 5) {
@@ -773,7 +790,8 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
session->startup_service_length =
_libssh2_ntohu32(session->startup_data + 1);
- if ((session->startup_service_length != (sizeof("ssh-userauth") - 1))
+
+ if((session->startup_service_length != (sizeof("ssh-userauth") - 1))
|| strncmp("ssh-userauth", (char *) session->startup_data + 5,
session->startup_service_length)) {
LIBSSH2_FREE(session, session->startup_data);
@@ -843,203 +861,204 @@ session_free(LIBSSH2_SESSION *session)
LIBSSH2_LISTENER *l;
int packets_left = 0;
- if (session->free_state == libssh2_NB_state_idle) {
- _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource",
+ if(session->free_state == libssh2_NB_state_idle) {
+ _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+ "Freeing session resource",
session->remote.banner);
session->free_state = libssh2_NB_state_created;
}
- if (session->free_state == libssh2_NB_state_created) {
- while ((ch = _libssh2_list_first(&session->channels))) {
+ if(session->free_state == libssh2_NB_state_created) {
+ while((ch = _libssh2_list_first(&session->channels))) {
rc = _libssh2_channel_free(ch);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
}
session->free_state = libssh2_NB_state_sent;
}
- if (session->free_state == libssh2_NB_state_sent) {
- while ((l = _libssh2_list_first(&session->listeners))) {
+ if(session->free_state == libssh2_NB_state_sent) {
+ while((l = _libssh2_list_first(&session->listeners))) {
rc = _libssh2_channel_forward_cancel(l);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
}
session->free_state = libssh2_NB_state_sent1;
}
- if (session->state & LIBSSH2_STATE_NEWKEYS) {
+ if(session->state & LIBSSH2_STATE_NEWKEYS) {
/* hostkey */
- if (session->hostkey && session->hostkey->dtor) {
+ if(session->hostkey && session->hostkey->dtor) {
session->hostkey->dtor(session, &session->server_hostkey_abstract);
}
/* Client to Server */
/* crypt */
- if (session->local.crypt && session->local.crypt->dtor) {
+ if(session->local.crypt && session->local.crypt->dtor) {
session->local.crypt->dtor(session,
&session->local.crypt_abstract);
}
/* comp */
- if (session->local.comp && session->local.comp->dtor) {
+ if(session->local.comp && session->local.comp->dtor) {
session->local.comp->dtor(session, 1,
&session->local.comp_abstract);
}
/* mac */
- if (session->local.mac && session->local.mac->dtor) {
+ if(session->local.mac && session->local.mac->dtor) {
session->local.mac->dtor(session, &session->local.mac_abstract);
}
/* Server to Client */
/* crypt */
- if (session->remote.crypt && session->remote.crypt->dtor) {
+ if(session->remote.crypt && session->remote.crypt->dtor) {
session->remote.crypt->dtor(session,
&session->remote.crypt_abstract);
}
/* comp */
- if (session->remote.comp && session->remote.comp->dtor) {
+ if(session->remote.comp && session->remote.comp->dtor) {
session->remote.comp->dtor(session, 0,
&session->remote.comp_abstract);
}
/* mac */
- if (session->remote.mac && session->remote.mac->dtor) {
+ if(session->remote.mac && session->remote.mac->dtor) {
session->remote.mac->dtor(session, &session->remote.mac_abstract);
}
/* session_id */
- if (session->session_id) {
+ if(session->session_id) {
LIBSSH2_FREE(session, session->session_id);
}
}
/* Free banner(s) */
- if (session->remote.banner) {
+ if(session->remote.banner) {
LIBSSH2_FREE(session, session->remote.banner);
}
- if (session->local.banner) {
+ if(session->local.banner) {
LIBSSH2_FREE(session, session->local.banner);
}
/* Free preference(s) */
- if (session->kex_prefs) {
+ if(session->kex_prefs) {
LIBSSH2_FREE(session, session->kex_prefs);
}
- if (session->hostkey_prefs) {
+ if(session->hostkey_prefs) {
LIBSSH2_FREE(session, session->hostkey_prefs);
}
- if (session->local.kexinit) {
+ if(session->local.kexinit) {
LIBSSH2_FREE(session, session->local.kexinit);
}
- if (session->local.crypt_prefs) {
+ if(session->local.crypt_prefs) {
LIBSSH2_FREE(session, session->local.crypt_prefs);
}
- if (session->local.mac_prefs) {
+ if(session->local.mac_prefs) {
LIBSSH2_FREE(session, session->local.mac_prefs);
}
- if (session->local.comp_prefs) {
+ if(session->local.comp_prefs) {
LIBSSH2_FREE(session, session->local.comp_prefs);
}
- if (session->local.lang_prefs) {
+ if(session->local.lang_prefs) {
LIBSSH2_FREE(session, session->local.lang_prefs);
}
- if (session->remote.kexinit) {
+ if(session->remote.kexinit) {
LIBSSH2_FREE(session, session->remote.kexinit);
}
- if (session->remote.crypt_prefs) {
+ if(session->remote.crypt_prefs) {
LIBSSH2_FREE(session, session->remote.crypt_prefs);
}
- if (session->remote.mac_prefs) {
+ if(session->remote.mac_prefs) {
LIBSSH2_FREE(session, session->remote.mac_prefs);
}
- if (session->remote.comp_prefs) {
+ if(session->remote.comp_prefs) {
LIBSSH2_FREE(session, session->remote.comp_prefs);
}
- if (session->remote.lang_prefs) {
+ if(session->remote.lang_prefs) {
LIBSSH2_FREE(session, session->remote.lang_prefs);
}
/*
* Make sure all memory used in the state variables are free
*/
- if (session->kexinit_data) {
+ if(session->kexinit_data) {
LIBSSH2_FREE(session, session->kexinit_data);
}
- if (session->startup_data) {
+ if(session->startup_data) {
LIBSSH2_FREE(session, session->startup_data);
}
- if (session->userauth_list_data) {
+ if(session->userauth_list_data) {
LIBSSH2_FREE(session, session->userauth_list_data);
}
- if (session->userauth_pswd_data) {
+ if(session->userauth_pswd_data) {
LIBSSH2_FREE(session, session->userauth_pswd_data);
}
- if (session->userauth_pswd_newpw) {
+ if(session->userauth_pswd_newpw) {
LIBSSH2_FREE(session, session->userauth_pswd_newpw);
}
- if (session->userauth_host_packet) {
+ if(session->userauth_host_packet) {
LIBSSH2_FREE(session, session->userauth_host_packet);
}
- if (session->userauth_host_method) {
+ if(session->userauth_host_method) {
LIBSSH2_FREE(session, session->userauth_host_method);
}
- if (session->userauth_host_data) {
+ if(session->userauth_host_data) {
LIBSSH2_FREE(session, session->userauth_host_data);
}
- if (session->userauth_pblc_data) {
+ if(session->userauth_pblc_data) {
LIBSSH2_FREE(session, session->userauth_pblc_data);
}
- if (session->userauth_pblc_packet) {
+ if(session->userauth_pblc_packet) {
LIBSSH2_FREE(session, session->userauth_pblc_packet);
}
- if (session->userauth_pblc_method) {
+ if(session->userauth_pblc_method) {
LIBSSH2_FREE(session, session->userauth_pblc_method);
}
- if (session->userauth_kybd_data) {
+ if(session->userauth_kybd_data) {
LIBSSH2_FREE(session, session->userauth_kybd_data);
}
- if (session->userauth_kybd_packet) {
+ if(session->userauth_kybd_packet) {
LIBSSH2_FREE(session, session->userauth_kybd_packet);
}
- if (session->userauth_kybd_auth_instruction) {
+ if(session->userauth_kybd_auth_instruction) {
LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction);
}
- if (session->open_packet) {
+ if(session->open_packet) {
LIBSSH2_FREE(session, session->open_packet);
}
- if (session->open_data) {
+ if(session->open_data) {
LIBSSH2_FREE(session, session->open_data);
}
- if (session->direct_message) {
+ if(session->direct_message) {
LIBSSH2_FREE(session, session->direct_message);
}
- if (session->fwdLstn_packet) {
+ if(session->fwdLstn_packet) {
LIBSSH2_FREE(session, session->fwdLstn_packet);
}
- if (session->pkeyInit_data) {
+ if(session->pkeyInit_data) {
LIBSSH2_FREE(session, session->pkeyInit_data);
}
- if (session->scpRecv_command) {
+ if(session->scpRecv_command) {
LIBSSH2_FREE(session, session->scpRecv_command);
}
- if (session->scpSend_command) {
+ if(session->scpSend_command) {
LIBSSH2_FREE(session, session->scpSend_command);
}
- if (session->sftpInit_sftp) {
+ if(session->sftpInit_sftp) {
LIBSSH2_FREE(session, session->sftpInit_sftp);
}
/* Free payload buffer */
- if (session->packet.total_num) {
+ if(session->packet.total_num) {
LIBSSH2_FREE(session, session->packet.payload);
}
/* Cleanup all remaining packets */
- while ((pkg = _libssh2_list_first(&session->packets))) {
+ while((pkg = _libssh2_list_first(&session->packets))) {
packets_left++;
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"packet left with id %d", pkg->data[0]);
@@ -1056,18 +1075,19 @@ session_free(LIBSSH2_SESSION *session)
if(session->socket_prev_blockstate) {
/* if the socket was previously blocking, put it back so */
rc = session_nonblock(session->socket_fd, 0);
- if (rc) {
+ if(rc) {
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unable to reset socket's blocking state");
}
}
- if (session->server_hostkey) {
+ if(session->server_hostkey) {
LIBSSH2_FREE(session, session->server_hostkey);
}
/* error string */
- if (session->err_msg && ((session->err_flags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
+ if(session->err_msg &&
+ ((session->err_flags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
LIBSSH2_FREE(session, (char *)session->err_msg);
}
@@ -1104,14 +1124,14 @@ session_disconnect(LIBSSH2_SESSION *session, int reason,
unsigned long descr_len = 0, lang_len = 0;
int rc;
- if (session->disconnect_state == libssh2_NB_state_idle) {
+ if(session->disconnect_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Disconnecting: reason=%d, desc=%s, lang=%s", reason,
description, lang);
- if (description)
+ if(description)
descr_len = strlen(description);
- if (lang)
+ if(lang)
lang_len = strlen(lang);
if(descr_len > 256)
@@ -1135,7 +1155,7 @@ session_disconnect(LIBSSH2_SESSION *session, int reason,
rc = _libssh2_transport_send(session, session->disconnect_data,
session->disconnect_data_len,
(unsigned char *)lang, lang_len);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
session->disconnect_state = libssh2_NB_state_idle;
@@ -1151,7 +1171,7 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
const char *desc, const char *lang)
{
int rc;
-
+ session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
BLOCK_ADJUST(rc, session,
session_disconnect(session, reason, desc, lang));
@@ -1171,7 +1191,7 @@ libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
/* All methods have char *name as their first element */
const LIBSSH2_KEX_METHOD *method = NULL;
- switch (method_type) {
+ switch(method_type) {
case LIBSSH2_METHOD_KEX:
method = session->kex;
break;
@@ -1216,7 +1236,7 @@ libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
return NULL;
}
- if (!method) {
+ if(!method) {
_libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
"No method negotiated");
return NULL;
@@ -1247,32 +1267,33 @@ libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
size_t msglen = 0;
/* No error to report */
- if (!session->err_code) {
- if (errmsg) {
- if (want_buf) {
+ if(!session->err_code) {
+ if(errmsg) {
+ if(want_buf) {
*errmsg = LIBSSH2_ALLOC(session, 1);
- if (*errmsg) {
+ if(*errmsg) {
**errmsg = 0;
}
- } else {
+ }
+ else {
*errmsg = (char *) "";
}
}
- if (errmsg_len) {
+ if(errmsg_len) {
*errmsg_len = 0;
}
return 0;
}
- if (errmsg) {
+ if(errmsg) {
const char *error = session->err_msg ? session->err_msg : "";
msglen = strlen(error);
- if (want_buf) {
+ if(want_buf) {
/* Make a copy so the calling program can own it */
*errmsg = LIBSSH2_ALLOC(session, msglen + 1);
- if (*errmsg) {
+ if(*errmsg) {
memcpy(*errmsg, error, msglen);
(*errmsg)[msglen] = 0;
}
@@ -1281,7 +1302,7 @@ libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
*errmsg = (char *)error;
}
- if (errmsg_len) {
+ if(errmsg_len) {
*errmsg_len = msglen;
}
@@ -1309,7 +1330,7 @@ libssh2_session_last_errno(LIBSSH2_SESSION * session)
LIBSSH2_API int
libssh2_session_set_last_error(LIBSSH2_SESSION* session,
int errcode,
- const char* errmsg)
+ const char *errmsg)
{
return _libssh2_error_flags(session, errcode, errmsg,
LIBSSH2_ERR_FLAG_DUP);
@@ -1417,14 +1438,20 @@ libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended)
session = channel->session;
packet = _libssh2_list_first(&session->packets);
- while (packet) {
- if ( channel->local.id == _libssh2_ntohu32(packet->data + 1)) {
- if ( extended == 1 &&
- (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
- || packet->data[0] == SSH_MSG_CHANNEL_DATA )) {
+ while(packet) {
+ if(packet->data_len < 5) {
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "Packet too small");
+ }
+
+ if(channel->local.id == _libssh2_ntohu32(packet->data + 1)) {
+ if(extended == 1 &&
+ (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
+ || packet->data[0] == SSH_MSG_CHANNEL_DATA)) {
return 1;
- } else if ( extended == 0 &&
- packet->data[0] == SSH_MSG_CHANNEL_DATA) {
+ }
+ else if(extended == 0 &&
+ packet->data[0] == SSH_MSG_CHANNEL_DATA) {
return 1;
}
/* else - no data of any type is ready to be read */
@@ -1475,7 +1502,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
#else
struct pollfd sockets[256];
- if (nfds > 256)
+ if(nfds > 256)
/* systems without alloca use a fixed-size array, this can be fixed if
we really want to, at least if the compiler is a C99 capable one */
return -1;
@@ -1483,7 +1510,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
/* Setup sockets for polling */
for(i = 0; i < nfds; i++) {
fds[i].revents = 0;
- switch (fds[i].type) {
+ switch(fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
sockets[i].fd = fds[i].fd.socket;
sockets[i].events = fds[i].events;
@@ -1494,7 +1521,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
sockets[i].fd = fds[i].fd.channel->session->socket_fd;
sockets[i].events = POLLIN;
sockets[i].revents = 0;
- if (!session)
+ if(!session)
session = fds[i].fd.channel->session;
break;
@@ -1502,12 +1529,12 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
sockets[i].fd = fds[i].fd.listener->session->socket_fd;
sockets[i].events = POLLIN;
sockets[i].revents = 0;
- if (!session)
+ if(!session)
session = fds[i].fd.listener->session;
break;
default:
- if (session)
+ if(session)
_libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
"Invalid descriptor passed to libssh2_poll()");
return -1;
@@ -1523,38 +1550,38 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
FD_ZERO(&wfds);
for(i = 0; i < nfds; i++) {
fds[i].revents = 0;
- switch (fds[i].type) {
+ switch(fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
- if (fds[i].events & LIBSSH2_POLLFD_POLLIN) {
+ if(fds[i].events & LIBSSH2_POLLFD_POLLIN) {
FD_SET(fds[i].fd.socket, &rfds);
- if (fds[i].fd.socket > maxfd)
+ if(fds[i].fd.socket > maxfd)
maxfd = fds[i].fd.socket;
}
- if (fds[i].events & LIBSSH2_POLLFD_POLLOUT) {
+ if(fds[i].events & LIBSSH2_POLLFD_POLLOUT) {
FD_SET(fds[i].fd.socket, &wfds);
- if (fds[i].fd.socket > maxfd)
+ if(fds[i].fd.socket > maxfd)
maxfd = fds[i].fd.socket;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
FD_SET(fds[i].fd.channel->session->socket_fd, &rfds);
- if (fds[i].fd.channel->session->socket_fd > maxfd)
+ if(fds[i].fd.channel->session->socket_fd > maxfd)
maxfd = fds[i].fd.channel->session->socket_fd;
- if (!session)
+ if(!session)
session = fds[i].fd.channel->session;
break;
case LIBSSH2_POLLFD_LISTENER:
FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
- if (fds[i].fd.listener->session->socket_fd > maxfd)
+ if(fds[i].fd.listener->session->socket_fd > maxfd)
maxfd = fds[i].fd.listener->session->socket_fd;
- if (!session)
+ if(!session)
session = fds[i].fd.listener->session;
break;
default:
- if (session)
+ if(session)
_libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
"Invalid descriptor passed to libssh2_poll()");
return -1;
@@ -1577,10 +1604,10 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
active_fds = 0;
for(i = 0; i < nfds; i++) {
- if (fds[i].events != fds[i].revents) {
- switch (fds[i].type) {
+ if(fds[i].events != fds[i].revents) {
+ switch(fds[i].type) {
case LIBSSH2_POLLFD_CHANNEL:
- if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
+ if((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
/* Want to be ready for read */
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
/* Not yet known to be ready for read */
@@ -1589,7 +1616,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
0) ?
LIBSSH2_POLLFD_POLLIN : 0;
}
- if ((fds[i].events & LIBSSH2_POLLFD_POLLEXT) &&
+ if((fds[i].events & LIBSSH2_POLLFD_POLLEXT) &&
/* Want to be ready for extended read */
((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) {
/* Not yet known to be ready for extended read */
@@ -1598,7 +1625,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
1) ?
LIBSSH2_POLLFD_POLLEXT : 0;
}
- if ((fds[i].events & LIBSSH2_POLLFD_POLLOUT) &&
+ if((fds[i].events & LIBSSH2_POLLFD_POLLOUT) &&
/* Want to be ready for write */
((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) {
/* Not yet known to be ready for write */
@@ -1606,11 +1633,11 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
poll_channel_write(fds[i].fd. channel) ?
LIBSSH2_POLLFD_POLLOUT : 0;
}
- if (fds[i].fd.channel->remote.close
+ if(fds[i].fd.channel->remote.close
|| fds[i].fd.channel->local.close) {
fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED;
}
- if (fds[i].fd.channel->session->socket_state ==
+ if(fds[i].fd.channel->session->socket_state ==
LIBSSH2_SOCKET_DISCONNECTED) {
fds[i].revents |=
LIBSSH2_POLLFD_CHANNEL_CLOSED |
@@ -1619,7 +1646,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
break;
case LIBSSH2_POLLFD_LISTENER:
- if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
+ if((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
/* Want a connection */
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
/* No connections known of yet */
@@ -1627,7 +1654,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
poll_listener_queued(fds[i].fd. listener) ?
LIBSSH2_POLLFD_POLLIN : 0;
}
- if (fds[i].fd.listener->session->socket_state ==
+ if(fds[i].fd.listener->session->socket_state ==
LIBSSH2_SOCKET_DISCONNECTED) {
fds[i].revents |=
LIBSSH2_POLLFD_LISTENER_CLOSED |
@@ -1636,12 +1663,12 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
break;
}
}
- if (fds[i].revents) {
+ if(fds[i].revents) {
active_fds++;
}
}
- if (active_fds) {
+ if(active_fds) {
/* Don't block on the sockets if we have channels/listeners which
are ready */
timeout_remaining = 0;
@@ -1666,23 +1693,25 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
timeout_remaining = 0;
#endif /* HAVE_GETTIMEOFDAY */
- if (sysret > 0) {
+ if(sysret > 0) {
for(i = 0; i < nfds; i++) {
- switch (fds[i].type) {
+ switch(fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
fds[i].revents = sockets[i].revents;
- sockets[i].revents = 0; /* In case we loop again, be nice */
- if (fds[i].revents) {
+ sockets[i].revents = 0; /* In case we loop again, be
+ nice */
+ if(fds[i].revents) {
active_fds++;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
- if (sockets[i].events & POLLIN) {
+ if(sockets[i].events & POLLIN) {
/* Spin session until no data available */
- while (_libssh2_transport_read(fds[i].fd.channel->session)
- > 0);
+ while(_libssh2_transport_read(fds[i].fd.
+ channel->session)
+ > 0);
}
- if (sockets[i].revents & POLLHUP) {
+ if(sockets[i].revents & POLLHUP) {
fds[i].revents |=
LIBSSH2_POLLFD_CHANNEL_CLOSED |
LIBSSH2_POLLFD_SESSION_CLOSED;
@@ -1690,12 +1719,13 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
sockets[i].revents = 0;
break;
case LIBSSH2_POLLFD_LISTENER:
- if (sockets[i].events & POLLIN) {
+ if(sockets[i].events & POLLIN) {
/* Spin session until no data available */
- while (_libssh2_transport_read(fds[i].fd.listener->session)
- > 0);
+ while(_libssh2_transport_read(fds[i].fd.
+ listener->session)
+ > 0);
}
- if (sockets[i].revents & POLLHUP) {
+ if(sockets[i].revents & POLLHUP) {
fds[i].revents |=
LIBSSH2_POLLFD_LISTENER_CLOSED |
LIBSSH2_POLLFD_SESSION_CLOSED;
@@ -1713,7 +1743,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
struct timeval tv_begin, tv_end;
_libssh2_gettimeofday((struct timeval *) &tv_begin, NULL);
- sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
+ sysret = select(maxfd + 1, &rfds, &wfds, NULL, &tv);
_libssh2_gettimeofday((struct timeval *) &tv_end, NULL);
timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
@@ -1723,39 +1753,42 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
/* If the platform doesn't support gettimeofday,
* then just make the call non-blocking and walk away
*/
- sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
+ sysret = select(maxfd + 1, &rfds, &wfds, NULL, &tv);
timeout_remaining = 0;
#endif
- if (sysret > 0) {
+ if(sysret > 0) {
for(i = 0; i < nfds; i++) {
- switch (fds[i].type) {
+ switch(fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
- if (FD_ISSET(fds[i].fd.socket, &rfds)) {
+ if(FD_ISSET(fds[i].fd.socket, &rfds)) {
fds[i].revents |= LIBSSH2_POLLFD_POLLIN;
}
- if (FD_ISSET(fds[i].fd.socket, &wfds)) {
+ if(FD_ISSET(fds[i].fd.socket, &wfds)) {
fds[i].revents |= LIBSSH2_POLLFD_POLLOUT;
}
- if (fds[i].revents) {
+ if(fds[i].revents) {
active_fds++;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
- if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
+ if(FD_ISSET(fds[i].fd.channel->session->socket_fd,
+ &rfds)) {
/* Spin session until no data available */
- while (_libssh2_transport_read(fds[i].fd.channel->session)
- > 0);
+ while(_libssh2_transport_read(fds[i].fd.
+ channel->session)
+ > 0);
}
break;
case LIBSSH2_POLLFD_LISTENER:
- if (FD_ISSET
+ if(FD_ISSET
(fds[i].fd.listener->session->socket_fd, &rfds)) {
/* Spin session until no data available */
- while (_libssh2_transport_read(fds[i].fd.listener->session)
- > 0);
+ while(_libssh2_transport_read(fds[i].fd.
+ listener->session)
+ > 0);
}
break;
}
@@ -1763,7 +1796,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
}
#endif /* else no select() or poll() -- timeout (and by extension
* timeout_remaining) will be equal to 0 */
- } while ((timeout_remaining > 0) && !active_fds);
+ } while((timeout_remaining > 0) && !active_fds);
return active_fds;
}
@@ -1789,10 +1822,10 @@ LIBSSH2_API const char *
libssh2_session_banner_get(LIBSSH2_SESSION *session)
{
/* to avoid a coredump when session is NULL */
- if (NULL == session)
+ if(NULL == session)
return NULL;
- if (NULL==session->remote.banner)
+ if(NULL == session->remote.banner)
return NULL;
return (const char *) session->remote.banner;
diff --git a/libs/libssh2/src/session.h b/libs/libssh2/src/session.h
index aff4f2c5c8..7b6c291e27 100644
--- a/libs/libssh2/src/session.h
+++ b/libs/libssh2/src/session.h
@@ -51,9 +51,9 @@
function.
*/
-#define BLOCK_ADJUST(rc,sess,x) \
+#define BLOCK_ADJUST(rc, sess, x) \
do { \
- time_t entry_time = time (NULL); \
+ time_t entry_time = time(NULL); \
do { \
rc = x; \
/* the order of the check below is important to properly deal with \
@@ -70,9 +70,9 @@
* immediately. If the API is blocking and we get a NULL we check the errno
* and *only* if that is EAGAIN we loop and wait for socket action.
*/
-#define BLOCK_ADJUST_ERRNO(ptr,sess,x) \
+#define BLOCK_ADJUST_ERRNO(ptr, sess, x) \
do { \
- time_t entry_time = time (NULL); \
+ time_t entry_time = time(NULL); \
int rc; \
do { \
ptr = x; \
diff --git a/libs/libssh2/src/sftp.c b/libs/libssh2/src/sftp.c
index fd94d39029..ece590e51f 100644
--- a/libs/libssh2/src/sftp.c
+++ b/libs/libssh2/src/sftp.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
- * Copyright (c) 2009-2014 by Daniel Stenberg
+ * Copyright (c) 2009-2019 by Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -91,7 +91,7 @@
/* This is the maximum packet length to accept, as larger than this indicate
some kind of server problem. */
-#define LIBSSH2_SFTP_PACKET_MAXLEN 80000
+#define LIBSSH2_SFTP_PACKET_MAXLEN (256 * 1024)
static int sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
uint32_t request_id, unsigned char **data,
@@ -161,7 +161,8 @@ 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 zombie requests",
+ "Removing request ID %ld from the list of "
+ "zombie requests",
request_id);
_libssh2_list_remove(&zombie->node);
@@ -181,7 +182,7 @@ add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
zombie = LIBSSH2_ALLOC(sftp->channel->session,
sizeof(struct sftp_zombie_requests));
- if (!zombie)
+ if(!zombie)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"malloc fail for zombie request ID");
else {
@@ -204,7 +205,7 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
LIBSSH2_SFTP_PACKET *packet;
uint32_t request_id;
- if (data_len < 5) {
+ if(data_len < 5) {
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
@@ -272,7 +273,7 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
}
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_PACKET));
- if (!packet) {
+ if(!packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate datablock for SFTP packet");
}
@@ -331,9 +332,9 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
(char *)&sftp->partial_size[
sftp->partial_size_len],
4 - sftp->partial_size_len);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
- else if (rc < 0)
+ else if(rc < 0)
return _libssh2_error(session, rc, "channel read");
sftp->partial_size_len += rc;
@@ -345,11 +346,15 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
sftp->partial_len = _libssh2_ntohu32(sftp->partial_size);
/* make sure we don't proceed if the packet size is unreasonably
large */
- if (sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN)
+ if(sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN) {
+ libssh2_channel_flush(channel);
+ sftp->partial_size_len = 0;
return _libssh2_error(session,
LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
"SFTP packet too large");
- if (sftp->partial_len == 0)
+ }
+
+ if(sftp->partial_len == 0)
return _libssh2_error(session,
LIBSSH2_ERROR_ALLOC,
"Unable to allocate empty SFTP packet");
@@ -358,7 +363,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
"Data begin - Packet Length: %lu",
sftp->partial_len);
packet = LIBSSH2_ALLOC(session, sftp->partial_len);
- if (!packet)
+ if(!packet)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate SFTP packet");
sftp->partial_size_len = 0;
@@ -372,7 +377,8 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
if(sftp->partial_len > recv_window) {
/* ask for twice the data amount we need at once */
rc = _libssh2_channel_receive_window_adjust(channel,
- sftp->partial_len*2,
+ sftp->partial_len
+ * 2,
1, NULL);
/* store the state so that we continue with the correct
operation at next invoke */
@@ -386,13 +392,13 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
}
/* Read as much of the packet as we can */
- while (sftp->partial_len > sftp->partial_received) {
+ while(sftp->partial_len > sftp->partial_received) {
rc = _libssh2_channel_read(channel, 0,
(char *)&packet[sftp->partial_received],
sftp->partial_len -
sftp->partial_received);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
/*
* We received EAGAIN, save what we have and return EAGAIN to
* the caller. Set 'partial_packet' so that this function
@@ -401,7 +407,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
sftp->packet_state = libssh2_NB_state_sent1;
return rc;
}
- else if (rc < 0) {
+ else if(rc < 0) {
LIBSSH2_FREE(session, packet);
sftp->partial_packet = NULL;
return _libssh2_error(session, rc,
@@ -416,7 +422,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp)
so we take a copy of the packet type before we call it. */
packet_type = packet[0];
rc = sftp_packet_add(sftp, packet, sftp->partial_len);
- if (rc) {
+ if(rc) {
LIBSSH2_FREE(session, packet);
return rc;
}
@@ -485,7 +491,7 @@ sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
/* Special consideration when getting VERSION packet */
- while (packet) {
+ while(packet) {
if((packet->data[0] == packet_type) &&
((packet_type == SSH_FXP_VERSION) ||
(packet->request_id == request_id))) {
@@ -517,38 +523,38 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
LIBSSH2_SESSION *session = sftp->channel->session;
int rc;
- if (data == NULL || data_len == NULL || required_size == 0) {
+ if(data == NULL || data_len == NULL || required_size == 0) {
return LIBSSH2_ERROR_BAD_USE;
}
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld",
(int) packet_type, request_id);
- if (sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) {
+ 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);
if (*data_len < required_size) {
- return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+ return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
return LIBSSH2_ERROR_NONE;
}
- while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+ while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
rc = sftp_packet_read(sftp);
- if (rc < 0)
+ if(rc < 0)
return rc;
/* data was read, check the queue again */
- if (!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) {
+ 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);
if (*data_len < required_size) {
- return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+ return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
return LIBSSH2_ERROR_NONE;
@@ -571,17 +577,17 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
int i;
int rc;
- if (data == NULL || data_len == NULL || required_size == 0) {
+ if(data == NULL || data_len == NULL || required_size == 0) {
return LIBSSH2_ERROR_BAD_USE;
}
/* If no timeout is active, start a new one */
- if (sftp->requirev_start == 0)
+ if(sftp->requirev_start == 0)
sftp->requirev_start = time(NULL);
- while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+ while(sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
for(i = 0; i < num_valid_responses; i++) {
- if (sftp_packet_ask(sftp, valid_responses[i], request_id,
+ if(sftp_packet_ask(sftp, valid_responses[i], request_id,
data, data_len) == 0) {
/*
* Set to zero before all returns to say
@@ -590,7 +596,7 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
sftp->requirev_start = 0;
if (*data_len < required_size) {
- return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+ return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
return LIBSSH2_ERROR_NONE;
@@ -598,19 +604,21 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
}
rc = sftp_packet_read(sftp);
- if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
+ if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
sftp->requirev_start = 0;
return rc;
- } else if (rc <= 0) {
+ }
+ else if(rc <= 0) {
/* prevent busy-looping */
long left =
- LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - sftp->requirev_start);
+ LIBSSH2_READ_TIMEOUT -
+ (long)(time(NULL) - sftp->requirev_start);
- if (left <= 0) {
+ if(left <= 0) {
sftp->requirev_start = 0;
return LIBSSH2_ERROR_TIMEOUT;
}
- else if (rc == LIBSSH2_ERROR_EAGAIN) {
+ else if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
}
@@ -636,27 +644,27 @@ sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs)
/* TODO: When we add SFTP4+ functionality flag_mask can get additional
bits */
- if (!attrs) {
+ if(!attrs) {
_libssh2_htonu32(s, 0);
return 4;
}
_libssh2_store_u32(&s, attrs->flags & flag_mask);
- if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
+ if(attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
_libssh2_store_u64(&s, attrs->filesize);
}
- if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
+ if(attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
_libssh2_store_u32(&s, attrs->uid);
_libssh2_store_u32(&s, attrs->gid);
}
- if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
+ if(attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
_libssh2_store_u32(&s, attrs->permissions);
}
- if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
+ if(attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
_libssh2_store_u32(&s, attrs->atime);
_libssh2_store_u32(&s, attrs->mtime);
}
@@ -667,68 +675,57 @@ sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs)
/* sftp_bin2attr
*/
static int
-sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs, const unsigned char *p, size_t data_len)
+sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES *attrs, const unsigned char *p,
+ size_t data_len)
{
- const unsigned char *s = p;
+ struct string_buf buf;
+ uint32_t flags = 0;
+ buf.data = (unsigned char *)p;
+ buf.dataptr = buf.data;
+ buf.len = data_len;
- if (data_len >= 4) {
- memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- attrs->flags = _libssh2_ntohu32(s);
- s += 4;
- data_len -= 4;
- }
- else {
- return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+ if(_libssh2_get_u32(&buf, &flags) != 0) {
+ return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
+ attrs->flags = flags;
- if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
- if (data_len >= 8) {
- attrs->filesize = _libssh2_ntohu64(s);
- s += 8;
- data_len -= 8;
- }
- else {
- return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+ if(attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
+ if(_libssh2_get_u64(&buf, &(attrs->filesize)) != 0) {
+ return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
}
- if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
- if (data_len >= 8) {
- attrs->uid = _libssh2_ntohu32(s);
- s += 4;
- attrs->gid = _libssh2_ntohu32(s);
- s += 4;
- data_len -= 8;
- }
- else {
- return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+ if(attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
+ uint32_t uid = 0;
+ uint32_t gid = 0;
+ if(_libssh2_get_u32(&buf, &uid) != 0 ||
+ _libssh2_get_u32(&buf, &gid) != 0) {
+ return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
+ attrs->uid = uid;
+ attrs->gid = gid;
}
- if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
- if (data_len >= 4) {
- attrs->permissions = _libssh2_ntohu32(s);
- s += 4;
- data_len -= 4;
- }
- else {
- return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+ if(attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
+ uint32_t permissions;
+ if(_libssh2_get_u32(&buf, &permissions) != 0) {
+ return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
+ attrs->permissions = permissions;
}
- if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
- if (data_len >= 8) {
- attrs->atime = _libssh2_ntohu32(s);
- s += 4;
- attrs->mtime = _libssh2_ntohu32(s);
- s += 4;
- }
- else {
- return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
+ if(attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
+ uint32_t atime;
+ uint32_t mtime;
+ if(_libssh2_get_u32(&buf, &atime) != 0 ||
+ _libssh2_get_u32(&buf, &mtime) != 0) {
+ return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
+ attrs->atime = atime;
+ attrs->mtime = mtime;
}
- return (s - p);
+ return (buf.dataptr - buf.data);
}
/* ************
@@ -748,12 +745,12 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
(void) channel;
/* Free the partial packet storage for sftp_packet_read */
- if (sftp->partial_packet) {
+ if(sftp->partial_packet) {
LIBSSH2_FREE(session, sftp->partial_packet);
}
/* Free the packet storage for _libssh2_sftp_packet_readdir */
- if (sftp->readdir_packet) {
+ if(sftp->readdir_packet) {
LIBSSH2_FREE(session, sftp->readdir_packet);
}
@@ -767,12 +764,14 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
*/
static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
{
- unsigned char *data, *s;
+ unsigned char *data;
size_t data_len;
ssize_t rc;
LIBSSH2_SFTP *sftp_handle;
+ struct string_buf buf;
+ unsigned char *endp;
- if (session->sftpInit_state == libssh2_NB_state_idle) {
+ if(session->sftpInit_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Initializing SFTP subsystem");
@@ -795,13 +794,13 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
sftp_handle = session->sftpInit_sftp;
- if (session->sftpInit_state == libssh2_NB_state_created) {
+ if(session->sftpInit_state == libssh2_NB_state_created) {
session->sftpInit_channel =
_libssh2_channel_open(session, "session", sizeof("session") - 1,
LIBSSH2_CHANNEL_WINDOW_DEFAULT,
LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
- if (!session->sftpInit_channel) {
- if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
+ if(!session->sftpInit_channel) {
+ if(libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting up channel");
}
@@ -816,16 +815,18 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
session->sftpInit_state = libssh2_NB_state_sent;
}
- if (session->sftpInit_state == libssh2_NB_state_sent) {
+ if(session->sftpInit_state == libssh2_NB_state_sent) {
int ret = _libssh2_channel_process_startup(session->sftpInit_channel,
"subsystem",
- sizeof("subsystem") - 1, "sftp",
+ sizeof("subsystem") - 1,
+ "sftp",
strlen("sftp"));
- if (ret == LIBSSH2_ERROR_EAGAIN) {
+ if(ret == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block to request SFTP subsystem");
return NULL;
- } else if (ret) {
+ }
+ else if(ret) {
_libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
"Unable to request SFTP subsystem");
goto sftp_init_error;
@@ -834,10 +835,10 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
session->sftpInit_state = libssh2_NB_state_sent1;
}
- if (session->sftpInit_state == libssh2_NB_state_sent1) {
+ if(session->sftpInit_state == libssh2_NB_state_sent1) {
rc = _libssh2_channel_extended_data(session->sftpInit_channel,
- LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting handle extended data");
return NULL;
@@ -846,7 +847,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
sftp_handle =
session->sftpInit_sftp =
LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP));
- if (!sftp_handle) {
+ if(!sftp_handle) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a new SFTP structure");
goto sftp_init_error;
@@ -860,19 +861,20 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
session->sftpInit_sent = 0; /* nothing's sent yet */
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
- "Sending FXP_INIT packet advertising version %d support",
+ "Sending FXP_INIT packet advertising "
+ "version %d support",
(int) LIBSSH2_SFTP_VERSION);
session->sftpInit_state = libssh2_NB_state_sent2;
}
- if (session->sftpInit_state == libssh2_NB_state_sent2) {
+ if(session->sftpInit_state == libssh2_NB_state_sent2) {
/* sent off what's left of the init buffer to send */
rc = _libssh2_channel_write(session->sftpInit_channel, 0,
session->sftpInit_buffer +
session->sftpInit_sent,
9 - session->sftpInit_sent);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending SSH_FXP_INIT");
return NULL;
@@ -896,29 +898,37 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION,
0, &data, &data_len, 5);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block receiving SSH_FXP_VERSION");
return NULL;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
_libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Invalid SSH_FXP_VERSION response");
goto sftp_init_error;
}
- else if (rc) {
+ else if(rc) {
_libssh2_error(session, rc,
"Timeout waiting for response from SFTP subsystem");
goto sftp_init_error;
}
- s = data + 1;
- sftp_handle->version = _libssh2_ntohu32(s);
- s += 4;
- if (sftp_handle->version > LIBSSH2_SFTP_VERSION) {
+ buf.data = data;
+ buf.dataptr = buf.data + 1;
+ buf.len = data_len;
+ endp = &buf.data[data_len];
+
+ if(_libssh2_get_u32(&buf, &(sftp_handle->version)) != 0) {
+ LIBSSH2_FREE(session, data);
+ rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+ goto sftp_init_error;
+ }
+
+ if(sftp_handle->version > LIBSSH2_SFTP_VERSION) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Truncating remote SFTP version from %lu",
sftp_handle->version);
@@ -927,20 +937,22 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Enabling SFTP version %lu compatibility",
sftp_handle->version);
- while (s < (data + data_len)) {
- size_t extname_len, extdata_len;
-
- extname_len = _libssh2_ntohu32(s);
- s += 4;
- /* the extension name starts here */
- s += extname_len;
-
- extdata_len = _libssh2_ntohu32(s);
- s += 4;
+ while(buf.dataptr < endp) {
+ unsigned char *extname, *extdata;
- /* TODO: Actually process extensions */
- s += extdata_len;
+ if(_libssh2_get_string(&buf, &extname, NULL)) {
+ 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)) {
+ LIBSSH2_FREE(session, data);
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "Data too short when extracting extdata");
+ goto sftp_init_error;
+ }
}
LIBSSH2_FREE(session, data);
@@ -960,10 +972,10 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
return sftp_handle;
sftp_init_error:
- while (_libssh2_channel_free(session->sftpInit_channel) ==
+ while(_libssh2_channel_free(session->sftpInit_channel) ==
LIBSSH2_ERROR_EAGAIN);
session->sftpInit_channel = NULL;
- if (session->sftpInit_sftp) {
+ if(session->sftpInit_sftp) {
LIBSSH2_FREE(session, session->sftpInit_sftp);
session->sftpInit_sftp = NULL;
}
@@ -1006,55 +1018,55 @@ sftp_shutdown(LIBSSH2_SFTP *sftp)
/*
* Make sure all memory used in the state variables are free
*/
- if (sftp->partial_packet) {
+ if(sftp->partial_packet) {
LIBSSH2_FREE(session, sftp->partial_packet);
sftp->partial_packet = NULL;
}
- if (sftp->open_packet) {
+ if(sftp->open_packet) {
LIBSSH2_FREE(session, sftp->open_packet);
sftp->open_packet = NULL;
}
- if (sftp->readdir_packet) {
+ if(sftp->readdir_packet) {
LIBSSH2_FREE(session, sftp->readdir_packet);
sftp->readdir_packet = NULL;
}
- if (sftp->fstat_packet) {
+ if(sftp->fstat_packet) {
LIBSSH2_FREE(session, sftp->fstat_packet);
sftp->fstat_packet = NULL;
}
- if (sftp->unlink_packet) {
+ if(sftp->unlink_packet) {
LIBSSH2_FREE(session, sftp->unlink_packet);
sftp->unlink_packet = NULL;
}
- if (sftp->rename_packet) {
+ if(sftp->rename_packet) {
LIBSSH2_FREE(session, sftp->rename_packet);
sftp->rename_packet = NULL;
}
- if (sftp->fstatvfs_packet) {
+ if(sftp->fstatvfs_packet) {
LIBSSH2_FREE(session, sftp->fstatvfs_packet);
sftp->fstatvfs_packet = NULL;
}
- if (sftp->statvfs_packet) {
+ if(sftp->statvfs_packet) {
LIBSSH2_FREE(session, sftp->statvfs_packet);
sftp->statvfs_packet = NULL;
}
- if (sftp->mkdir_packet) {
+ if(sftp->mkdir_packet) {
LIBSSH2_FREE(session, sftp->mkdir_packet);
sftp->mkdir_packet = NULL;
}
- if (sftp->rmdir_packet) {
+ if(sftp->rmdir_packet) {
LIBSSH2_FREE(session, sftp->rmdir_packet);
sftp->rmdir_packet = NULL;
}
- if (sftp->stat_packet) {
+ if(sftp->stat_packet) {
LIBSSH2_FREE(session, sftp->stat_packet);
sftp->stat_packet = NULL;
}
- if (sftp->symlink_packet) {
+ if(sftp->symlink_packet) {
LIBSSH2_FREE(session, sftp->symlink_packet);
sftp->symlink_packet = NULL;
}
- if (sftp->fsync_packet) {
+ if(sftp->fsync_packet) {
LIBSSH2_FREE(session, sftp->fsync_packet);
sftp->fsync_packet = NULL;
}
@@ -1103,16 +1115,17 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
ssize_t rc;
int open_file = (open_type == LIBSSH2_SFTP_OPENFILE)?1:0;
- if (sftp->open_state == libssh2_NB_state_idle) {
+ if(sftp->open_state == libssh2_NB_state_idle) {
/* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) +
flags(4) */
sftp->open_packet_len = filename_len + 13 +
- (open_file? (4 + sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0);
+ (open_file? (4 +
+ sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0);
/* surprise! this starts out with nothing sent */
sftp->open_packet_sent = 0;
s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len);
- if (!sftp->open_packet) {
+ if(!sftp->open_packet) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_OPEN or "
"FXP_OPENDIR packet");
@@ -1129,7 +1142,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
_libssh2_store_u32(&s, sftp->open_request_id);
_libssh2_store_str(&s, filename, filename_len);
- if (open_file) {
+ if(open_file) {
_libssh2_store_u32(&s, flags);
s += sftp_attr2bin(s, &attrs);
}
@@ -1140,14 +1153,15 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
sftp->open_state = libssh2_NB_state_created;
}
- if (sftp->open_state == libssh2_NB_state_created) {
+ if(sftp->open_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, sftp->open_packet+
sftp->open_packet_sent,
sftp->open_packet_len -
sftp->open_packet_sent);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
- "Would block sending FXP_OPEN or FXP_OPENDIR command");
+ "Would block sending FXP_OPEN or "
+ "FXP_OPENDIR command");
return NULL;
}
else if(rc < 0) {
@@ -1170,7 +1184,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
}
}
- if (sftp->open_state == libssh2_NB_state_sent) {
+ if(sftp->open_state == libssh2_NB_state_sent) {
size_t data_len;
unsigned char *data;
static const unsigned char fopen_responses[2] =
@@ -1178,13 +1192,13 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
rc = sftp_packet_requirev(sftp, 2, fopen_responses,
sftp->open_request_id, &data,
&data_len, 1);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for status message");
return NULL;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
_libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
@@ -1192,7 +1206,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
return NULL;
}
sftp->open_state = libssh2_NB_state_idle;
- if (rc) {
+ if(rc) {
_libssh2_error(session, rc, "Timeout waiting for status message");
return NULL;
}
@@ -1201,7 +1215,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
a fine response while STATUS means error. It seems though that at
times we get an SSH_FX_OK back in a STATUS, followed the "real"
HANDLE so we need to properly deal with that. */
- if (data[0] == SSH_FXP_STATUS) {
+ if(data[0] == SSH_FXP_STATUS) {
int badness = 1;
if(data_len < 9) {
@@ -1214,7 +1228,8 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
sftp->last_errno = _libssh2_ntohu32(data + 5);
if(LIBSSH2_FX_OK == sftp->last_errno) {
- _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got HANDLE FXOK!");
+ _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+ "got HANDLE FXOK!");
LIBSSH2_FREE(session, data);
@@ -1227,8 +1242,8 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
sftp->open_state = libssh2_NB_state_sent;
return NULL;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
_libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
@@ -1243,7 +1258,8 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
if(badness) {
_libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Failed opening remote file");
- _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got FXP_STATUS %d",
+ _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
+ "got FXP_STATUS %d",
sftp->last_errno);
LIBSSH2_FREE(session, data);
return NULL;
@@ -1258,7 +1274,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
}
fp = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
- if (!fp) {
+ if(!fp) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate new SFTP handle structure");
LIBSSH2_FREE(session, data);
@@ -1268,7 +1284,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
LIBSSH2_SFTP_HANDLE_DIR;
fp->handle_len = _libssh2_ntohu32(data + 5);
- if (fp->handle_len > SFTP_HANDLE_MAXLEN)
+ if(fp->handle_len > SFTP_HANDLE_MAXLEN)
/* SFTP doesn't allow handles longer than 256 characters */
fp->handle_len = SFTP_HANDLE_MAXLEN;
@@ -1364,7 +1380,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
and second phases on the next call and resume sending.
*/
- switch (sftp->read_state) {
+ switch(sftp->read_state) {
case libssh2_NB_state_idle:
/* Some data may already have been read from the server in the
@@ -1388,9 +1404,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
return copy;
}
- if (filep->eof) {
+ if(filep->eof) {
return 0;
- } else {
+ }
+ else {
/* We allow a number of bytes being requested at any given time
without having been acked - until we reach EOF. */
@@ -1441,7 +1458,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
at next call */
assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->data_left);
assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->eof);
- if (rc)
+ if(rc)
return rc;
}
}
@@ -1455,14 +1472,14 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
uint32_t request_id;
uint32_t size = count;
- if (size < buffer_size)
+ if(size < buffer_size)
size = buffer_size;
- if (size > MAX_SFTP_READ_SIZE)
+ if(size > MAX_SFTP_READ_SIZE)
size = MAX_SFTP_READ_SIZE;
chunk = LIBSSH2_ALLOC(session, packet_len +
sizeof(struct sftp_pipeline_chunk));
- if (!chunk)
+ if(!chunk)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"malloc fail for FXP_WRITE");
@@ -1485,13 +1502,13 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
/* add this new entry LAST in the list */
_libssh2_list_add(&handle->packet_list, &chunk->node);
- count -= MIN(size,count); /* deduct the size we used, as we might
- * have to create more packets */
+ count -= MIN(size, count); /* deduct the size we used, as we might
+ * have to create more packets */
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"read request id %d sent (offset: %d, size: %d)",
request_id, (int)chunk->offset, (int)chunk->len);
}
-
+ /* FALL-THROUGH */
case libssh2_NB_state_sent:
sftp->read_state = libssh2_NB_state_idle;
@@ -1519,9 +1536,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
/* We still have data left to send for this chunk.
* If there is at least one completely sent chunk,
* we can get out of this loop and start reading. */
- if (chunk != _libssh2_list_first(&handle->packet_list)) {
+ if(chunk != _libssh2_list_first(&handle->packet_list)) {
break;
- } else {
+ }
+ else {
continue;
}
}
@@ -1530,6 +1548,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 */
case libssh2_NB_state_sent2:
@@ -1551,9 +1570,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
if(chunk->lefttosend) {
/* if the chunk still has data left to send, we shouldn't wait
for an ACK for it just yet */
- if (bytes_in_buffer > 0) {
+ if(bytes_in_buffer > 0) {
return bytes_in_buffer;
- } else {
+ }
+ else {
/* we should never reach this point */
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"sftp_read() internal error");
@@ -1562,14 +1582,14 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
rc = sftp_packet_requirev(sftp, 2, read_responses,
chunk->request_id, &data, &data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN && bytes_in_buffer != 0) {
+ if(rc == LIBSSH2_ERROR_EAGAIN && bytes_in_buffer != 0) {
/* do not return EAGAIN if we have already
* written data into the buffer */
return bytes_in_buffer;
}
- if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
@@ -1585,7 +1605,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
* FX_EOF when we reach the end of the file.
*/
- switch (data[0]) {
+ switch(data[0]) {
case SSH_FXP_STATUS:
/* remove the chunk we just processed */
@@ -1599,7 +1619,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
rc32 = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (rc32 == LIBSSH2_FX_EOF) {
+ if(rc32 == LIBSSH2_FX_EOF) {
filep->eof = TRUE;
return bytes_in_buffer;
}
@@ -1611,7 +1631,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
break;
case SSH_FXP_DATA:
- if (chunk->offset != filep->offset) {
+ if(chunk->offset != filep->offset) {
/* This could happen if the server returns less bytes than
requested, which shouldn't happen for normal files. See:
https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
@@ -1622,7 +1642,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
}
rc32 = _libssh2_ntohu32(data + 5);
- if (rc32 > (data_len - 9))
+ if(rc32 > (data_len - 9))
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP Protocol badness");
@@ -1676,9 +1696,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
/* check if we have space left in the buffer
* and either continue to the next chunk or stop
*/
- if (bytes_in_buffer < buffer_size) {
+ if(bytes_in_buffer < buffer_size) {
chunk = next;
- } else {
+ }
+ else {
chunk = NULL;
}
@@ -1690,7 +1711,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
}
}
- if (bytes_in_buffer > 0)
+ if(bytes_in_buffer > 0)
return bytes_in_buffer;
break;
@@ -1739,8 +1760,8 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
SSH_FXP_NAME, SSH_FXP_STATUS };
ssize_t retcode;
- if (sftp->readdir_state == libssh2_NB_state_idle) {
- if (handle->u.dir.names_left) {
+ if(sftp->readdir_state == libssh2_NB_state_idle) {
+ if(handle->u.dir.names_left) {
/*
* A prior request returned more than one directory entry,
* feed it back from the buffer
@@ -1750,29 +1771,53 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
size_t real_filename_len;
size_t filename_len;
size_t longentry_len;
-
- s = (unsigned char *) handle->u.dir.next_name;
- real_filename_len = _libssh2_ntohu32(s);
-
- s += 4;
+ size_t names_packet_len = handle->u.dir.names_packet_len;
+ int attr_len = 0;
+
+ if(names_packet_len >= 4) {
+ s = (unsigned char *) handle->u.dir.next_name;
+ real_filename_len = _libssh2_ntohu32(s);
+ s += 4;
+ names_packet_len -= 4;
+ }
+ else {
+ filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+ goto end;
+ }
filename_len = real_filename_len;
- if (filename_len >= buffer_maxlen) {
+ if(filename_len >= buffer_maxlen) {
filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
goto end;
}
- memcpy(buffer, s, filename_len);
- buffer[filename_len] = '\0'; /* zero terminate */
- s += real_filename_len;
+ if(buffer_maxlen >= filename_len && names_packet_len >=
+ filename_len) {
+ memcpy(buffer, s, filename_len);
+ buffer[filename_len] = '\0'; /* zero terminate */
+ s += real_filename_len;
+ names_packet_len -= real_filename_len;
+ }
+ else {
+ filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+ goto end;
+ }
- real_longentry_len = _libssh2_ntohu32(s);
- s += 4;
+ if(names_packet_len >= 4) {
+ real_longentry_len = _libssh2_ntohu32(s);
+ s += 4;
+ names_packet_len -= 4;
+ }
+ else {
+ filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+ goto end;
+ }
- if (longentry && (longentry_maxlen>1)) {
+ if(longentry && (longentry_maxlen>1)) {
longentry_len = real_longentry_len;
- if (longentry_len >= longentry_maxlen) {
+ if(longentry_len >= longentry_maxlen ||
+ longentry_len > names_packet_len) {
filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
goto end;
}
@@ -1780,17 +1825,36 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
memcpy(longentry, s, longentry_len);
longentry[longentry_len] = '\0'; /* zero terminate */
}
- s += real_longentry_len;
- if (attrs)
+ if(real_longentry_len <= names_packet_len) {
+ s += real_longentry_len;
+ names_packet_len -= real_longentry_len;
+ }
+ else {
+ filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+ goto end;
+ }
+
+ if(attrs)
memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- s += sftp_bin2attr(attrs ? attrs : &attrs_dummy, s, 32);
+ attr_len = sftp_bin2attr(attrs ? attrs : &attrs_dummy, s,
+ names_packet_len);
+
+ if(attr_len >= 0) {
+ s += attr_len;
+ names_packet_len -= attr_len;
+ }
+ else {
+ filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
+ goto end;
+ }
handle->u.dir.next_name = (char *) s;
+ handle->u.dir.names_packet_len = names_packet_len;
end:
- if ((--handle->u.dir.names_left) == 0)
+ if((--handle->u.dir.names_left) == 0)
LIBSSH2_FREE(session, handle->u.dir.names_packet);
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
@@ -1802,7 +1866,7 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
/* Request another entry(entries?) */
s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!sftp->readdir_packet)
+ if(!sftp->readdir_packet)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"FXP_READDIR packet");
@@ -1816,15 +1880,15 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
sftp->readdir_state = libssh2_NB_state_created;
}
- if (sftp->readdir_state == libssh2_NB_state_created) {
+ if(sftp->readdir_state == libssh2_NB_state_created) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Reading entries from directory handle");
retcode = _libssh2_channel_write(channel, 0, sftp->readdir_packet,
packet_len);
- if (retcode == LIBSSH2_ERROR_EAGAIN) {
+ if(retcode == LIBSSH2_ERROR_EAGAIN) {
return retcode;
}
- else if ((ssize_t)packet_len != retcode) {
+ else if((ssize_t)packet_len != retcode) {
LIBSSH2_FREE(session, sftp->readdir_packet);
sftp->readdir_packet = NULL;
sftp->readdir_state = libssh2_NB_state_idle;
@@ -1841,25 +1905,25 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
retcode = sftp_packet_requirev(sftp, 2, read_responses,
sftp->readdir_request_id, &data,
&data_len, 9);
- if (retcode == LIBSSH2_ERROR_EAGAIN)
+ if(retcode == LIBSSH2_ERROR_EAGAIN)
return retcode;
- else if (retcode == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ else if(retcode == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
- return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
- "Status message too short");
+ return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
+ "Status message too short");
}
- else if (retcode) {
+ else if(retcode) {
sftp->readdir_state = libssh2_NB_state_idle;
return _libssh2_error(session, retcode,
"Timeout waiting for status message");
}
- if (data[0] == SSH_FXP_STATUS) {
+ if(data[0] == SSH_FXP_STATUS) {
retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode == LIBSSH2_FX_EOF) {
+ if(retcode == LIBSSH2_FX_EOF) {
sftp->readdir_state = libssh2_NB_state_idle;
return 0;
}
@@ -1876,7 +1940,7 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
num_names = _libssh2_ntohu32(data + 5);
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned",
num_names);
- if (!num_names) {
+ if(!num_names) {
LIBSSH2_FREE(session, data);
return 0;
}
@@ -1884,6 +1948,7 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
handle->u.dir.names_left = num_names;
handle->u.dir.names_packet = data;
handle->u.dir.next_name = (char *) data + 9;
+ handle->u.dir.names_packet_len = data_len - 9;
/* use the name popping mechanism from the start of the function */
return sftp_readdir(handle, buffer, buffer_maxlen, longentry,
@@ -1967,14 +2032,15 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
default:
case libssh2_NB_state_idle:
- /* Number of bytes sent off that haven't been acked and therefor we
+ /* Number of bytes sent off that haven't been acked and therefore we
will get passed in here again.
Also, add up the number of bytes that actually already have been
acked but we haven't been able to return as such yet, so we will
get that data as well passed in here again.
*/
- already = (size_t) (handle->u.file.offset_sent - handle->u.file.offset)+
+ already = (size_t) (handle->u.file.offset_sent -
+ handle->u.file.offset)+
handle->u.file.acked;
if(count >= already) {
@@ -1999,7 +2065,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
chunk = LIBSSH2_ALLOC(session, packet_len +
sizeof(struct sftp_pipeline_chunk));
- if (!chunk)
+ if(!chunk)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"malloc fail for FXP_WRITE");
@@ -2027,8 +2093,8 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
to create more packets */
}
- /* move through the WRITE packets that haven't been sent and send as many
- as possible - remember that we don't block */
+ /* move through the WRITE packets that haven't been sent and send as
+ many as possible - remember that we don't block */
chunk = _libssh2_list_first(&handle->packet_list);
while(chunk) {
@@ -2076,15 +2142,15 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
/* we check the packets in order */
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
chunk->request_id, &data, &data_len, 9);
- if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"FXP write packet too short");
}
- else if (rc < 0) {
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ else if(rc < 0) {
+ if(rc == LIBSSH2_ERROR_EAGAIN)
sftp->write_state = libssh2_NB_state_sent;
return rc;
}
@@ -2093,7 +2159,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
LIBSSH2_FREE(session, data);
sftp->last_errno = retcode;
- if (retcode == LIBSSH2_FX_OK) {
+ if(retcode == LIBSSH2_FX_OK) {
acked += chunk->len; /* number of payload data that was acked
here */
@@ -2113,7 +2179,8 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
/* since we return error now, the application will not get any
outstanding data acked, so we need to rewind the offset to
- where the application knows it has reached with acked data */
+ where the application knows it has reached with acked
+ data */
handle->u.file.offset -= handle->u.file.acked;
/* then reset the offset_sent to be the same as the offset */
@@ -2123,8 +2190,8 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
ack after an error */
handle->u.file.acked = 0;
- /* the server returned an error for that written chunk, propagate
- this back to our parent function */
+ /* the server returned an error for that written chunk,
+ propagate this back to our parent function */
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"FXP write failed");
}
@@ -2183,11 +2250,11 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
ssize_t rc;
uint32_t retcode;
- if (sftp->fsync_state == libssh2_NB_state_idle) {
+ if(sftp->fsync_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Issuing fsync command");
s = packet = LIBSSH2_ALLOC(session, packet_len);
- if (!packet) {
+ if(!packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_EXTENDED "
"packet");
@@ -2201,13 +2268,14 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
_libssh2_store_str(&s, handle->handle, handle->handle_len);
sftp->fsync_state = libssh2_NB_state_created;
- } else {
+ }
+ else {
packet = sftp->fsync_packet;
}
- if (sftp->fsync_state == libssh2_NB_state_created) {
+ if(sftp->fsync_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, packet, packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN ||
+ if(rc == LIBSSH2_ERROR_EAGAIN ||
(0 <= rc && rc < (ssize_t)packet_len)) {
sftp->fsync_packet = packet;
return LIBSSH2_ERROR_EAGAIN;
@@ -2216,7 +2284,7 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
LIBSSH2_FREE(session, packet);
sftp->fsync_packet = NULL;
- if (rc < 0) {
+ if(rc < 0) {
sftp->fsync_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"_libssh2_channel_write() failed");
@@ -2226,17 +2294,17 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->fsync_request_id, &data, &data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 fsync packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->fsync_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Error waiting for FXP EXTENDED REPLY");
@@ -2247,7 +2315,7 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode != LIBSSH2_FX_OK) {
+ if(retcode != LIBSSH2_FX_OK) {
sftp->last_errno = retcode;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"fsync failed");
@@ -2291,11 +2359,11 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
{ SSH_FXP_ATTRS, SSH_FXP_STATUS };
ssize_t rc;
- if (sftp->fstat_state == libssh2_NB_state_idle) {
+ if(sftp->fstat_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command",
setstat ? "set-stat" : "stat");
s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!sftp->fstat_packet) {
+ if(!sftp->fstat_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"FSTAT/FSETSTAT packet");
@@ -2307,20 +2375,20 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
_libssh2_store_u32(&s, sftp->fstat_request_id);
_libssh2_store_str(&s, handle->handle, handle->handle_len);
- if (setstat) {
+ if(setstat) {
s += sftp_attr2bin(s, attrs);
}
sftp->fstat_state = libssh2_NB_state_created;
}
- if (sftp->fstat_state == libssh2_NB_state_created) {
+ if(sftp->fstat_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, sftp->fstat_packet,
packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if ((ssize_t)packet_len != rc) {
+ else if((ssize_t)packet_len != rc) {
LIBSSH2_FREE(session, sftp->fstat_packet);
sftp->fstat_packet = NULL;
sftp->fstat_state = libssh2_NB_state_idle;
@@ -2337,16 +2405,16 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
rc = sftp_packet_requirev(sftp, 2, fstat_responses,
sftp->fstat_request_id, &data,
&data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 fstat packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->fstat_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Timeout waiting for status message");
@@ -2354,21 +2422,22 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
sftp->fstat_state = libssh2_NB_state_idle;
- if (data[0] == SSH_FXP_STATUS) {
+ if(data[0] == SSH_FXP_STATUS) {
uint32_t retcode;
retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode == LIBSSH2_FX_OK) {
+ if(retcode == LIBSSH2_FX_OK) {
return 0;
- } else {
+ }
+ else {
sftp->last_errno = retcode;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP Protocol Error");
}
}
- if (sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) {
+ if(sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) {
LIBSSH2_FREE(session, data);
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Attributes too short in SFTP fstat");
@@ -2411,7 +2480,7 @@ libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset)
sftp_packetlist_flush(handle);
/* free the left received buffered data */
- if (handle->u.file.data_left) {
+ if(handle->u.file.data_left) {
LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data);
handle->u.file.data_left = handle->u.file.data_len = 0;
handle->u.file.data = NULL;
@@ -2512,15 +2581,16 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
unsigned char *s, *data = NULL;
int rc = 0;
- if (handle->close_state == libssh2_NB_state_idle) {
+ if(handle->close_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle");
s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!handle->close_packet) {
+ if(!handle->close_packet) {
handle->close_state = libssh2_NB_state_idle;
rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_CLOSE "
"packet");
- } else {
+ }
+ else {
_libssh2_store_u32(&s, packet_len - 4);
*(s++) = SSH_FXP_CLOSE;
@@ -2531,38 +2601,40 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
}
}
- if (handle->close_state == libssh2_NB_state_created) {
+ if(handle->close_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, handle->close_packet,
packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if ((ssize_t)packet_len != rc) {
+ }
+ else if((ssize_t)packet_len != rc) {
handle->close_state = libssh2_NB_state_idle;
rc = _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_CLOSE command");
- } else
+ }
+ else
handle->close_state = libssh2_NB_state_sent;
LIBSSH2_FREE(session, handle->close_packet);
handle->close_packet = NULL;
}
- if (handle->close_state == libssh2_NB_state_sent) {
+ if(handle->close_state == libssh2_NB_state_sent) {
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
handle->close_request_id, &data,
&data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
data = NULL;
_libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Packet too short in FXP_CLOSE command");
}
- else if (rc) {
+ else if(rc) {
_libssh2_error(session, rc,
"Error waiting for status message");
}
@@ -2575,11 +2647,12 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
happened for which we should have set an error code */
assert(rc);
- } else {
+ }
+ else {
int retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode != LIBSSH2_FX_OK) {
+ if(retcode != LIBSSH2_FX_OK) {
sftp->last_errno = retcode;
handle->close_state = libssh2_NB_state_idle;
rc = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
@@ -2590,11 +2663,11 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
/* remove this handle from the parent's list */
_libssh2_list_remove(&handle->node);
- if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR)
- && handle->u.dir.names_left) {
- LIBSSH2_FREE(session, handle->u.dir.names_packet);
+ if(handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) {
+ if(handle->u.dir.names_left)
+ LIBSSH2_FREE(session, handle->u.dir.names_packet);
}
- else {
+ else if(handle->handle_type == LIBSSH2_SFTP_HANDLE_FILE) {
if(handle->u.file.data)
LIBSSH2_FREE(session, handle->u.file.data);
}
@@ -2639,10 +2712,10 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
unsigned char *s, *data;
int rc;
- if (sftp->unlink_state == libssh2_NB_state_idle) {
+ if(sftp->unlink_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename);
s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!sftp->unlink_packet) {
+ if(!sftp->unlink_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_REMOVE "
"packet");
@@ -2656,12 +2729,13 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
sftp->unlink_state = libssh2_NB_state_created;
}
- if (sftp->unlink_state == libssh2_NB_state_created) {
+ if(sftp->unlink_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, sftp->unlink_packet,
packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if ((ssize_t)packet_len != rc) {
+ }
+ else if((ssize_t)packet_len != rc) {
LIBSSH2_FREE(session, sftp->unlink_packet);
sftp->unlink_packet = NULL;
sftp->unlink_state = libssh2_NB_state_idle;
@@ -2677,17 +2751,17 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->unlink_request_id, &data,
&data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 unlink packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->unlink_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Error waiting for FXP STATUS");
@@ -2698,9 +2772,10 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode == LIBSSH2_FX_OK) {
+ if(retcode == LIBSSH2_FX_OK) {
return 0;
- } else {
+ }
+ else {
sftp->last_errno = retcode;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP Protocol Error");
@@ -2744,17 +2819,17 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
unsigned char *data;
ssize_t rc;
- if (sftp->version < 2) {
+ if(sftp->version < 2) {
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Server does not support RENAME");
}
- if (sftp->rename_state == libssh2_NB_state_idle) {
+ if(sftp->rename_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s",
source_filename, dest_filename);
sftp->rename_s = sftp->rename_packet =
LIBSSH2_ALLOC(session, packet_len);
- if (!sftp->rename_packet) {
+ if(!sftp->rename_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_RENAME "
"packet");
@@ -2768,18 +2843,19 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
source_filename_len);
_libssh2_store_str(&sftp->rename_s, dest_filename, dest_filename_len);
- if (sftp->version >= 5)
+ if(sftp->version >= 5)
_libssh2_store_u32(&sftp->rename_s, flags);
sftp->rename_state = libssh2_NB_state_created;
}
- if (sftp->rename_state == libssh2_NB_state_created) {
+ if(sftp->rename_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, sftp->rename_packet,
sftp->rename_s - sftp->rename_packet);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if ((ssize_t)packet_len != rc) {
+ }
+ else if((ssize_t)packet_len != rc) {
LIBSSH2_FREE(session, sftp->rename_packet);
sftp->rename_packet = NULL;
sftp->rename_state = libssh2_NB_state_idle;
@@ -2795,17 +2871,17 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rename_request_id, &data,
&data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 rename packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->rename_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Error waiting for FXP STATUS");
@@ -2820,7 +2896,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
/* now convert the SFTP error code to libssh2 return code or error
message */
- switch (retcode) {
+ switch(retcode) {
case LIBSSH2_FX_OK:
retcode = LIBSSH2_ERROR_NONE;
break;
@@ -2884,11 +2960,11 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
static const unsigned char responses[2] =
{ SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS };
- if (sftp->fstatvfs_state == libssh2_NB_state_idle) {
+ if(sftp->fstatvfs_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Getting file system statistics");
s = packet = LIBSSH2_ALLOC(session, packet_len);
- if (!packet) {
+ if(!packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_EXTENDED "
"packet");
@@ -2907,9 +2983,9 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
packet = sftp->fstatvfs_packet;
}
- if (sftp->fstatvfs_state == libssh2_NB_state_created) {
+ if(sftp->fstatvfs_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, packet, packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN ||
+ if(rc == LIBSSH2_ERROR_EAGAIN ||
(0 <= rc && rc < (ssize_t)packet_len)) {
sftp->fstatvfs_packet = packet;
return LIBSSH2_ERROR_EAGAIN;
@@ -2918,7 +2994,7 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
LIBSSH2_FREE(session, packet);
sftp->fstatvfs_packet = NULL;
- if (rc < 0) {
+ if(rc < 0) {
sftp->fstatvfs_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"_libssh2_channel_write() failed");
@@ -2929,23 +3005,23 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
rc = sftp_packet_requirev(sftp, 2, responses, sftp->fstatvfs_request_id,
&data, &data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 rename packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->fstatvfs_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Error waiting for FXP EXTENDED REPLY");
}
- if (data[0] == SSH_FXP_STATUS) {
+ if(data[0] == SSH_FXP_STATUS) {
int retcode = _libssh2_ntohu32(data + 5);
sftp->fstatvfs_state = libssh2_NB_state_idle;
LIBSSH2_FREE(session, data);
@@ -2954,7 +3030,7 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
"SFTP Protocol Error");
}
- if (data_len < 93) {
+ if(data_len < 93) {
LIBSSH2_FREE(session, data);
sftp->fstatvfs_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
@@ -2994,7 +3070,8 @@ libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
int rc;
if(!handle || !st)
return LIBSSH2_ERROR_BAD_USE;
- BLOCK_ADJUST(rc, handle->sftp->channel->session, sftp_fstatvfs(handle, st));
+ BLOCK_ADJUST(rc, handle->sftp->channel->session,
+ sftp_fstatvfs(handle, st));
return rc;
}
@@ -3019,11 +3096,11 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
static const unsigned char responses[2] =
{ SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS };
- if (sftp->statvfs_state == libssh2_NB_state_idle) {
+ if(sftp->statvfs_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Getting file system statistics of %s", path);
s = packet = LIBSSH2_ALLOC(session, packet_len);
- if (!packet) {
+ if(!packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_EXTENDED "
"packet");
@@ -3042,9 +3119,9 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
packet = sftp->statvfs_packet;
}
- if (sftp->statvfs_state == libssh2_NB_state_created) {
+ if(sftp->statvfs_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, packet, packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN ||
+ if(rc == LIBSSH2_ERROR_EAGAIN ||
(0 <= rc && rc < (ssize_t)packet_len)) {
sftp->statvfs_packet = packet;
return LIBSSH2_ERROR_EAGAIN;
@@ -3053,7 +3130,7 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
LIBSSH2_FREE(session, packet);
sftp->statvfs_packet = NULL;
- if (rc < 0) {
+ if(rc < 0) {
sftp->statvfs_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"_libssh2_channel_write() failed");
@@ -3063,23 +3140,23 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_requirev(sftp, 2, responses, sftp->statvfs_request_id,
&data, &data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 fstat packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->statvfs_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Error waiting for FXP EXTENDED REPLY");
}
- if (data[0] == SSH_FXP_STATUS) {
+ if(data[0] == SSH_FXP_STATUS) {
int retcode = _libssh2_ntohu32(data + 5);
sftp->statvfs_state = libssh2_NB_state_idle;
LIBSSH2_FREE(session, data);
@@ -3088,7 +3165,7 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
"SFTP Protocol Error");
}
- if (data_len < 93) {
+ if(data_len < 93) {
LIBSSH2_FREE(session, data);
sftp->statvfs_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
@@ -3146,27 +3223,32 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
LIBSSH2_SFTP_ATTRIBUTES attrs = {
- LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0
};
size_t data_len;
int retcode;
- /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
- ssize_t packet_len = path_len + 13 +
- sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS);
+ ssize_t packet_len;
unsigned char *packet, *s, *data;
int rc;
- if (sftp->mkdir_state == libssh2_NB_state_idle) {
+ if(mode != LIBSSH2_SFTP_DEFAULT_MODE) {
+ /* Filetype in SFTP 3 and earlier */
+ attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+ attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR;
+ }
+
+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
+ packet_len = path_len + 13 + sftp_attrsize(attrs.flags);
+
+ if(sftp->mkdir_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Creating directory %s with mode 0%lo", path, mode);
s = packet = LIBSSH2_ALLOC(session, packet_len);
- if (!packet) {
+ if(!packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_MKDIR "
"packet");
}
- /* Filetype in SFTP 3 and earlier */
- attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR;
_libssh2_store_u32(&s, packet_len - 4);
*(s++) = SSH_FXP_MKDIR;
@@ -3182,13 +3264,13 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
packet = sftp->mkdir_packet;
}
- if (sftp->mkdir_state == libssh2_NB_state_created) {
+ if(sftp->mkdir_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, packet, packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
sftp->mkdir_packet = packet;
return rc;
}
- if (packet_len != rc) {
+ if(packet_len != rc) {
LIBSSH2_FREE(session, packet);
sftp->mkdir_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
@@ -3201,17 +3283,17 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id,
&data, &data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 mkdir packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->mkdir_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Error waiting for FXP STATUS");
@@ -3222,10 +3304,11 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode == LIBSSH2_FX_OK) {
+ if(retcode == LIBSSH2_FX_OK) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!");
return 0;
- } else {
+ }
+ else {
sftp->last_errno = retcode;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP Protocol Error");
@@ -3264,11 +3347,11 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
unsigned char *s, *data;
int rc;
- if (sftp->rmdir_state == libssh2_NB_state_idle) {
+ if(sftp->rmdir_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Removing directory: %s",
path);
s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!sftp->rmdir_packet) {
+ if(!sftp->rmdir_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_RMDIR "
"packet");
@@ -3283,12 +3366,13 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
sftp->rmdir_state = libssh2_NB_state_created;
}
- if (sftp->rmdir_state == libssh2_NB_state_created) {
+ if(sftp->rmdir_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, sftp->rmdir_packet,
packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (packet_len != rc) {
+ }
+ else if(packet_len != rc) {
LIBSSH2_FREE(session, sftp->rmdir_packet);
sftp->rmdir_packet = NULL;
sftp->rmdir_state = libssh2_NB_state_idle;
@@ -3303,17 +3387,17 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rmdir_request_id, &data, &data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 rmdir packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->rmdir_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Error waiting for FXP STATUS");
@@ -3324,9 +3408,10 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode == LIBSSH2_FX_OK) {
+ if(retcode == LIBSSH2_FX_OK) {
return 0;
- } else {
+ }
+ else {
sftp->last_errno = retcode;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP Protocol Error");
@@ -3368,13 +3453,13 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
{ SSH_FXP_ATTRS, SSH_FXP_STATUS };
int rc;
- if (sftp->stat_state == libssh2_NB_state_idle) {
+ if(sftp->stat_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s",
(stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" :
(stat_type ==
LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path);
s = sftp->stat_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!sftp->stat_packet) {
+ if(!sftp->stat_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_*STAT "
"packet");
@@ -3382,7 +3467,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
_libssh2_store_u32(&s, packet_len - 4);
- switch (stat_type) {
+ switch(stat_type) {
case LIBSSH2_SFTP_SETSTAT:
*(s++) = SSH_FXP_SETSTAT;
break;
@@ -3399,17 +3484,18 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
_libssh2_store_u32(&s, sftp->stat_request_id);
_libssh2_store_str(&s, path, path_len);
- if (stat_type == LIBSSH2_SFTP_SETSTAT)
+ if(stat_type == LIBSSH2_SFTP_SETSTAT)
s += sftp_attr2bin(s, attrs);
sftp->stat_state = libssh2_NB_state_created;
}
- if (sftp->stat_state == libssh2_NB_state_created) {
+ if(sftp->stat_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, sftp->stat_packet, packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
- } else if (packet_len != rc) {
+ }
+ else if(packet_len != rc) {
LIBSSH2_FREE(session, sftp->stat_packet);
sftp->stat_packet = NULL;
sftp->stat_state = libssh2_NB_state_idle;
@@ -3424,16 +3510,16 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
rc = sftp_packet_requirev(sftp, 2, stat_responses,
sftp->stat_request_id, &data, &data_len, 9);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
- else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ 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 stat packet too short");
}
- else if (rc) {
+ else if(rc) {
sftp->stat_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Timeout waiting for status message");
@@ -3441,14 +3527,16 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
sftp->stat_state = libssh2_NB_state_idle;
- if (data[0] == SSH_FXP_STATUS) {
+ if(data[0] == SSH_FXP_STATUS) {
int retcode;
retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode == LIBSSH2_FX_OK) {
+ if(retcode == LIBSSH2_FX_OK) {
+ memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
return 0;
- } else {
+ }
+ else {
sftp->last_errno = retcode;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP Protocol Error");
@@ -3456,7 +3544,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
}
memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- if (sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) {
+ if(sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) {
LIBSSH2_FREE(session, data);
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Attributes too short in SFTP fstat");
@@ -3502,14 +3590,14 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
{ SSH_FXP_NAME, SSH_FXP_STATUS };
int retcode;
- if ((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) {
+ if((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) {
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Server does not support SYMLINK or READLINK");
}
- if (sftp->symlink_state == libssh2_NB_state_idle) {
+ if(sftp->symlink_state == libssh2_NB_state_idle) {
s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len);
- if (!sftp->symlink_packet) {
+ if(!sftp->symlink_packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"SYMLINK/READLINK/REALPATH packet");
@@ -3523,7 +3611,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
_libssh2_store_u32(&s, packet_len - 4);
- switch (link_type) {
+ switch(link_type) {
case LIBSSH2_SFTP_REALPATH:
*(s++) = SSH_FXP_REALPATH;
break;
@@ -3540,18 +3628,18 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
_libssh2_store_u32(&s, sftp->symlink_request_id);
_libssh2_store_str(&s, path, path_len);
- if (link_type == LIBSSH2_SFTP_SYMLINK)
+ if(link_type == LIBSSH2_SFTP_SYMLINK)
_libssh2_store_str(&s, target, target_len);
sftp->symlink_state = libssh2_NB_state_created;
}
- if (sftp->symlink_state == libssh2_NB_state_created) {
+ if(sftp->symlink_state == libssh2_NB_state_created) {
ssize_t rc = _libssh2_channel_write(channel, 0, sftp->symlink_packet,
packet_len);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
- else if (packet_len != rc) {
+ else if(packet_len != rc) {
LIBSSH2_FREE(session, sftp->symlink_packet);
sftp->symlink_packet = NULL;
sftp->symlink_state = libssh2_NB_state_idle;
@@ -3567,16 +3655,16 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
retcode = sftp_packet_requirev(sftp, 2, link_responses,
sftp->symlink_request_id, &data,
&data_len, 9);
- if (retcode == LIBSSH2_ERROR_EAGAIN)
+ if(retcode == LIBSSH2_ERROR_EAGAIN)
return retcode;
- else if (retcode == LIBSSH2_ERROR_OUT_OF_BOUNDARY) {
- if (data_len > 0) {
+ else if(retcode == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP symlink packet too short");
}
- else if (retcode) {
+ else if(retcode) {
sftp->symlink_state = libssh2_NB_state_idle;
return _libssh2_error(session, retcode,
"Error waiting for status message");
@@ -3584,12 +3672,10 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
sftp->symlink_state = libssh2_NB_state_idle;
- if (data[0] == SSH_FXP_STATUS) {
- int retcode;
-
+ if(data[0] == SSH_FXP_STATUS) {
retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
- if (retcode == LIBSSH2_FX_OK)
+ if(retcode == LIBSSH2_FX_OK)
return LIBSSH2_ERROR_NONE;
else {
sftp->last_errno = retcode;
@@ -3598,15 +3684,15 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
}
}
- if (_libssh2_ntohu32(data + 5) < 1) {
+ if(_libssh2_ntohu32(data + 5) < 1) {
LIBSSH2_FREE(session, data);
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Invalid READLINK/REALPATH response, "
"no name entries");
}
- if (data_len < 13) {
- if (data_len > 0) {
+ if(data_len < 13) {
+ if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
@@ -3615,7 +3701,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
/* this reads a u32 and stores it into a signed 32bit value */
link_len = _libssh2_ntohu32(data + 9);
- if (link_len < target_len) {
+ if(link_len < target_len) {
memcpy(target, data + 13, link_len);
target[link_len] = 0;
retcode = (int)link_len;
@@ -3662,7 +3748,7 @@ libssh2_sftp_last_error(LIBSSH2_SFTP *sftp)
LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp)
{
- if (!sftp)
+ if(!sftp)
return NULL;
return sftp->channel;
diff --git a/libs/libssh2/src/sftp.h b/libs/libssh2/src/sftp.h
index 2ed32cea6d..ae4162f10f 100644
--- a/libs/libssh2/src/sftp.h
+++ b/libs/libssh2/src/sftp.h
@@ -122,6 +122,7 @@ struct _LIBSSH2_SFTP_HANDLE
uint32_t names_left;
void *names_packet;
char *next_name;
+ size_t names_packet_len;
} dir;
} u;
diff --git a/libs/libssh2/src/transport.c b/libs/libssh2/src/transport.c
index 7317579f36..45e445c743 100644
--- a/libs/libssh2/src/transport.c
+++ b/libs/libssh2/src/transport.c
@@ -65,16 +65,16 @@ debugdump(LIBSSH2_SESSION * session,
unsigned int width = 0x10;
char buffer[256]; /* Must be enough for width*4 + about 30 or so */
size_t used;
- static const char* hex_chars = "0123456789ABCDEF";
+ static const char *hex_chars = "0123456789ABCDEF";
- if (!(session->showmask & LIBSSH2_TRACE_TRANS)) {
+ if(!(session->showmask & LIBSSH2_TRACE_TRANS)) {
/* not asked for, bail out */
return;
}
used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n",
desc, (int) size);
- if (session->tracehandler)
+ if(session->tracehandler)
(session->tracehandler)(session, session->tracehandler_context,
buffer, used);
else
@@ -86,9 +86,9 @@ debugdump(LIBSSH2_SESSION * session,
/* hex not disabled, show it */
for(c = 0; c < width; c++) {
- if (i + c < size) {
- buffer[used++] = hex_chars[(ptr[i+c] >> 4) & 0xF];
- buffer[used++] = hex_chars[ptr[i+c] & 0xF];
+ if(i + c < size) {
+ buffer[used++] = hex_chars[(ptr[i + c] >> 4) & 0xF];
+ buffer[used++] = hex_chars[ptr[i + c] & 0xF];
}
else {
buffer[used++] = ' ';
@@ -96,7 +96,7 @@ debugdump(LIBSSH2_SESSION * session,
}
buffer[used++] = ' ';
- if ((width/2) - 1 == c)
+ if((width/2) - 1 == c)
buffer[used++] = ' ';
}
@@ -110,7 +110,7 @@ debugdump(LIBSSH2_SESSION * session,
buffer[used++] = '\n';
buffer[used] = 0;
- if (session->tracehandler)
+ if(session->tracehandler)
(session->tracehandler)(session, session->tracehandler_context,
buffer, used);
else
@@ -138,8 +138,8 @@ decrypt(LIBSSH2_SESSION * session, unsigned char *source,
we risk losing those extra bytes */
assert((len % blocksize) == 0);
- while (len >= blocksize) {
- if (session->remote.crypt->crypt(session, source, blocksize,
+ while(len >= blocksize) {
+ if(session->remote.crypt->crypt(session, source, blocksize,
&session->remote.crypt_abstract)) {
LIBSSH2_FREE(session, p->payload);
return LIBSSH2_ERROR_DECRYPT;
@@ -169,11 +169,11 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
int rc;
int compressed;
- if (session->fullpacket_state == libssh2_NB_state_idle) {
+ if(session->fullpacket_state == libssh2_NB_state_idle) {
session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED;
session->fullpacket_payload_len = p->packet_length - 1;
- if (encrypted) {
+ if(encrypted) {
/* Calculate MAC hash */
session->remote.mac->hash(session, macbuf, /* store hash here */
@@ -188,7 +188,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
* buffer. Note that 'payload_len' here is the packet_length
* field which includes the padding but not the MAC.
*/
- if (memcmp(macbuf, p->payload + session->fullpacket_payload_len,
+ if(memcmp(macbuf, p->payload + session->fullpacket_payload_len,
session->remote.mac->mac_len)) {
session->fullpacket_macstate = LIBSSH2_MAC_INVALID;
}
@@ -206,7 +206,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
((session->state & LIBSSH2_STATE_AUTHENTICATED) ||
session->local.comp->use_in_auth);
- if (compressed && session->remote.comp_abstract) {
+ if(compressed && session->remote.comp_abstract) {
/*
* The buffer for the decompression (remote.comp_abstract) is
* initialised in time when it is needed so as long it is NULL we
@@ -237,13 +237,13 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
session->fullpacket_state = libssh2_NB_state_created;
}
- if (session->fullpacket_state == libssh2_NB_state_created) {
+ if(session->fullpacket_state == libssh2_NB_state_created) {
rc = _libssh2_packet_add(session, p->payload,
session->fullpacket_payload_len,
session->fullpacket_macstate);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return rc;
- if (rc) {
+ if(rc) {
session->fullpacket_state = libssh2_NB_state_idle;
return rc;
}
@@ -281,7 +281,6 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
unsigned char block[MAX_BLOCKSIZE];
int blocksize;
int encrypted = 1;
- size_t total_num;
/* default clear the bit */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
@@ -298,7 +297,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
* of packet_read, then don't redirect, as that would be an infinite loop!
*/
- if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
+ if(session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
!(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {
/* Whoever wants a packet won't get anything until the key re-exchange
@@ -307,7 +306,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the"
" key re-exchange from _libssh2_transport_read");
rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
- if (rc)
+ if(rc)
return rc;
}
@@ -316,20 +315,21 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
* I know this is very ugly and not a really good use of "goto", but
* this case statement would be even uglier to do it any other way
*/
- if (session->readPack_state == libssh2_NB_state_jump1) {
+ if(session->readPack_state == libssh2_NB_state_jump1) {
session->readPack_state = libssh2_NB_state_idle;
encrypted = session->readPack_encrypted;
goto libssh2_transport_read_point1;
}
do {
- if (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
+ if(session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
return LIBSSH2_ERROR_NONE;
}
- if (session->state & LIBSSH2_STATE_NEWKEYS) {
+ if(session->state & LIBSSH2_STATE_NEWKEYS) {
blocksize = session->remote.crypt->blocksize;
- } else {
+ }
+ else {
encrypted = 0; /* not encrypted */
blocksize = 5; /* not strictly true, but we can use 5 here to
make the checks below work fine still */
@@ -348,18 +348,19 @@ 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) {
/* If we have less than a blocksize left, it is too
little data to deal with, read more */
ssize_t nread;
/* move any remainder to the start of the buffer so
that we can do a full refill */
- if (remainbuf) {
+ if(remainbuf) {
memmove(p->buf, &p->buf[p->readidx], remainbuf);
p->readidx = 0;
p->writeidx = remainbuf;
- } else {
+ }
+ else {
/* nothing to move, just zero the indexes */
p->readidx = p->writeidx = 0;
}
@@ -369,10 +370,10 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
LIBSSH2_RECV(session, &p->buf[remainbuf],
PACKETBUFSIZE - remainbuf,
LIBSSH2_SOCKET_RECV_FLAGS(session));
- if (nread <= 0) {
+ if(nread <= 0) {
/* check if this is due to EAGAIN and return the special
return code if so, error out normally otherwise */
- if ((nread < 0) && (nread == -EAGAIN)) {
+ if((nread < 0) && (nread == -EAGAIN)) {
session->socket_block_directions |=
LIBSSH2_SESSION_BLOCK_INBOUND;
return LIBSSH2_ERROR_EAGAIN;
@@ -398,12 +399,14 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
/* how much data to deal with from the buffer */
numbytes = remainbuf;
- if (!p->total_num) {
+ if(!p->total_num) {
+ size_t total_num;
+
/* No payload package area allocated yet. To know the
size of this payload, we need to decrypt the first
blocksize data. */
- if (numbytes < blocksize) {
+ if(numbytes < blocksize) {
/* we can't act on anything less than blocksize, but this
check is only done for the initial block since once we have
got the start of a block we can in fact deal with fractions
@@ -413,15 +416,16 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
return LIBSSH2_ERROR_EAGAIN;
}
- if (encrypted) {
+ if(encrypted) {
rc = decrypt(session, &p->buf[p->readidx], block, blocksize);
- if (rc != LIBSSH2_ERROR_NONE) {
+ if(rc != LIBSSH2_ERROR_NONE) {
return rc;
}
/* save the first 5 bytes of the decrypted package, to be
used in the hash calculation later down. */
- memcpy(p->init, &p->buf[p->readidx], 5);
- } else {
+ memcpy(p->init, block, 5);
+ }
+ else {
/* the data is plain, just copy it verbatim to
the working block buffer */
memcpy(block, &p->buf[p->readidx], blocksize);
@@ -434,17 +438,15 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
* and we can extract packet and padding length from it
*/
p->packet_length = _libssh2_ntohu32(block);
- if (p->packet_length < 1)
- return LIBSSH2_ERROR_DECRYPT;
-
- p->padding_length = block[4];
if(p->packet_length < 1) {
return LIBSSH2_ERROR_DECRYPT;
}
else if(p->packet_length > LIBSSH2_PACKET_MAXPAYLOAD) {
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
- else if ( p->padding_length > p->packet_length - 1 ) {
+
+ p->padding_length = block[4];
+ if(p->padding_length > p->packet_length - 1) {
return LIBSSH2_ERROR_DECRYPT;
}
@@ -463,28 +465,29 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
* or less (including length, padding length, payload,
* padding, and MAC.)."
*/
- if (total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
+ if(total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
/* Get a packet handle put data into. We get one to
hold all data, including padding and MAC. */
p->payload = LIBSSH2_ALLOC(session, total_num);
- if (!p->payload) {
+ if(!p->payload) {
return LIBSSH2_ERROR_ALLOC;
}
p->total_num = total_num;
/* init write pointer to start of payload buffer */
p->wptr = p->payload;
- if (blocksize > 5) {
+ if(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 <= total_num) {
+ if(blocksize - 5 <= (int) total_num) {
memcpy(p->wptr, &block[5], blocksize - 5);
p->wptr += blocksize - 5; /* advance write pointer */
- } else {
+ }
+ else {
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
}
@@ -501,13 +504,13 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
package */
remainpack = p->total_num - p->data_num;
- if (numbytes > remainpack) {
+ if(numbytes > remainpack) {
/* if we have more data in the buffer than what is going into this
particular packet, we limit this round to this packet only */
numbytes = remainpack;
}
- if (encrypted) {
+ if(encrypted) {
/* 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
@@ -517,13 +520,14 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
/* if what we have plus numbytes is bigger than the
total minus the skip margin, we should lower the
amount to decrypt even more */
- if ((p->data_num + numbytes) > (p->total_num - skip)) {
+ if((p->data_num + numbytes) > (p->total_num - skip)) {
numdecrypt = (p->total_num - skip) - p->data_num;
- } else {
+ }
+ else {
int frac;
numdecrypt = numbytes;
frac = numdecrypt % blocksize;
- if (frac) {
+ if(frac) {
/* not an aligned amount of blocks,
align it */
numdecrypt -= frac;
@@ -532,16 +536,17 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
numbytes = 0;
}
}
- } else {
+ }
+ else {
/* unencrypted data should not be decrypted at all */
numdecrypt = 0;
}
/* if there are bytes to decrypt, do that */
- if (numdecrypt > 0) {
+ if(numdecrypt > 0) {
/* now decrypt the lot */
rc = decrypt(session, &p->buf[p->readidx], p->wptr, numdecrypt);
- if (rc != LIBSSH2_ERROR_NONE) {
+ if(rc != LIBSSH2_ERROR_NONE) {
p->total_num = 0; /* no packet buffer available */
return rc;
}
@@ -559,9 +564,9 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
/* if there are bytes to copy that aren't decrypted, simply
copy them as-is to the target buffer */
- if (numbytes > 0) {
-
- if (numbytes <= total_num - (p->wptr - p->payload)) {
+ if(numbytes > 0) {
+
+ if(numbytes <= (int)(p->total_num - (p->wptr - p->payload))) {
memcpy(p->wptr, &p->buf[p->readidx], numbytes);
}
else {
@@ -580,21 +585,21 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
current packet */
remainpack = p->total_num - p->data_num;
- if (!remainpack) {
+ if(!remainpack) {
/* we have a full packet */
libssh2_transport_read_point1:
rc = fullpacket(session, encrypted);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
- if (session->packAdd_state != libssh2_NB_state_idle)
- {
+ if(session->packAdd_state != libssh2_NB_state_idle) {
/* fullpacket only returns LIBSSH2_ERROR_EAGAIN if
- * libssh2_packet_add returns LIBSSH2_ERROR_EAGAIN. If that
- * returns LIBSSH2_ERROR_EAGAIN but the packAdd_state is idle,
- * then the packet has been added to the brigade, but some
- * immediate action that was taken based on the packet
- * type (such as key re-exchange) is not yet complete.
- * Clear the way for a new packet to be read in.
+ * libssh2_packet_add returns LIBSSH2_ERROR_EAGAIN. If
+ * that returns LIBSSH2_ERROR_EAGAIN but the packAdd_state
+ * is idle, then the packet has been added to the brigade,
+ * but some immediate action that was taken based on the
+ * packet type (such as key re-exchange) is not yet
+ * complete. Clear the way for a new packet to be read
+ * in.
*/
session->readPack_encrypted = encrypted;
session->readPack_state = libssh2_NB_state_jump1;
@@ -607,7 +612,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
return rc;
}
- } while (1); /* loop */
+ } while(1); /* loop */
return LIBSSH2_ERROR_SOCKET_RECV; /* we never reach this point */
}
@@ -620,13 +625,13 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
ssize_t length;
struct transportpacket *p = &session->packet;
- if (!p->olen) {
+ if(!p->olen) {
*ret = 0;
return LIBSSH2_ERROR_NONE;
}
/* send as much as possible of the existing packet */
- if ((data != p->odata) || (data_len != p->olen)) {
+ if((data != p->odata) || (data_len != p->olen)) {
/* When we are about to complete the sending of a packet, it is vital
that the caller doesn't try to send a new/different packet since
we don't add this one up until the previous one has been sent. To
@@ -642,7 +647,7 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
rc = LIBSSH2_SEND(session, &p->outbuf[p->osent], length,
LIBSSH2_SOCKET_SEND_FLAGS(session));
- if (rc < 0)
+ if(rc < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d", length, -rc);
else {
@@ -653,7 +658,7 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
&p->outbuf[p->osent], rc);
}
- if (rc == length) {
+ if(rc == length) {
/* the remainder of the package was sent */
p->ototal_num = 0;
p->olen = 0;
@@ -663,9 +668,9 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
return LIBSSH2_ERROR_NONE;
}
- else if (rc < 0) {
+ else if(rc < 0) {
/* nothing was sent */
- if (rc != -EAGAIN)
+ if(rc != -EAGAIN)
/* send failure! */
return LIBSSH2_ERROR_SOCKET_SEND;
@@ -725,14 +730,14 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
*
* See the similar block in _libssh2_transport_read for more details.
*/
- if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
+ if(session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
!(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {
/* Don't write any new packets if we're still in the middle of a key
* exchange. */
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the"
" key re-exchange from _libssh2_transport_send");
rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
- if (rc)
+ if(rc)
return rc;
}
@@ -743,12 +748,12 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
/* 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!! */
rc = send_existing(session, data, data_len, &ret);
- if (rc)
+ if(rc)
return rc;
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
- if (ret)
+ if(ret)
/* set by send_existing if data was sent */
return rc;
@@ -760,7 +765,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
((session->state & LIBSSH2_STATE_AUTHENTICATED) ||
session->local.comp->use_in_auth);
- if (encrypted && compressed) {
+ if(encrypted && compressed) {
/* the idea here is that these function must fail if the output gets
larger than what fits in the assigned buffer so thus they don't
check the input size as we don't know how much it compresses */
@@ -781,7 +786,8 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
dest2_len -= dest_len;
rc = session->local.comp->comp(session,
- &p->outbuf[5+dest_len], &dest2_len,
+ &p->outbuf[5 + dest_len],
+ &dest2_len,
data2, data2_len,
&session->local.comp_abstract);
}
@@ -801,7 +807,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
/* copy the payload data */
memcpy(&p->outbuf[5], data, data_len);
if(data2 && data2_len)
- memcpy(&p->outbuf[5+data_len], data2, data2_len);
+ memcpy(&p->outbuf[5 + data_len], data2, data2_len);
data_len += data2_len; /* use the combined length */
}
@@ -825,7 +831,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
/* if the padding becomes too small we add another blocksize worth
of it (taken from the original libssh2 where it didn't have any
real explanation) */
- if (padding_length < 4) {
+ if(padding_length < 4) {
padding_length += blocksize;
}
#ifdef RANDOM_PADDING
@@ -854,7 +860,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
/* fill the padding area with random junk */
_libssh2_random(p->outbuf + 5 + data_len, padding_length);
- if (encrypted) {
+ if(encrypted) {
size_t i;
/* Calculate MAC hash. Put the output at index packet_length,
@@ -870,7 +876,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
The MAC field is not encrypted. */
for(i = 0; i < packet_length; i += session->local.crypt->blocksize) {
unsigned char *ptr = &p->outbuf[i];
- if (session->local.crypt->crypt(session, ptr,
+ if(session->local.crypt->crypt(session, ptr,
session->local.crypt->blocksize,
&session->local.crypt_abstract))
return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */
@@ -881,7 +887,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
ret = LIBSSH2_SEND(session, p->outbuf, total_length,
LIBSSH2_SOCKET_SEND_FLAGS(session));
- if (ret < 0)
+ if(ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
"Error sending %d bytes: %d", total_length, -ret);
else {
@@ -890,8 +896,8 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);
}
- if (ret != total_length) {
- if (ret >= 0 || ret == -EAGAIN) {
+ if(ret != total_length) {
+ if(ret >= 0 || ret == -EAGAIN) {
/* the whole packet could not be sent, save the rest */
session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;
p->odata = orgdata;
diff --git a/libs/libssh2/src/userauth.c b/libs/libssh2/src/userauth.c
index c02d81d0ea..949dc1c660 100644
--- a/libs/libssh2/src/userauth.c
+++ b/libs/libssh2/src/userauth.c
@@ -71,7 +71,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
unsigned char *s;
int rc;
- if (session->userauth_list_state == libssh2_NB_state_idle) {
+ if(session->userauth_list_state == libssh2_NB_state_idle) {
/* Zero the whole thing out */
memset(&session->userauth_list_packet_requirev_state, 0,
sizeof(session->userauth_list_packet_requirev_state));
@@ -80,7 +80,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
s = session->userauth_list_data =
LIBSSH2_ALLOC(session, session->userauth_list_data_len);
- if (!session->userauth_list_data) {
+ if(!session->userauth_list_data) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for userauth_list");
return NULL;
@@ -94,11 +94,11 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
session->userauth_list_state = libssh2_NB_state_created;
}
- if (session->userauth_list_state == libssh2_NB_state_created) {
+ if(session->userauth_list_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, session->userauth_list_data,
session->userauth_list_data_len,
(unsigned char *)"none", 4);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting userauth list");
return NULL;
@@ -107,7 +107,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
LIBSSH2_FREE(session, session->userauth_list_data);
session->userauth_list_data = NULL;
- if (rc) {
+ if(rc) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-none request");
session->userauth_list_state = libssh2_NB_state_idle;
@@ -117,23 +117,24 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
session->userauth_list_state = libssh2_NB_state_sent;
}
- if (session->userauth_list_state == libssh2_NB_state_sent) {
+ if(session->userauth_list_state == libssh2_NB_state_sent) {
rc = _libssh2_packet_requirev(session, reply_codes,
&session->userauth_list_data,
&session->userauth_list_data_len, 0,
NULL, 0,
- &session->userauth_list_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ &session->userauth_list_packet_requirev_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting userauth list");
return NULL;
- } else if (rc || (session->userauth_list_data_len < 1)) {
+ }
+ else if(rc || (session->userauth_list_data_len < 1)) {
_libssh2_error(session, rc, "Failed getting response");
session->userauth_list_state = libssh2_NB_state_idle;
return NULL;
}
- if (session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+ if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
/* Wow, who'dve thought... */
_libssh2_error(session, LIBSSH2_ERROR_NONE, "No error");
LIBSSH2_FREE(session, session->userauth_list_data);
@@ -143,7 +144,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
return NULL;
}
- if(session->userauth_list_data_len < 5) {
+ if(session->userauth_list_data_len < 5) {
LIBSSH2_FREE(session, session->userauth_list_data);
session->userauth_list_data = NULL;
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
@@ -157,6 +158,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
"Unexpected userauth list size");
return NULL;
}
+
/* Do note that the memory areas overlap! */
memmove(session->userauth_list_data, session->userauth_list_data + 5,
methods_len);
@@ -217,7 +219,7 @@ userauth_password(LIBSSH2_SESSION *session,
};
int rc;
- if (session->userauth_pswd_state == libssh2_NB_state_idle) {
+ if(session->userauth_pswd_state == libssh2_NB_state_idle) {
/* Zero the whole thing out */
memset(&session->userauth_pswd_packet_requirev_state, 0,
sizeof(session->userauth_pswd_packet_requirev_state));
@@ -235,7 +237,7 @@ userauth_password(LIBSSH2_SESSION *session,
struct */
s = session->userauth_pswd_data =
LIBSSH2_ALLOC(session, session->userauth_pswd_data_len);
- if (!session->userauth_pswd_data) {
+ if(!session->userauth_pswd_data) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"userauth-password request");
@@ -255,11 +257,11 @@ userauth_password(LIBSSH2_SESSION *session,
session->userauth_pswd_state = libssh2_NB_state_created;
}
- if (session->userauth_pswd_state == libssh2_NB_state_created) {
+ if(session->userauth_pswd_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, session->userauth_pswd_data,
session->userauth_pswd_data_len,
password, password_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block writing password request");
}
@@ -268,7 +270,7 @@ userauth_password(LIBSSH2_SESSION *session,
LIBSSH2_FREE(session, session->userauth_pswd_data);
session->userauth_pswd_data = NULL;
- if (rc) {
+ if(rc) {
session->userauth_pswd_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-password request");
@@ -279,10 +281,10 @@ userauth_password(LIBSSH2_SESSION *session,
password_response:
- if ((session->userauth_pswd_state == libssh2_NB_state_sent)
+ if((session->userauth_pswd_state == libssh2_NB_state_sent)
|| (session->userauth_pswd_state == libssh2_NB_state_sent1)
|| (session->userauth_pswd_state == libssh2_NB_state_sent2)) {
- if (session->userauth_pswd_state == libssh2_NB_state_sent) {
+ if(session->userauth_pswd_state == libssh2_NB_state_sent) {
rc = _libssh2_packet_requirev(session, reply_codes,
&session->userauth_pswd_data,
&session->userauth_pswd_data_len,
@@ -290,8 +292,8 @@ userauth_password(LIBSSH2_SESSION *session,
&session->
userauth_pswd_packet_requirev_state);
- if (rc) {
- if (rc != LIBSSH2_ERROR_EAGAIN)
+ if(rc) {
+ if(rc != LIBSSH2_ERROR_EAGAIN)
session->userauth_pswd_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
@@ -303,7 +305,7 @@ userauth_password(LIBSSH2_SESSION *session,
"Unexpected packet size");
}
- if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+ if(session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Password authentication successful");
LIBSSH2_FREE(session, session->userauth_pswd_data);
@@ -311,7 +313,9 @@ userauth_password(LIBSSH2_SESSION *session,
session->state |= LIBSSH2_STATE_AUTHENTICATED;
session->userauth_pswd_state = libssh2_NB_state_idle;
return 0;
- } else if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
+ }
+ else if(session->userauth_pswd_data[0] ==
+ SSH_MSG_USERAUTH_FAILURE) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Password authentication failed");
LIBSSH2_FREE(session, session->userauth_pswd_data);
@@ -335,41 +339,48 @@ userauth_password(LIBSSH2_SESSION *session,
"Unexpected packet size");
}
- if ((session->userauth_pswd_data[0] ==
+ if((session->userauth_pswd_data[0] ==
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)
|| (session->userauth_pswd_data0 ==
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)) {
session->userauth_pswd_data0 = SSH_MSG_USERAUTH_PASSWD_CHANGEREQ;
- if ((session->userauth_pswd_state == libssh2_NB_state_sent1) ||
+ if((session->userauth_pswd_state == libssh2_NB_state_sent1) ||
(session->userauth_pswd_state == libssh2_NB_state_sent2)) {
- if (session->userauth_pswd_state == libssh2_NB_state_sent1) {
+ if(session->userauth_pswd_state == libssh2_NB_state_sent1) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Password change required");
LIBSSH2_FREE(session, session->userauth_pswd_data);
session->userauth_pswd_data = NULL;
}
- if (passwd_change_cb) {
- if (session->userauth_pswd_state == libssh2_NB_state_sent1) {
+ if(passwd_change_cb) {
+ if(session->userauth_pswd_state ==
+ libssh2_NB_state_sent1) {
passwd_change_cb(session,
&session->userauth_pswd_newpw,
&session->userauth_pswd_newpw_len,
&session->abstract);
- if (!session->userauth_pswd_newpw) {
+ if(!session->userauth_pswd_newpw) {
return _libssh2_error(session,
- LIBSSH2_ERROR_PASSWORD_EXPIRED,
+ LIBSSH2_ERROR_PASSWORD_EXPIRED,
"Password expired, and "
"callback failed");
}
/* basic data_len + newpw_len(4) */
- session->userauth_pswd_data_len =
- username_len + password_len + 44;
+ if(username_len + password_len + 44 <= UINT_MAX) {
+ session->userauth_pswd_data_len =
+ username_len + password_len + 44;
+ s = session->userauth_pswd_data =
+ LIBSSH2_ALLOC(session,
+ session->userauth_pswd_data_len);
+ }
+ else {
+ s = session->userauth_pswd_data = NULL;
+ session->userauth_pswd_data_len = 0;
+ }
- s = session->userauth_pswd_data =
- LIBSSH2_ALLOC(session,
- session->userauth_pswd_data_len);
- if (!session->userauth_pswd_data) {
+ if(!session->userauth_pswd_data) {
LIBSSH2_FREE(session,
session->userauth_pswd_newpw);
session->userauth_pswd_newpw = NULL;
@@ -394,15 +405,17 @@ userauth_password(LIBSSH2_SESSION *session,
session->userauth_pswd_state = libssh2_NB_state_sent2;
}
- if (session->userauth_pswd_state == libssh2_NB_state_sent2) {
+ if(session->userauth_pswd_state ==
+ libssh2_NB_state_sent2) {
rc = _libssh2_transport_send(session,
- session->userauth_pswd_data,
- session->userauth_pswd_data_len,
- (unsigned char *)
- session->userauth_pswd_newpw,
- session->userauth_pswd_newpw_len);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+ session->userauth_pswd_data,
+ session->userauth_pswd_data_len,
+ (unsigned char *)
+ session->userauth_pswd_newpw,
+ session->userauth_pswd_newpw_len);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return _libssh2_error(session,
+ LIBSSH2_ERROR_EAGAIN,
"Would block waiting");
}
@@ -412,7 +425,7 @@ userauth_password(LIBSSH2_SESSION *session,
LIBSSH2_FREE(session, session->userauth_pswd_newpw);
session->userauth_pswd_newpw = NULL;
- if (rc) {
+ if(rc) {
return _libssh2_error(session,
LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth "
@@ -427,7 +440,8 @@ userauth_password(LIBSSH2_SESSION *session,
goto password_response;
}
}
- } else {
+ }
+ else {
session->userauth_pswd_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED,
"Password Expired, and no callback "
@@ -455,7 +469,8 @@ LIBSSH2_API int
libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username,
unsigned int username_len, const char *password,
unsigned int password_len,
- LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
+ LIBSSH2_PASSWD_CHANGEREQ_FUNC
+ ((*passwd_change_cb)))
{
int rc;
BLOCK_ADJUST(rc, session,
@@ -477,13 +492,13 @@ memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
size_t pubkey_len = pubkeyfiledata_len;
unsigned int tmp_len;
- if (pubkeyfiledata_len <= 1) {
+ if(pubkeyfiledata_len <= 1) {
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Invalid data in public key file");
}
pubkey = LIBSSH2_ALLOC(session, pubkeyfiledata_len);
- if (!pubkey) {
+ if(!pubkey) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for public key data");
}
@@ -493,16 +508,17 @@ memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
/*
* Remove trailing whitespace
*/
- while (pubkey_len && isspace(pubkey[pubkey_len - 1]))
+ while(pubkey_len && isspace(pubkey[pubkey_len - 1]))
pubkey_len--;
- if (!pubkey_len) {
+ if(!pubkey_len) {
LIBSSH2_FREE(session, pubkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Missing public key data");
}
- if ((sp1 = memchr(pubkey, ' ', pubkey_len)) == NULL) {
+ sp1 = memchr(pubkey, ' ', pubkey_len);
+ if(sp1 == NULL) {
LIBSSH2_FREE(session, pubkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Invalid public key data");
@@ -510,12 +526,13 @@ memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
sp1++;
- if ((sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey - 1))) == NULL) {
+ sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey));
+ if(sp2 == NULL) {
/* Assume that the id string is missing, but that it's okay */
sp2 = pubkey + pubkey_len;
}
- if (libssh2_base64_decode(session, (char **) &tmp, &tmp_len,
+ if(libssh2_base64_decode(session, (char **) &tmp, &tmp_len,
(char *) sp1, sp2 - sp1)) {
LIBSSH2_FREE(session, pubkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
@@ -561,29 +578,29 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
_libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading public key file: %s",
pubkeyfile);
/* Read Public Key */
- fd = fopen(pubkeyfile, "r");
- if (!fd) {
+ fd = fopen(pubkeyfile, FOPEN_READTEXT);
+ if(!fd) {
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Unable to open public key file");
}
- while (!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') {
+ while(!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') {
pubkey_len++;
}
rewind(fd);
- if (pubkey_len <= 1) {
+ if(pubkey_len <= 1) {
fclose(fd);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Invalid data in public key file");
}
pubkey = LIBSSH2_ALLOC(session, pubkey_len);
- if (!pubkey) {
+ if(!pubkey) {
fclose(fd);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for public key data");
}
- if (fread(pubkey, 1, pubkey_len, fd) != pubkey_len) {
+ if(fread(pubkey, 1, pubkey_len, fd) != pubkey_len) {
LIBSSH2_FREE(session, pubkey);
fclose(fd);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
@@ -593,17 +610,18 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
/*
* Remove trailing whitespace
*/
- while (pubkey_len && isspace(pubkey[pubkey_len - 1])) {
+ while(pubkey_len && isspace(pubkey[pubkey_len - 1])) {
pubkey_len--;
}
- if (!pubkey_len) {
+ if(!pubkey_len) {
LIBSSH2_FREE(session, pubkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Missing public key data");
}
- if ((sp1 = memchr(pubkey, ' ', pubkey_len)) == NULL) {
+ sp1 = memchr(pubkey, ' ', pubkey_len);
+ if(sp1 == NULL) {
LIBSSH2_FREE(session, pubkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Invalid public key data");
@@ -612,12 +630,13 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
sp1++;
sp_len = sp1 > pubkey ? (sp1 - pubkey) - 1 : 0;
- if ((sp2 = memchr(sp1, ' ', pubkey_len - sp_len)) == NULL) {
+ sp2 = memchr(sp1, ' ', pubkey_len - sp_len);
+ if(sp2 == NULL) {
/* Assume that the id string is missing, but that it's okay */
sp2 = pubkey + pubkey_len;
}
- if (libssh2_base64_decode(session, (char **) &tmp, &tmp_len,
+ if(libssh2_base64_decode(session, (char **) &tmp, &tmp_len,
(char *) sp1, sp2 - sp1)) {
LIBSSH2_FREE(session, pubkey);
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
@@ -649,8 +668,8 @@ memory_read_privatekey(LIBSSH2_SESSION * session,
*hostkey_method = NULL;
*hostkey_abstract = NULL;
- while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
- if ((*hostkey_methods_avail)->initPEMFromMemory
+ while(*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
+ if((*hostkey_methods_avail)->initPEMFromMemory
&& strncmp((*hostkey_methods_avail)->name, (const char *) method,
method_len) == 0) {
*hostkey_method = *hostkey_methods_avail;
@@ -658,12 +677,12 @@ memory_read_privatekey(LIBSSH2_SESSION * session,
}
hostkey_methods_avail++;
}
- if (!*hostkey_method) {
+ if(!*hostkey_method) {
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
"No handler for specified private key");
}
- if ((*hostkey_method)->
+ if((*hostkey_method)->
initPEMFromMemory(session, privkeyfiledata, privkeyfiledata_len,
(unsigned char *) passphrase,
hostkey_abstract)) {
@@ -691,8 +710,8 @@ file_read_privatekey(LIBSSH2_SESSION * session,
privkeyfile);
*hostkey_method = NULL;
*hostkey_abstract = NULL;
- while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
- if ((*hostkey_methods_avail)->initPEM
+ while(*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
+ if((*hostkey_methods_avail)->initPEM
&& strncmp((*hostkey_methods_avail)->name, (const char *) method,
method_len) == 0) {
*hostkey_method = *hostkey_methods_avail;
@@ -700,12 +719,12 @@ file_read_privatekey(LIBSSH2_SESSION * session,
}
hostkey_methods_avail++;
}
- if (!*hostkey_method) {
+ if(!*hostkey_method) {
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
"No handler for specified private key");
}
- if ((*hostkey_method)->
+ if((*hostkey_method)->
initPEM(session, privkeyfile, (unsigned char *) passphrase,
hostkey_abstract)) {
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
@@ -743,15 +762,15 @@ sign_frommemory(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
datavec.iov_base = (void *)data;
datavec.iov_len = data_len;
- if (privkeyobj->signv(session, sig, sig_len, 1, &datavec,
+ if(privkeyobj->signv(session, sig, sig_len, 1, &datavec,
&hostkey_abstract)) {
- if (privkeyobj->dtor) {
- privkeyobj->dtor(session, abstract);
+ if(privkeyobj->dtor) {
+ privkeyobj->dtor(session, &hostkey_abstract);
}
return -1;
}
- if (privkeyobj->dtor) {
+ if(privkeyobj->dtor) {
privkeyobj->dtor(session, &hostkey_abstract);
}
return 0;
@@ -779,15 +798,15 @@ sign_fromfile(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
datavec.iov_base = (void *)data;
datavec.iov_len = data_len;
- if (privkeyobj->signv(session, sig, sig_len, 1, &datavec,
+ if(privkeyobj->signv(session, sig, sig_len, 1, &datavec,
&hostkey_abstract)) {
- if (privkeyobj->dtor) {
+ if(privkeyobj->dtor) {
privkeyobj->dtor(session, &hostkey_abstract);
}
return -1;
}
- if (privkeyobj->dtor) {
+ if(privkeyobj->dtor) {
privkeyobj->dtor(session, &hostkey_abstract);
}
return 0;
@@ -809,9 +828,15 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
{
int rc;
- if (session->userauth_host_state == libssh2_NB_state_idle) {
+#if !LIBSSH2_RSA
+ return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+ "RSA is not supported by crypto backend");
+#endif
+
+ if(session->userauth_host_state == libssh2_NB_state_idle) {
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
- unsigned char *pubkeydata, *sig = NULL;
+ unsigned char *pubkeydata = NULL;
+ unsigned char *sig = NULL;
size_t pubkeydata_len = 0;
size_t sig_len = 0;
void *abstract;
@@ -822,7 +847,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
memset(&session->userauth_host_packet_requirev_state, 0,
sizeof(session->userauth_host_packet_requirev_state));
- if (publickey) {
+ if(publickey) {
rc = file_read_publickey(session, &session->userauth_host_method,
&session->userauth_host_method_len,
&pubkeydata, &pubkeydata_len, publickey);
@@ -837,7 +862,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
&session->userauth_host_method_len,
&pubkeydata, &pubkeydata_len,
privatekey, passphrase);
- if (rc)
+ if(rc)
/* libssh2_pub_priv_keyfile calls _libssh2_error() */
return rc;
}
@@ -862,7 +887,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
session->userauth_host_packet_len + 4 +
(4 + session->userauth_host_method_len) +
(4 + pubkeydata_len));
- if (!session->userauth_host_packet) {
+ if(!session->userauth_host_packet) {
LIBSSH2_FREE(session, session->userauth_host_method);
session->userauth_host_method = NULL;
LIBSSH2_FREE(session, pubkeydata);
@@ -906,31 +931,31 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
datavec[2].iov_base = (void *)session->userauth_host_packet;
datavec[2].iov_len = session->userauth_host_packet_len;
- if (privkeyobj && privkeyobj->signv &&
+ if(privkeyobj && privkeyobj->signv &&
privkeyobj->signv(session, &sig, &sig_len, 3,
datavec, &abstract)) {
LIBSSH2_FREE(session, session->userauth_host_method);
session->userauth_host_method = NULL;
LIBSSH2_FREE(session, session->userauth_host_packet);
session->userauth_host_packet = NULL;
- if (privkeyobj->dtor) {
+ if(privkeyobj->dtor) {
privkeyobj->dtor(session, &abstract);
}
return -1;
}
- if (privkeyobj && privkeyobj->dtor) {
+ if(privkeyobj && privkeyobj->dtor) {
privkeyobj->dtor(session, &abstract);
}
- if (sig_len > pubkeydata_len) {
+ if(sig_len > pubkeydata_len) {
unsigned char *newpacket;
/* Should *NEVER* happen, but...well.. better safe than sorry */
newpacket = LIBSSH2_REALLOC(session, session->userauth_host_packet,
session->userauth_host_packet_len + 4 +
(4 + session->userauth_host_method_len)
+ (4 + sig_len)); /* PK sigblob */
- if (!newpacket) {
+ if(!newpacket) {
LIBSSH2_FREE(session, sig);
LIBSSH2_FREE(session, session->userauth_host_packet);
session->userauth_host_packet = NULL;
@@ -947,7 +972,8 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
session->userauth_host_packet + session->userauth_host_packet_len;
_libssh2_store_u32(&session->userauth_host_s,
- 4 + session->userauth_host_method_len + 4 + sig_len);
+ 4 + session->userauth_host_method_len +
+ 4 + sig_len);
_libssh2_store_str(&session->userauth_host_s,
(const char *)session->userauth_host_method,
session->userauth_host_method_len);
@@ -964,15 +990,16 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
session->userauth_host_state = libssh2_NB_state_created;
}
- if (session->userauth_host_state == libssh2_NB_state_created) {
+ if(session->userauth_host_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, session->userauth_host_packet,
session->userauth_host_s -
session->userauth_host_packet,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+ "Would block");
}
- else if (rc) {
+ else if(rc) {
LIBSSH2_FREE(session, session->userauth_host_packet);
session->userauth_host_packet = NULL;
session->userauth_host_state = libssh2_NB_state_idle;
@@ -985,7 +1012,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
session->userauth_host_state = libssh2_NB_state_sent;
}
- if (session->userauth_host_state == libssh2_NB_state_sent) {
+ if(session->userauth_host_state == libssh2_NB_state_sent) {
static const unsigned char reply_codes[3] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
size_t data_len;
@@ -994,17 +1021,18 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
&data_len, 0, NULL, 0,
&session->
userauth_host_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+ "Would block");
}
session->userauth_host_state = libssh2_NB_state_idle;
- if (rc || data_len < 1) {
+ if(rc || data_len < 1) {
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Auth failed");
}
- if (session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+ if(session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Hostbased authentication successful");
/* We are us and we've proved it. */
@@ -1055,7 +1083,8 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
unsigned int username_len,
const unsigned char *pubkeydata,
unsigned long pubkeydata_len,
- LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
+ LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC
+ ((*sign_callback)),
void *abstract)
{
unsigned char reply_codes[4] =
@@ -1065,13 +1094,13 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
int rc;
unsigned char *s;
- if (session->userauth_pblc_state == libssh2_NB_state_idle) {
+ if(session->userauth_pblc_state == libssh2_NB_state_idle) {
/*
* The call to _libssh2_ntohu32 later relies on pubkeydata having at
* least 4 valid bytes containing the length of the method name.
*/
- if (pubkeydata_len < 4)
+ if(pubkeydata_len < 4)
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Invalid public key, too short");
@@ -1085,10 +1114,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
* allocation/free.
* For other uses, we allocate and populate it here.
*/
- if (!session->userauth_pblc_method) {
+ if(!session->userauth_pblc_method) {
session->userauth_pblc_method_len = _libssh2_ntohu32(pubkeydata);
- if(session->userauth_pblc_method_len > pubkeydata_len)
+ if(session->userauth_pblc_method_len > pubkeydata_len - 4)
/* the method length simply cannot be longer than the entire
passed in data, so we use this to detect crazy input
data */
@@ -1098,10 +1127,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_method =
LIBSSH2_ALLOC(session, session->userauth_pblc_method_len);
- if (!session->userauth_pblc_method) {
+ if(!session->userauth_pblc_method) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
- "Unable to allocate memory for public key "
- "data");
+ "Unable to allocate memory "
+ "for public key data");
}
memcpy(session->userauth_pblc_method, pubkeydata + 4,
session->userauth_pblc_method_len);
@@ -1111,7 +1140,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
* file must match length embedded in the key.
* TODO: The data should match too but we don't check that. Should we?
*/
- else if (session->userauth_pblc_method_len !=
+ else if(session->userauth_pblc_method_len !=
_libssh2_ntohu32(pubkeydata))
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Invalid public key");
@@ -1140,7 +1169,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_packet_len + 4 +
(4 + session->userauth_pblc_method_len)
+ (4 + pubkeydata_len));
- if (!session->userauth_pblc_packet) {
+ if(!session->userauth_pblc_packet) {
LIBSSH2_FREE(session, session->userauth_pblc_method);
session->userauth_pblc_method = NULL;
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
@@ -1166,13 +1195,14 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_state = libssh2_NB_state_created;
}
- if (session->userauth_pblc_state == libssh2_NB_state_created) {
+ if(session->userauth_pblc_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, session->userauth_pblc_packet,
session->userauth_pblc_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN)
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
- else if (rc) {
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+ "Would block");
+ else if(rc) {
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
LIBSSH2_FREE(session, session->userauth_pblc_method);
@@ -1185,17 +1215,18 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_state = libssh2_NB_state_sent;
}
- if (session->userauth_pblc_state == libssh2_NB_state_sent) {
+ if(session->userauth_pblc_state == libssh2_NB_state_sent) {
rc = _libssh2_packet_requirev(session, reply_codes,
&session->userauth_pblc_data,
&session->userauth_pblc_data_len, 0,
NULL, 0,
&session->
userauth_pblc_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+ "Would block");
}
- else if (rc || (session->userauth_pblc_data_len < 1)) {
+ else if(rc || (session->userauth_pblc_data_len < 1)) {
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
LIBSSH2_FREE(session, session->userauth_pblc_method);
@@ -1205,7 +1236,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
"Waiting for USERAUTH response");
}
- if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+ if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Pubkey authentication prematurely successful");
/*
@@ -1223,7 +1254,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
return 0;
}
- if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_FAILURE) {
+ if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_FAILURE) {
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, session->userauth_pblc_data);
session->userauth_pblc_data = NULL;
@@ -1244,14 +1275,14 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_state = libssh2_NB_state_sent1;
}
- if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
+ if(session->userauth_pblc_state == libssh2_NB_state_sent1) {
unsigned char *buf;
unsigned char *sig;
size_t sig_len;
s = buf = LIBSSH2_ALLOC(session, 4 + session->session_id_len
+ session->userauth_pblc_packet_len);
- if (!buf) {
+ if(!buf) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"userauth-publickey signed data");
@@ -1260,15 +1291,17 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
_libssh2_store_str(&s, (const char *)session->session_id,
session->session_id_len);
- memcpy (s, session->userauth_pblc_packet,
- session->userauth_pblc_packet_len);
+ memcpy(s, session->userauth_pblc_packet,
+ session->userauth_pblc_packet_len);
s += session->userauth_pblc_packet_len;
rc = sign_callback(session, &sig, &sig_len, buf, s - buf, abstract);
LIBSSH2_FREE(session, buf);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
- } else if (rc) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+ "Would block");
+ }
+ else if(rc) {
LIBSSH2_FREE(session, session->userauth_pblc_method);
session->userauth_pblc_method = NULL;
LIBSSH2_FREE(session, session->userauth_pblc_packet);
@@ -1282,7 +1315,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
* If this function was restarted, pubkeydata_len might still be 0
* which will cause an unnecessary but harmless realloc here.
*/
- if (sig_len > pubkeydata_len) {
+ if(sig_len > pubkeydata_len) {
unsigned char *newpacket;
/* Should *NEVER* happen, but...well.. better safe than sorry */
newpacket = LIBSSH2_REALLOC(session,
@@ -1290,7 +1323,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_packet_len + 4 +
(4 + session->userauth_pblc_method_len)
+ (4 + sig_len)); /* PK sigblob */
- if (!newpacket) {
+ if(!newpacket) {
LIBSSH2_FREE(session, sig);
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
@@ -1308,7 +1341,8 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_b = NULL;
_libssh2_store_u32(&s,
- 4 + session->userauth_pblc_method_len + 4 + sig_len);
+ 4 + session->userauth_pblc_method_len + 4 +
+ sig_len);
_libssh2_store_str(&s, (const char *)session->userauth_pblc_method,
session->userauth_pblc_method_len);
@@ -1325,14 +1359,16 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_state = libssh2_NB_state_sent2;
}
- if (session->userauth_pblc_state == libssh2_NB_state_sent2) {
+ if(session->userauth_pblc_state == libssh2_NB_state_sent2) {
rc = _libssh2_transport_send(session, session->userauth_pblc_packet,
session->userauth_pblc_s -
session->userauth_pblc_packet,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
- } else if (rc) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+ "Would block");
+ }
+ else if(rc) {
LIBSSH2_FREE(session, session->userauth_pblc_packet);
session->userauth_pblc_packet = NULL;
session->userauth_pblc_state = libssh2_NB_state_idle;
@@ -1349,19 +1385,20 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
reply_codes[2] = 0;
rc = _libssh2_packet_requirev(session, reply_codes,
- &session->userauth_pblc_data,
- &session->userauth_pblc_data_len, 0, NULL, 0,
- &session->userauth_pblc_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ &session->userauth_pblc_data,
+ &session->userauth_pblc_data_len, 0, NULL, 0,
+ &session->userauth_pblc_packet_requirev_state);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting userauth list");
- } else if (rc || session->userauth_pblc_data_len < 1) {
+ }
+ else if(rc || session->userauth_pblc_data_len < 1) {
session->userauth_pblc_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
"Waiting for publickey USERAUTH response");
}
- if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+ if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Publickey authentication successful");
/* We are us and we've proved it. */
@@ -1401,11 +1438,16 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session,
void *abstract = &privkey_file;
int rc;
+#if !LIBSSH2_RSA
+ return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+ "RSA is not supported by crypto backend");
+#endif
+
privkey_file.filename = privatekeydata;
privkey_file.passphrase = passphrase;
- if (session->userauth_pblc_state == libssh2_NB_state_idle) {
- if (publickeydata_len && publickeydata) {
+ if(session->userauth_pblc_state == libssh2_NB_state_idle) {
+ if(publickeydata_len && publickeydata) {
rc = memory_read_publickey(session, &session->userauth_pblc_method,
&session->userauth_pblc_method_len,
&pubkeydata, &pubkeydata_len,
@@ -1413,14 +1455,14 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session,
if(rc)
return rc;
}
- else if (privatekeydata_len && privatekeydata) {
+ else if(privatekeydata_len && privatekeydata) {
/* Compute public key from private key. */
- if (_libssh2_pub_priv_keyfilememory(session,
- &session->userauth_pblc_method,
- &session->userauth_pblc_method_len,
- &pubkeydata, &pubkeydata_len,
- privatekeydata, privatekeydata_len,
- passphrase))
+ if(_libssh2_pub_priv_keyfilememory(session,
+ &session->userauth_pblc_method,
+ &session->userauth_pblc_method_len,
+ &pubkeydata, &pubkeydata_len,
+ privatekeydata, privatekeydata_len,
+ passphrase))
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Unable to extract public key "
"from private key.");
@@ -1458,15 +1500,20 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
void *abstract = &privkey_file;
int rc;
+#if !LIBSSH2_RSA
+ return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+ "RSA is not supported by crypto backend");
+#endif
+
privkey_file.filename = privatekey;
privkey_file.passphrase = passphrase;
- if (session->userauth_pblc_state == libssh2_NB_state_idle) {
- if (publickey) {
+ if(session->userauth_pblc_state == libssh2_NB_state_idle) {
+ if(publickey) {
rc = file_read_publickey(session, &session->userauth_pblc_method,
&session->userauth_pblc_method_len,
- &pubkeydata, &pubkeydata_len,publickey);
- if (rc)
+ &pubkeydata, &pubkeydata_len, publickey);
+ if(rc)
return rc;
}
else {
@@ -1478,7 +1525,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
privatekey, passphrase);
/* _libssh2_pub_priv_keyfile calls _libssh2_error() */
- if (rc)
+ if(rc)
return rc;
}
}
@@ -1510,7 +1557,7 @@ libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION *session,
if(NULL == passphrase)
/* if given a NULL pointer, make it point to a zero-length
string to save us from having to check this all over */
- passphrase="";
+ passphrase = "";
BLOCK_ADJUST(rc, session,
userauth_publickey_frommemory(session, user, user_len,
@@ -1538,7 +1585,7 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
if(NULL == passphrase)
/* if given a NULL pointer, make it point to a zero-length
string to save us from having to check this all over */
- passphrase="";
+ passphrase = "";
BLOCK_ADJUST(rc, session,
userauth_publickey_fromfile(session, user, user_len,
@@ -1555,7 +1602,8 @@ libssh2_userauth_publickey(LIBSSH2_SESSION *session,
const char *user,
const unsigned char *pubkeydata,
size_t pubkeydata_len,
- LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
+ LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC
+ ((*sign_callback)),
void **abstract)
{
int rc;
@@ -1581,7 +1629,8 @@ static int
userauth_keyboard_interactive(LIBSSH2_SESSION * session,
const char *username,
unsigned int username_len,
- LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)))
+ LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC
+ ((*response_callback)))
{
unsigned char *s;
int rc;
@@ -1593,7 +1642,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
unsigned int language_tag_len;
unsigned int i;
- if (session->userauth_kybd_state == libssh2_NB_state_idle) {
+ if(session->userauth_kybd_state == libssh2_NB_state_idle) {
session->userauth_kybd_auth_name = NULL;
session->userauth_kybd_auth_instruction = NULL;
session->userauth_kybd_num_prompts = 0;
@@ -1618,7 +1667,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
session->userauth_kybd_data = s =
LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
- if (!s) {
+ if(!s) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"keyboard-interactive authentication");
@@ -1647,18 +1696,21 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
session->userauth_kybd_state = libssh2_NB_state_created;
}
- if (session->userauth_kybd_state == libssh2_NB_state_created) {
+ if(session->userauth_kybd_state == libssh2_NB_state_created) {
rc = _libssh2_transport_send(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
- } else if (rc) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
+ "Would block");
+ }
+ else if(rc) {
LIBSSH2_FREE(session, session->userauth_kybd_data);
session->userauth_kybd_data = NULL;
session->userauth_kybd_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
- "Unable to send keyboard-interactive request");
+ "Unable to send keyboard-interactive"
+ " request");
}
LIBSSH2_FREE(session, session->userauth_kybd_data);
session->userauth_kybd_data = NULL;
@@ -1667,26 +1719,29 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
}
for(;;) {
- if (session->userauth_kybd_state == libssh2_NB_state_sent) {
+ if(session->userauth_kybd_state == libssh2_NB_state_sent) {
rc = _libssh2_packet_requirev(session, reply_codes,
&session->userauth_kybd_data,
&session->userauth_kybd_data_len,
0, NULL, 0,
&session->
userauth_kybd_packet_requirev_state);
- if (rc == LIBSSH2_ERROR_EAGAIN) {
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block");
- } else if (rc || session->userauth_kybd_data_len < 1) {
+ }
+ else if(rc || session->userauth_kybd_data_len < 1) {
session->userauth_kybd_state = libssh2_NB_state_idle;
return _libssh2_error(session,
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
- "Waiting for keyboard USERAUTH response");
+ "Waiting for keyboard "
+ "USERAUTH response");
}
- if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
+ if(session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
- "Keyboard-interactive authentication successful");
+ "Keyboard-interactive "
+ "authentication successful");
LIBSSH2_FREE(session, session->userauth_kybd_data);
session->userauth_kybd_data = NULL;
session->state |= LIBSSH2_STATE_AUTHENTICATED;
@@ -1694,7 +1749,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
return 0;
}
- if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
+ if(session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Keyboard-interactive authentication failed");
LIBSSH2_FREE(session, session->userauth_kybd_data);
@@ -1709,60 +1764,127 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
/* server requested PAM-like conversation */
s = session->userauth_kybd_data + 1;
- /* string name (ISO-10646 UTF-8) */
- session->userauth_kybd_auth_name_len = _libssh2_ntohu32(s);
- s += 4;
+ if(session->userauth_kybd_data_len >= 5) {
+ /* string name (ISO-10646 UTF-8) */
+ session->userauth_kybd_auth_name_len = _libssh2_ntohu32(s);
+ s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too small"
+ "to get length");
+ goto cleanup;
+ }
+
if(session->userauth_kybd_auth_name_len) {
session->userauth_kybd_auth_name =
LIBSSH2_ALLOC(session,
session->userauth_kybd_auth_name_len);
- if (!session->userauth_kybd_auth_name) {
+ if(!session->userauth_kybd_auth_name) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"keyboard-interactive 'name' "
"request field");
goto cleanup;
}
- memcpy(session->userauth_kybd_auth_name, s,
- session->userauth_kybd_auth_name_len);
- s += session->userauth_kybd_auth_name_len;
+ if(s + session->userauth_list_data_len <=
+ session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ memcpy(session->userauth_kybd_auth_name, s,
+ session->userauth_kybd_auth_name_len);
+ s += session->userauth_kybd_auth_name_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too small"
+ "for auth name");
+ goto cleanup;
+ }
+ }
+
+ if(s + 4 <= session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ /* string instruction (ISO-10646 UTF-8) */
+ session->userauth_kybd_auth_instruction_len =
+ _libssh2_ntohu32(s);
+ s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too small"
+ "for auth instruction length");
+ goto cleanup;
}
- /* string instruction (ISO-10646 UTF-8) */
- session->userauth_kybd_auth_instruction_len = _libssh2_ntohu32(s);
- s += 4;
if(session->userauth_kybd_auth_instruction_len) {
session->userauth_kybd_auth_instruction =
LIBSSH2_ALLOC(session,
session->userauth_kybd_auth_instruction_len);
- if (!session->userauth_kybd_auth_instruction) {
+ if(!session->userauth_kybd_auth_instruction) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"keyboard-interactive 'instruction' "
"request field");
goto cleanup;
}
- memcpy(session->userauth_kybd_auth_instruction, s,
- session->userauth_kybd_auth_instruction_len);
- s += session->userauth_kybd_auth_instruction_len;
+ if(s + session->userauth_kybd_auth_instruction_len <=
+ session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ memcpy(session->userauth_kybd_auth_instruction, s,
+ session->userauth_kybd_auth_instruction_len);
+ s += session->userauth_kybd_auth_instruction_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too small"
+ "for auth instruction");
+ goto cleanup;
+ }
}
- /* string language tag (as defined in [RFC-3066]) */
- language_tag_len = _libssh2_ntohu32(s);
- s += 4;
-
- /* ignoring this field as deprecated */
- s += language_tag_len;
-
- /* int num-prompts */
- session->userauth_kybd_num_prompts = _libssh2_ntohu32(s);
- s += 4;
- if(session->userauth_kybd_num_prompts &&
- session->userauth_kybd_num_prompts > 100) {
- _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
- "Too many replies for "
- "keyboard-interactive prompts");
- goto cleanup;
+ if(s + 4 <= session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ /* string language tag (as defined in [RFC-3066]) */
+ language_tag_len = _libssh2_ntohu32(s);
+ s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too small"
+ "for auth language tag length");
+ goto cleanup;
+ }
+
+ if(s + language_tag_len <= session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ /* ignoring this field as deprecated */
+ s += language_tag_len;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too small"
+ "for auth language tag");
+ goto cleanup;
+ }
+
+ if(s + 4 <= session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ /* int num-prompts */
+ session->userauth_kybd_num_prompts = _libssh2_ntohu32(s);
+ s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too small"
+ "for auth num keyboard prompts");
+ goto cleanup;
+ }
+
+ if(session->userauth_kybd_num_prompts > 100) {
+ _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+ "Too many replies for "
+ "keyboard-interactive prompts");
+ goto cleanup;
}
if(session->userauth_kybd_num_prompts) {
@@ -1770,7 +1892,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
LIBSSH2_CALLOC(session,
sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) *
session->userauth_kybd_num_prompts);
- if (!session->userauth_kybd_prompts) {
+ if(!session->userauth_kybd_prompts) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"keyboard-interactive prompts array");
@@ -1781,7 +1903,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
LIBSSH2_CALLOC(session,
sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) *
session->userauth_kybd_num_prompts);
- if (!session->userauth_kybd_responses) {
+ if(!session->userauth_kybd_responses) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"keyboard-interactive responses array");
@@ -1789,25 +1911,56 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
}
for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
- /* string prompt[1] (ISO-10646 UTF-8) */
- session->userauth_kybd_prompts[i].length =
- _libssh2_ntohu32(s);
- s += 4;
+ if(s + 4 <= session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ /* string prompt[1] (ISO-10646 UTF-8) */
+ session->userauth_kybd_prompts[i].length =
+ _libssh2_ntohu32(s);
+ s += 4;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too "
+ "small for auth keyboard "
+ "prompt length");
+ goto cleanup;
+ }
+
session->userauth_kybd_prompts[i].text =
LIBSSH2_CALLOC(session,
- session->userauth_kybd_prompts[i].length);
- if (!session->userauth_kybd_prompts[i].text) {
+ session->userauth_kybd_prompts[i].
+ length);
+ if(!session->userauth_kybd_prompts[i].text) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"keyboard-interactive prompt message");
goto cleanup;
}
- memcpy(session->userauth_kybd_prompts[i].text, s,
- session->userauth_kybd_prompts[i].length);
- s += session->userauth_kybd_prompts[i].length;
- /* boolean echo[1] */
- session->userauth_kybd_prompts[i].echo = *s++;
+ if(s + session->userauth_kybd_prompts[i].length <=
+ session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ memcpy(session->userauth_kybd_prompts[i].text, s,
+ session->userauth_kybd_prompts[i].length);
+ s += session->userauth_kybd_prompts[i].length;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too "
+ "small for auth keyboard prompt");
+ goto cleanup;
+ }
+ if(s < session->userauth_kybd_data +
+ session->userauth_kybd_data_len) {
+ /* boolean echo[1] */
+ session->userauth_kybd_prompts[i].echo = *s++;
+ }
+ else {
+ _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
+ "userauth keyboard data buffer too "
+ "small for auth keyboard prompt echo");
+ goto cleanup;
+ }
}
}
@@ -1831,7 +1984,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
/* string response[1] (ISO-10646 UTF-8) */
- if(session->userauth_kybd_responses[i].length <=
+ 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;
@@ -1850,7 +2003,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
session->userauth_kybd_data = s =
LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
- if (!s) {
+ if(!s) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for keyboard-"
"interactive response packet");
@@ -1870,14 +2023,14 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
session->userauth_kybd_state = libssh2_NB_state_sent1;
}
- if (session->userauth_kybd_state == libssh2_NB_state_sent1) {
+ if(session->userauth_kybd_state == libssh2_NB_state_sent1) {
rc = _libssh2_transport_send(session, session->userauth_kybd_data,
session->userauth_kybd_packet_len,
NULL, 0);
- if (rc == LIBSSH2_ERROR_EAGAIN)
+ if(rc == LIBSSH2_ERROR_EAGAIN)
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block");
- if (rc) {
+ if(rc) {
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send userauth-keyboard-interactive"
" request");
@@ -1896,14 +2049,14 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
LIBSSH2_FREE(session, session->userauth_kybd_data);
session->userauth_kybd_data = NULL;
- if (session->userauth_kybd_prompts) {
+ if(session->userauth_kybd_prompts) {
for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
LIBSSH2_FREE(session, session->userauth_kybd_prompts[i].text);
session->userauth_kybd_prompts[i].text = NULL;
}
}
- if (session->userauth_kybd_responses) {
+ if(session->userauth_kybd_responses) {
for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
LIBSSH2_FREE(session,
session->userauth_kybd_responses[i].text);
@@ -1928,7 +2081,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
session->userauth_kybd_auth_instruction = NULL;
}
- if (session->userauth_kybd_auth_failure) {
+ if(session->userauth_kybd_auth_failure) {
session->userauth_kybd_state = libssh2_NB_state_idle;
return -1;
}
@@ -1946,7 +2099,8 @@ LIBSSH2_API int
libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session,
const char *user,
unsigned int user_len,
- LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)))
+ LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC
+ ((*response_callback)))
{
int rc;
BLOCK_ADJUST(rc, session,
diff --git a/libs/libssh2/src/userauth.h b/libs/libssh2/src/userauth.h
index c0442ae158..a7b0a9846e 100644
--- a/libs/libssh2/src/userauth.h
+++ b/libs/libssh2/src/userauth.h
@@ -44,7 +44,8 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
unsigned int username_len,
const unsigned char *pubkeydata,
unsigned long pubkeydata_len,
- LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
+ LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC
+ ((*sign_callback)),
void *abstract);
#endif /* LIBSSH2_USERAUTH_H */
diff --git a/libs/libssh2/src/wincng.c b/libs/libssh2/src/wincng.c
index d3271b3e33..4bebc6407a 100644
--- a/libs/libssh2/src/wincng.c
+++ b/libs/libssh2/src/wincng.c
@@ -59,6 +59,7 @@
#include <windows.h>
#include <bcrypt.h>
#include <math.h>
+#include "misc.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -244,34 +245,50 @@ _libssh2_wincng_init(void)
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_CBC,
BCRYPT_AES_ALGORITHM, NULL, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_CBC, BCRYPT_CHAINING_MODE,
+ if(BCRYPT_SUCCESS(ret)) {
+ ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_CBC,
+ BCRYPT_CHAINING_MODE,
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
}
}
+ ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_ECB,
+ BCRYPT_AES_ALGORITHM, NULL, 0);
+ if(BCRYPT_SUCCESS(ret)) {
+ ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_ECB,
+ BCRYPT_CHAINING_MODE,
+ (PBYTE)BCRYPT_CHAIN_MODE_ECB,
+ sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
+ if(!BCRYPT_SUCCESS(ret)) {
+ (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_ECB, 0);
+ }
+ }
+
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRC4_NA,
BCRYPT_RC4_ALGORITHM, NULL, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(_libssh2_wincng.hAlgRC4_NA, BCRYPT_CHAINING_MODE,
+ if(BCRYPT_SUCCESS(ret)) {
+ ret = BCryptSetProperty(_libssh2_wincng.hAlgRC4_NA,
+ BCRYPT_CHAINING_MODE,
(PBYTE)BCRYPT_CHAIN_MODE_NA,
sizeof(BCRYPT_CHAIN_MODE_NA), 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
}
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlg3DES_CBC,
BCRYPT_3DES_ALGORITHM, NULL, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(_libssh2_wincng.hAlg3DES_CBC, BCRYPT_CHAINING_MODE,
+ if(BCRYPT_SUCCESS(ret)) {
+ ret = BCryptSetProperty(_libssh2_wincng.hAlg3DES_CBC,
+ BCRYPT_CHAINING_MODE,
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
- if (!BCRYPT_SUCCESS(ret)) {
- (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC, 0);
+ if(!BCRYPT_SUCCESS(ret)) {
+ (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC,
+ 0);
}
}
}
@@ -314,11 +331,11 @@ _libssh2_wincng_safe_free(void *buf, int len)
(void)len;
#endif
- if (!buf)
+ if(!buf)
return;
#ifdef LIBSSH2_CLEAR_MEMORY
- if (len > 0)
+ if(len > 0)
SecureZeroMemory(buf, len);
#endif
@@ -345,7 +362,7 @@ _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx,
(unsigned char *)&dwHash,
sizeof(dwHash),
&cbData, 0);
- if ((!BCRYPT_SUCCESS(ret)) || dwHash != hashlen) {
+ if((!BCRYPT_SUCCESS(ret)) || dwHash != hashlen) {
return -1;
}
@@ -353,12 +370,12 @@ _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx,
(unsigned char *)&dwHashObject,
sizeof(dwHashObject),
&cbData, 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
return -1;
}
pbHashObject = malloc(dwHashObject);
- if (!pbHashObject) {
+ if(!pbHashObject) {
return -1;
}
@@ -366,7 +383,7 @@ _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx,
ret = BCryptCreateHash(hAlg, &hHash,
pbHashObject, dwHashObject,
key, keylen, 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng_safe_free(pbHashObject, dwHashObject);
return -1;
}
@@ -418,7 +435,7 @@ _libssh2_wincng_hash(unsigned char *data, unsigned long datalen,
int ret;
ret = _libssh2_wincng_hash_init(&ctx, hAlg, hashlen, NULL, 0);
- if (!ret) {
+ if(!ret) {
ret = _libssh2_wincng_hash_update(&ctx, data, datalen);
ret |= _libssh2_wincng_hash_final(&ctx, hash);
}
@@ -476,13 +493,13 @@ _libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx,
datalen = m_len;
data = malloc(datalen);
- if (!data) {
+ if(!data) {
return -1;
}
hashlen = SHA_DIGEST_LENGTH;
hash = malloc(hashlen);
- if (!hash) {
+ if(!hash) {
free(data);
return -1;
}
@@ -495,22 +512,23 @@ _libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx,
_libssh2_wincng_safe_free(data, datalen);
- if (ret) {
+ if(ret) {
_libssh2_wincng_safe_free(hash, hashlen);
return -1;
}
datalen = sig_len;
data = malloc(datalen);
- if (!data) {
+ if(!data) {
_libssh2_wincng_safe_free(hash, hashlen);
return -1;
}
- if (flags & BCRYPT_PAD_PKCS1) {
+ if(flags & BCRYPT_PAD_PKCS1) {
paddingInfoPKCS1.pszAlgId = BCRYPT_SHA1_ALGORITHM;
pPaddingInfo = &paddingInfoPKCS1;
- } else
+ }
+ else
pPaddingInfo = NULL;
memcpy(data, sig, datalen);
@@ -537,14 +555,13 @@ _libssh2_wincng_load_pem(LIBSSH2_SESSION *session,
FILE *fp;
int ret;
- (void)passphrase;
-
- fp = fopen(filename, "r");
- if (!fp) {
+ fp = fopen(filename, FOPEN_READTEXT);
+ if(!fp) {
return -1;
}
ret = _libssh2_pem_parse(session, headerbegin, headerend,
+ passphrase,
fp, data, datalen);
fclose(fp);
@@ -564,19 +581,19 @@ _libssh2_wincng_load_private(LIBSSH2_SESSION *session,
unsigned int datalen = 0;
int ret = -1;
- if (ret && tryLoadRSA) {
+ if(ret && tryLoadRSA) {
ret = _libssh2_wincng_load_pem(session, filename, passphrase,
PEM_RSA_HEADER, PEM_RSA_FOOTER,
&data, &datalen);
}
- if (ret && tryLoadDSA) {
+ if(ret && tryLoadDSA) {
ret = _libssh2_wincng_load_pem(session, filename, passphrase,
PEM_DSA_HEADER, PEM_DSA_FOOTER,
&data, &datalen);
}
- if (!ret) {
+ if(!ret) {
*ppbEncoded = data;
*pcbEncoded = datalen;
}
@@ -599,21 +616,21 @@ _libssh2_wincng_load_private_memory(LIBSSH2_SESSION *session,
(void)passphrase;
- if (ret && tryLoadRSA) {
+ if(ret && tryLoadRSA) {
ret = _libssh2_pem_parse_memory(session,
PEM_RSA_HEADER, PEM_RSA_FOOTER,
privatekeydata, privatekeydata_len,
&data, &datalen);
}
- if (ret && tryLoadDSA) {
+ if(ret && tryLoadDSA) {
ret = _libssh2_pem_parse_memory(session,
PEM_DSA_HEADER, PEM_DSA_FOOTER,
privatekeydata, privatekeydata_len,
&data, &datalen);
}
- if (!ret) {
+ if(!ret) {
*ppbEncoded = data;
*pcbEncoded = datalen;
}
@@ -636,12 +653,12 @@ _libssh2_wincng_asn_decode(unsigned char *pbEncoded,
lpszStructType,
pbEncoded, cbEncoded, 0, NULL,
NULL, &cbDecoded);
- if (!ret) {
+ if(!ret) {
return -1;
}
pbDecoded = malloc(cbDecoded);
- if (!pbDecoded) {
+ if(!pbDecoded) {
return -1;
}
@@ -649,7 +666,7 @@ _libssh2_wincng_asn_decode(unsigned char *pbEncoded,
lpszStructType,
pbEncoded, cbEncoded, 0, NULL,
pbDecoded, &cbDecoded);
- if (!ret) {
+ if(!ret) {
_libssh2_wincng_safe_free(pbDecoded, cbDecoded);
return -1;
}
@@ -670,25 +687,25 @@ _libssh2_wincng_bn_ltob(unsigned char *pbInput,
unsigned char *pbOutput;
unsigned long cbOutput, index, offset, length;
- if (cbInput < 1) {
+ if(cbInput < 1) {
return 0;
}
offset = 0;
length = cbInput - 1;
cbOutput = cbInput;
- if (pbInput[length] & (1 << 7)) {
+ if(pbInput[length] & (1 << 7)) {
offset++;
cbOutput += offset;
}
pbOutput = (unsigned char *)malloc(cbOutput);
- if (!pbOutput) {
+ if(!pbOutput) {
return -1;
}
pbOutput[0] = 0;
- for (index = 0; ((index + offset) < cbOutput)
+ for(index = 0; ((index + offset) < cbOutput)
&& (index < cbInput); index++) {
pbOutput[index + offset] = pbInput[length - index];
}
@@ -713,11 +730,11 @@ _libssh2_wincng_asn_decode_bn(unsigned char *pbEncoded,
ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
X509_MULTI_BYTE_UINT,
&pbInteger, &cbInteger);
- if (!ret) {
+ if(!ret) {
ret = _libssh2_wincng_bn_ltob(((PCRYPT_DATA_BLOB)pbInteger)->pbData,
((PCRYPT_DATA_BLOB)pbInteger)->cbData,
&pbDecoded, &cbDecoded);
- if (!ret) {
+ if(!ret) {
*ppbDecoded = pbDecoded;
*pcbDecoded = cbDecoded;
}
@@ -742,30 +759,31 @@ _libssh2_wincng_asn_decode_bns(unsigned char *pbEncoded,
ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded,
X509_SEQUENCE_OF_ANY,
&pbDecoded, &cbDecoded);
- if (!ret) {
+ if(!ret) {
length = ((PCRYPT_DATA_BLOB)pbDecoded)->cbData;
rpbDecoded = malloc(sizeof(PBYTE) * length);
- if (rpbDecoded) {
+ if(rpbDecoded) {
rcbDecoded = malloc(sizeof(DWORD) * length);
- if (rcbDecoded) {
- for (index = 0; index < length; index++) {
+ if(rcbDecoded) {
+ for(index = 0; index < length; index++) {
pBlob = &((PCRYPT_DER_BLOB)
((PCRYPT_DATA_BLOB)pbDecoded)->pbData)[index];
ret = _libssh2_wincng_asn_decode_bn(pBlob->pbData,
pBlob->cbData,
&rpbDecoded[index],
&rcbDecoded[index]);
- if (ret)
+ if(ret)
break;
}
- if (!ret) {
+ if(!ret) {
*prpbDecoded = rpbDecoded;
*prcbDecoded = rcbDecoded;
*pcbCount = length;
- } else {
- for (length = 0; length < index; length++) {
+ }
+ else {
+ for(length = 0; length < index; length++) {
_libssh2_wincng_safe_free(rpbDecoded[length],
rcbDecoded[length]);
rpbDecoded[length] = NULL;
@@ -774,11 +792,13 @@ _libssh2_wincng_asn_decode_bns(unsigned char *pbEncoded,
free(rpbDecoded);
free(rcbDecoded);
}
- } else {
+ }
+ else {
free(rpbDecoded);
ret = -1;
}
- } else {
+ }
+ else {
ret = -1;
}
@@ -795,13 +815,13 @@ _libssh2_wincng_bn_size(const unsigned char *bignum,
{
unsigned long offset;
- if (!bignum)
+ if(!bignum)
return 0;
length--;
offset = 0;
- while (!(*(bignum + offset)) && (offset < length))
+ while(!(*(bignum + offset)) && (offset < length))
offset++;
length++;
@@ -845,7 +865,7 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
_libssh2_wincng_bn_size(ddata, dlen));
offset = sizeof(BCRYPT_RSAKEY_BLOB);
keylen = offset + elen + mlen;
- if (ddata && dlen > 0) {
+ if(ddata && dlen > 0) {
p1len = max(_libssh2_wincng_bn_size(pdata, plen),
_libssh2_wincng_bn_size(e1data, e1len));
p2len = max(_libssh2_wincng_bn_size(qdata, qlen),
@@ -854,7 +874,7 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
}
key = malloc(keylen);
- if (!key) {
+ if(!key) {
return -1;
}
@@ -870,45 +890,45 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
memcpy(key + offset, edata, elen);
offset += elen;
- if (nlen < mlen)
+ if(nlen < mlen)
memcpy(key + offset + mlen - nlen, ndata, nlen);
else
memcpy(key + offset, ndata + nlen - mlen, mlen);
- if (ddata && dlen > 0) {
+ if(ddata && dlen > 0) {
offset += mlen;
- if (plen < p1len)
+ if(plen < p1len)
memcpy(key + offset + p1len - plen, pdata, plen);
else
memcpy(key + offset, pdata + plen - p1len, p1len);
offset += p1len;
- if (qlen < p2len)
+ if(qlen < p2len)
memcpy(key + offset + p2len - qlen, qdata, qlen);
else
memcpy(key + offset, qdata + qlen - p2len, p2len);
offset += p2len;
- if (e1len < p1len)
+ if(e1len < p1len)
memcpy(key + offset + p1len - e1len, e1data, e1len);
else
memcpy(key + offset, e1data + e1len - p1len, p1len);
offset += p1len;
- if (e2len < p2len)
+ if(e2len < p2len)
memcpy(key + offset + p2len - e2len, e2data, e2len);
else
memcpy(key + offset, e2data + e2len - p2len, p2len);
offset += p2len;
- if (coefflen < p1len)
+ if(coefflen < p1len)
memcpy(key + offset + p1len - coefflen, coeffdata, coefflen);
else
memcpy(key + offset, coeffdata + coefflen - p1len, p1len);
offset += p1len;
- if (dlen < mlen)
+ if(dlen < mlen)
memcpy(key + offset + mlen - dlen, ddata, dlen);
else
memcpy(key + offset, ddata + dlen - mlen, mlen);
@@ -917,7 +937,8 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
rsakey->Magic = BCRYPT_RSAFULLPRIVATE_MAGIC;
rsakey->cbPrime1 = p1len;
rsakey->cbPrime2 = p2len;
- } else {
+ }
+ else {
lpszBlobType = BCRYPT_RSAPUBLIC_BLOB;
rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC;
rsakey->cbPrime1 = 0;
@@ -927,14 +948,14 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa,
ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL, lpszBlobType,
&hKey, key, keylen, 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng_safe_free(key, keylen);
return -1;
}
*rsa = malloc(sizeof(libssh2_rsa_ctx));
- if (!(*rsa)) {
+ if(!(*rsa)) {
BCryptDestroyKey(hKey);
_libssh2_wincng_safe_free(key, keylen);
return -1;
@@ -967,7 +988,7 @@ _libssh2_wincng_rsa_new_private_parse(libssh2_rsa_ctx **rsa,
_libssh2_wincng_safe_free(pbEncoded, cbEncoded);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -975,14 +996,14 @@ _libssh2_wincng_rsa_new_private_parse(libssh2_rsa_ctx **rsa,
ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
LEGACY_RSAPRIVATE_BLOB, &hKey,
pbStructInfo, cbStructInfo, 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng_safe_free(pbStructInfo, cbStructInfo);
return -1;
}
*rsa = malloc(sizeof(libssh2_rsa_ctx));
- if (!(*rsa)) {
+ if(!(*rsa)) {
BCryptDestroyKey(hKey);
_libssh2_wincng_safe_free(pbStructInfo, cbStructInfo);
return -1;
@@ -1012,7 +1033,7 @@ _libssh2_wincng_rsa_new_private(libssh2_rsa_ctx **rsa,
ret = _libssh2_wincng_load_private(session, filename,
(const char *)passphrase,
&pbEncoded, &cbEncoded, 1, 0);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -1046,7 +1067,7 @@ _libssh2_wincng_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
(const char *)passphrase,
&pbEncoded, &cbEncoded, 1, 0);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -1090,7 +1111,7 @@ _libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session,
datalen = (unsigned long)hash_len;
data = malloc(datalen);
- if (!data) {
+ if(!data) {
return -1;
}
@@ -1101,20 +1122,22 @@ _libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session,
ret = BCryptSignHash(rsa->hKey, &paddingInfo,
data, datalen, NULL, 0,
&cbData, BCRYPT_PAD_PKCS1);
- if (BCRYPT_SUCCESS(ret)) {
+ if(BCRYPT_SUCCESS(ret)) {
siglen = cbData;
sig = LIBSSH2_ALLOC(session, siglen);
- if (sig) {
+ if(sig) {
ret = BCryptSignHash(rsa->hKey, &paddingInfo,
data, datalen, sig, siglen,
&cbData, BCRYPT_PAD_PKCS1);
- if (BCRYPT_SUCCESS(ret)) {
+ if(BCRYPT_SUCCESS(ret)) {
*signature_len = siglen;
*signature = sig;
- } else {
+ }
+ else {
LIBSSH2_FREE(session, sig);
}
- } else
+ }
+ else
ret = STATUS_NO_MEMORY;
}
@@ -1126,7 +1149,7 @@ _libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session,
void
_libssh2_wincng_rsa_free(libssh2_rsa_ctx *rsa)
{
- if (!rsa)
+ if(!rsa)
return;
BCryptDestroyKey(rsa->hKey);
@@ -1168,11 +1191,11 @@ _libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa,
_libssh2_wincng_bn_size(ydata, ylen));
offset = sizeof(BCRYPT_DSA_KEY_BLOB);
keylen = offset + length * 3;
- if (xdata && xlen > 0)
+ if(xdata && xlen > 0)
keylen += 20;
key = malloc(keylen);
- if (!key) {
+ if(!key) {
return -1;
}
@@ -1186,39 +1209,40 @@ _libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa,
memset(dsakey->Count, -1, sizeof(dsakey->Count));
memset(dsakey->Seed, -1, sizeof(dsakey->Seed));
- if (qlen < 20)
+ if(qlen < 20)
memcpy(dsakey->q + 20 - qlen, qdata, qlen);
else
memcpy(dsakey->q, qdata + qlen - 20, 20);
- if (plen < length)
+ if(plen < length)
memcpy(key + offset + length - plen, pdata, plen);
else
memcpy(key + offset, pdata + plen - length, length);
offset += length;
- if (glen < length)
+ if(glen < length)
memcpy(key + offset + length - glen, gdata, glen);
else
memcpy(key + offset, gdata + glen - length, length);
offset += length;
- if (ylen < length)
+ if(ylen < length)
memcpy(key + offset + length - ylen, ydata, ylen);
else
memcpy(key + offset, ydata + ylen - length, length);
- if (xdata && xlen > 0) {
+ if(xdata && xlen > 0) {
offset += length;
- if (xlen < 20)
+ if(xlen < 20)
memcpy(key + offset + 20 - xlen, xdata, xlen);
else
memcpy(key + offset, xdata + xlen - 20, 20);
lpszBlobType = BCRYPT_DSA_PRIVATE_BLOB;
dsakey->dwMagic = BCRYPT_DSA_PRIVATE_MAGIC;
- } else {
+ }
+ else {
lpszBlobType = BCRYPT_DSA_PUBLIC_BLOB;
dsakey->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC;
}
@@ -1226,14 +1250,14 @@ _libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa,
ret = BCryptImportKeyPair(_libssh2_wincng.hAlgDSA, NULL, lpszBlobType,
&hKey, key, keylen, 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng_safe_free(key, keylen);
return -1;
}
*dsa = malloc(sizeof(libssh2_dsa_ctx));
- if (!(*dsa)) {
+ if(!(*dsa)) {
BCryptDestroyKey(hKey);
_libssh2_wincng_safe_free(key, keylen);
return -1;
@@ -1264,23 +1288,24 @@ _libssh2_wincng_dsa_new_private_parse(libssh2_dsa_ctx **dsa,
_libssh2_wincng_safe_free(pbEncoded, cbEncoded);
- if (ret) {
+ if(ret) {
return -1;
}
- if (length == 6) {
+ if(length == 6) {
ret = _libssh2_wincng_dsa_new(dsa,
rpbDecoded[1], rcbDecoded[1],
rpbDecoded[2], rcbDecoded[2],
rpbDecoded[3], rcbDecoded[3],
rpbDecoded[4], rcbDecoded[4],
rpbDecoded[5], rcbDecoded[5]);
- } else {
+ }
+ else {
ret = -1;
}
- for (index = 0; index < length; index++) {
+ for(index = 0; index < length; index++) {
_libssh2_wincng_safe_free(rpbDecoded[index], rcbDecoded[index]);
rpbDecoded[index] = NULL;
rcbDecoded[index] = 0;
@@ -1307,7 +1332,7 @@ _libssh2_wincng_dsa_new_private(libssh2_dsa_ctx **dsa,
ret = _libssh2_wincng_load_private(session, filename,
(const char *)passphrase,
&pbEncoded, &cbEncoded, 0, 1);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -1339,7 +1364,7 @@ _libssh2_wincng_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa,
ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
(const char *)passphrase,
&pbEncoded, &cbEncoded, 0, 1);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -1378,7 +1403,7 @@ _libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa,
datalen = hash_len;
data = malloc(datalen);
- if (!data) {
+ if(!data) {
return -1;
}
@@ -1386,21 +1411,23 @@ _libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa,
ret = BCryptSignHash(dsa->hKey, NULL, data, datalen,
NULL, 0, &cbData, 0);
- if (BCRYPT_SUCCESS(ret)) {
+ if(BCRYPT_SUCCESS(ret)) {
siglen = cbData;
- if (siglen == 40) {
+ if(siglen == 40) {
sig = malloc(siglen);
- if (sig) {
+ if(sig) {
ret = BCryptSignHash(dsa->hKey, NULL, data, datalen,
sig, siglen, &cbData, 0);
- if (BCRYPT_SUCCESS(ret)) {
+ if(BCRYPT_SUCCESS(ret)) {
memcpy(sig_fixed, sig, siglen);
}
_libssh2_wincng_safe_free(sig, siglen);
- } else
+ }
+ else
ret = STATUS_NO_MEMORY;
- } else
+ }
+ else
ret = STATUS_NO_MEMORY;
}
@@ -1412,7 +1439,7 @@ _libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa,
void
_libssh2_wincng_dsa_free(libssh2_dsa_ctx *dsa)
{
- if (!dsa)
+ if(!dsa)
return;
BCryptDestroyKey(dsa->hKey);
@@ -1466,24 +1493,25 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session,
_libssh2_wincng_safe_free(pbEncoded, cbEncoded);
- if (ret) {
+ if(ret) {
return -1;
}
- if (length == 9) { /* private RSA key */
+ if(length == 9) { /* private RSA key */
mthlen = 7;
mth = LIBSSH2_ALLOC(session, mthlen);
- if (mth) {
+ if(mth) {
memcpy(mth, "ssh-rsa", mthlen);
- } else {
+ }
+ else {
ret = -1;
}
keylen = 4 + mthlen + 4 + rcbDecoded[2] + 4 + rcbDecoded[1];
key = LIBSSH2_ALLOC(session, keylen);
- if (key) {
+ if(key) {
offset = _libssh2_wincng_pub_priv_write(key, 0, mth, mthlen);
offset = _libssh2_wincng_pub_priv_write(key, offset,
@@ -1493,23 +1521,26 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session,
_libssh2_wincng_pub_priv_write(key, offset,
rpbDecoded[1],
rcbDecoded[1]);
- } else {
+ }
+ else {
ret = -1;
}
- } else if (length == 6) { /* private DSA key */
+ }
+ else if(length == 6) { /* private DSA key */
mthlen = 7;
mth = LIBSSH2_ALLOC(session, mthlen);
- if (mth) {
+ if(mth) {
memcpy(mth, "ssh-dss", mthlen);
- } else {
+ }
+ else {
ret = -1;
}
keylen = 4 + mthlen + 4 + rcbDecoded[1] + 4 + rcbDecoded[2]
+ 4 + rcbDecoded[3] + 4 + rcbDecoded[4];
key = LIBSSH2_ALLOC(session, keylen);
- if (key) {
+ if(key) {
offset = _libssh2_wincng_pub_priv_write(key, 0, mth, mthlen);
offset = _libssh2_wincng_pub_priv_write(key, offset,
@@ -1527,16 +1558,18 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session,
_libssh2_wincng_pub_priv_write(key, offset,
rpbDecoded[4],
rcbDecoded[4]);
- } else {
+ }
+ else {
ret = -1;
}
- } else {
+ }
+ else {
ret = -1;
}
- for (index = 0; index < length; index++) {
+ for(index = 0; index < length; index++) {
_libssh2_wincng_safe_free(rpbDecoded[index], rcbDecoded[index]);
rpbDecoded[index] = NULL;
rcbDecoded[index] = 0;
@@ -1546,12 +1579,13 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session,
free(rcbDecoded);
- if (ret) {
- if (mth)
+ if(ret) {
+ if(mth)
LIBSSH2_FREE(session, mth);
- if (key)
+ if(key)
LIBSSH2_FREE(session, key);
- } else {
+ }
+ else {
*method = mth;
*method_len = mthlen;
*pubkeydata = key;
@@ -1578,7 +1612,7 @@ _libssh2_wincng_pub_priv_keyfile(LIBSSH2_SESSION *session,
ret = _libssh2_wincng_load_private(session, privatekey, passphrase,
&pbEncoded, &cbEncoded, 1, 1);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -1617,7 +1651,7 @@ _libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
ret = _libssh2_wincng_load_private_memory(session, privatekeydata,
privatekeydata_len, passphrase,
&pbEncoded, &cbEncoded, 1, 1);
- if (ret) {
+ if(ret) {
return -1;
}
@@ -1634,8 +1668,8 @@ _libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
(void)passphrase;
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
- "Unable to extract public key from private key in memory: "
- "Method unsupported in Windows CNG backend");
+ "Unable to extract public key from private key in memory: "
+ "Method unsupported in Windows CNG backend");
#endif /* HAVE_LIBCRYPT32 */
}
@@ -1653,8 +1687,9 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx,
{
BCRYPT_KEY_HANDLE hKey;
BCRYPT_KEY_DATA_BLOB_HEADER *header;
- unsigned char *pbKeyObject, *pbIV, *key;
- unsigned long dwKeyObject, dwIV, dwBlockLength, cbData, keylen;
+ unsigned char *pbKeyObject, *pbIV, *key, *pbCtr, *pbIVCopy;
+ unsigned long dwKeyObject, dwIV, dwCtrLength, dwBlockLength,
+ cbData, keylen;
int ret;
(void)encrypt;
@@ -1663,7 +1698,7 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx,
(unsigned char *)&dwKeyObject,
sizeof(dwKeyObject),
&cbData, 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
return -1;
}
@@ -1671,19 +1706,19 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx,
(unsigned char *)&dwBlockLength,
sizeof(dwBlockLength),
&cbData, 0);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
return -1;
}
pbKeyObject = malloc(dwKeyObject);
- if (!pbKeyObject) {
+ if(!pbKeyObject) {
return -1;
}
keylen = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + type.dwKeyLength;
key = malloc(keylen);
- if (!key) {
+ if(!key) {
free(pbKeyObject);
return -1;
}
@@ -1702,36 +1737,46 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx,
_libssh2_wincng_safe_free(key, keylen);
- if (!BCRYPT_SUCCESS(ret)) {
+ if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng_safe_free(pbKeyObject, dwKeyObject);
return -1;
}
- if (type.dwUseIV) {
- pbIV = malloc(dwBlockLength);
- if (!pbIV) {
+ pbIV = NULL;
+ pbCtr = NULL;
+ dwIV = 0;
+ dwCtrLength = 0;
+
+ if(type.useIV || type.ctrMode) {
+ pbIVCopy = malloc(dwBlockLength);
+ if(!pbIVCopy) {
BCryptDestroyKey(hKey);
_libssh2_wincng_safe_free(pbKeyObject, dwKeyObject);
return -1;
}
- dwIV = dwBlockLength;
- memcpy(pbIV, iv, dwIV);
- } else {
- pbIV = NULL;
- dwIV = 0;
- }
+ memcpy(pbIVCopy, iv, dwBlockLength);
+ if(type.ctrMode) {
+ pbCtr = pbIVCopy;
+ dwCtrLength = dwBlockLength;
+ }
+ else if(type.useIV) {
+ pbIV = pbIVCopy;
+ dwIV = dwBlockLength;
+ }
+ }
ctx->hKey = hKey;
ctx->pbKeyObject = pbKeyObject;
ctx->pbIV = pbIV;
+ ctx->pbCtr = pbCtr;
ctx->dwKeyObject = dwKeyObject;
ctx->dwIV = dwIV;
ctx->dwBlockLength = dwBlockLength;
+ ctx->dwCtrLength = dwCtrLength;
return 0;
}
-
int
_libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx,
_libssh2_cipher_type(type),
@@ -1739,7 +1784,7 @@ _libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx,
unsigned char *block,
size_t blocklen)
{
- unsigned char *pbOutput;
+ unsigned char *pbOutput, *pbInput;
unsigned long cbOutput, cbInput;
int ret;
@@ -1747,31 +1792,47 @@ _libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx,
cbInput = (unsigned long)blocklen;
- if (encrypt) {
- ret = BCryptEncrypt(ctx->hKey, block, cbInput, NULL,
+ if(type.ctrMode) {
+ pbInput = ctx->pbCtr;
+ }
+ else {
+ pbInput = block;
+ }
+
+ if(encrypt || type.ctrMode) {
+ ret = BCryptEncrypt(ctx->hKey, pbInput, cbInput, NULL,
ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0);
- } else {
- ret = BCryptDecrypt(ctx->hKey, block, cbInput, NULL,
+ }
+ else {
+ ret = BCryptDecrypt(ctx->hKey, pbInput, cbInput, NULL,
ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0);
}
- if (BCRYPT_SUCCESS(ret)) {
+ if(BCRYPT_SUCCESS(ret)) {
pbOutput = malloc(cbOutput);
- if (pbOutput) {
- if (encrypt) {
- ret = BCryptEncrypt(ctx->hKey, block, cbInput, NULL,
+ if(pbOutput) {
+ if(encrypt || type.ctrMode) {
+ ret = BCryptEncrypt(ctx->hKey, pbInput, cbInput, NULL,
ctx->pbIV, ctx->dwIV,
pbOutput, cbOutput, &cbOutput, 0);
- } else {
- ret = BCryptDecrypt(ctx->hKey, block, cbInput, NULL,
+ }
+ else {
+ ret = BCryptDecrypt(ctx->hKey, pbInput, cbInput, NULL,
ctx->pbIV, ctx->dwIV,
pbOutput, cbOutput, &cbOutput, 0);
}
- if (BCRYPT_SUCCESS(ret)) {
- memcpy(block, pbOutput, cbOutput);
+ if(BCRYPT_SUCCESS(ret)) {
+ if(type.ctrMode) {
+ _libssh2_xor_data(block, block, pbOutput, blocklen);
+ _libssh2_aes_ctr_increment(ctx->pbCtr, ctx->dwCtrLength);
+ }
+ else {
+ memcpy(block, pbOutput, cbOutput);
+ }
}
_libssh2_wincng_safe_free(pbOutput, cbOutput);
- } else
+ }
+ else
ret = STATUS_NO_MEMORY;
}
@@ -1791,6 +1852,10 @@ _libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx)
_libssh2_wincng_safe_free(ctx->pbIV, ctx->dwBlockLength);
ctx->pbIV = NULL;
ctx->dwBlockLength = 0;
+
+ _libssh2_wincng_safe_free(ctx->pbCtr, ctx->dwCtrLength);
+ ctx->pbCtr = NULL;
+ ctx->dwCtrLength = 0;
}
@@ -1805,7 +1870,7 @@ _libssh2_wincng_bignum_init(void)
_libssh2_bn *bignum;
bignum = (_libssh2_bn *)malloc(sizeof(_libssh2_bn));
- if (bignum) {
+ if(bignum) {
bignum->bignum = NULL;
bignum->length = 0;
}
@@ -1818,20 +1883,20 @@ _libssh2_wincng_bignum_resize(_libssh2_bn *bn, unsigned long length)
{
unsigned char *bignum;
- if (!bn)
+ if(!bn)
return -1;
- if (length == bn->length)
+ if(length == bn->length)
return 0;
#ifdef LIBSSH2_CLEAR_MEMORY
- if (bn->bignum && bn->length > 0 && length < bn->length) {
+ if(bn->bignum && bn->length > 0 && length < bn->length) {
SecureZeroMemory(bn->bignum + length, bn->length - length);
}
#endif
bignum = realloc(bn->bignum, length);
- if (!bignum)
+ if(!bignum)
return -1;
bn->bignum = bignum;
@@ -1840,22 +1905,22 @@ _libssh2_wincng_bignum_resize(_libssh2_bn *bn, unsigned long length)
return 0;
}
-int
+static int
_libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom)
{
unsigned char *bignum;
unsigned long length;
- if (!rnd)
+ if(!rnd)
return -1;
length = (unsigned long)(ceil((float)bits / 8) * sizeof(unsigned char));
- if (_libssh2_wincng_bignum_resize(rnd, length))
+ if(_libssh2_wincng_bignum_resize(rnd, length))
return -1;
bignum = rnd->bignum;
- if (_libssh2_wincng_random(bignum, length))
+ if(_libssh2_wincng_random(bignum, length))
return -1;
/* calculate significant bits in most significant byte */
@@ -1865,24 +1930,23 @@ _libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom)
bignum[0] &= (1 << (8 - bits)) - 1;
/* set some special last bits in most significant byte */
- if (top == 0)
+ if(top == 0)
bignum[0] |= (1 << (7 - bits));
- else if (top == 1)
+ else if(top == 1)
bignum[0] |= (3 << (6 - bits));
/* make odd by setting first bit in least significant byte */
- if (bottom)
+ if(bottom)
bignum[length - 1] |= 1;
return 0;
}
-int
+static int
_libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
_libssh2_bn *a,
_libssh2_bn *p,
- _libssh2_bn *m,
- _libssh2_bn_ctx *bnctx)
+ _libssh2_bn *m)
{
BCRYPT_KEY_HANDLE hKey;
BCRYPT_RSAKEY_BLOB *rsakey;
@@ -1890,16 +1954,14 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
unsigned long keylen, offset, length;
int ret;
- (void)bnctx;
-
- if (!r || !a || !p || !m)
+ if(!r || !a || !p || !m)
return -1;
offset = sizeof(BCRYPT_RSAKEY_BLOB);
keylen = offset + p->length + m->length;
key = malloc(keylen);
- if (!key)
+ if(!key)
return -1;
@@ -1921,14 +1983,14 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen,
BCRYPT_NO_KEY_VALIDATION);
- if (BCRYPT_SUCCESS(ret)) {
+ if(BCRYPT_SUCCESS(ret)) {
ret = BCryptEncrypt(hKey, a->bignum, a->length, NULL, NULL, 0,
NULL, 0, &length, BCRYPT_PAD_NONE);
- if (BCRYPT_SUCCESS(ret)) {
- if (!_libssh2_wincng_bignum_resize(r, length)) {
+ if(BCRYPT_SUCCESS(ret)) {
+ if(!_libssh2_wincng_bignum_resize(r, length)) {
length = max(a->length, length);
bignum = malloc(length);
- if (bignum) {
+ if(bignum) {
offset = length - a->length;
memset(bignum, 0, offset);
memcpy(bignum + offset, a->bignum, a->length);
@@ -1939,12 +2001,14 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
_libssh2_wincng_safe_free(bignum, length);
- if (BCRYPT_SUCCESS(ret)) {
+ if(BCRYPT_SUCCESS(ret)) {
_libssh2_wincng_bignum_resize(r, offset);
}
- } else
+ }
+ else
ret = STATUS_NO_MEMORY;
- } else
+ }
+ else
ret = STATUS_NO_MEMORY;
}
@@ -1961,20 +2025,20 @@ _libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word)
{
unsigned long offset, number, bits, length;
- if (!bn)
+ if(!bn)
return -1;
bits = 0;
number = word;
- while (number >>= 1)
+ while(number >>= 1)
bits++;
length = (unsigned long) (ceil(((double)(bits + 1)) / 8.0) *
sizeof(unsigned char));
- if (_libssh2_wincng_bignum_resize(bn, length))
+ if(_libssh2_wincng_bignum_resize(bn, length))
return -1;
- for (offset = 0; offset < length; offset++)
+ for(offset = 0; offset < length; offset++)
bn->bignum[offset] = (word >> (offset * 8)) & 0xff;
return 0;
@@ -1986,19 +2050,19 @@ _libssh2_wincng_bignum_bits(const _libssh2_bn *bn)
unsigned char number;
unsigned long offset, length, bits;
- if (!bn)
+ if(!bn)
return 0;
length = bn->length - 1;
offset = 0;
- while (!(*(bn->bignum + offset)) && (offset < length))
+ while(!(*(bn->bignum + offset)) && (offset < length))
offset++;
bits = (length - offset) * 8;
number = bn->bignum[offset];
- while (number >>= 1)
+ while(number >>= 1)
bits++;
bits++;
@@ -2013,10 +2077,10 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len,
unsigned char *bignum;
unsigned long offset, length, bits;
- if (!bn || !bin || !len)
+ if(!bn || !bin || !len)
return;
- if (_libssh2_wincng_bignum_resize(bn, len))
+ if(_libssh2_wincng_bignum_resize(bn, len))
return;
memcpy(bn->bignum, bin, len);
@@ -2026,7 +2090,7 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len,
sizeof(unsigned char));
offset = bn->length - length;
- if (offset > 0) {
+ if(offset > 0) {
memmove(bn->bignum, bn->bignum + offset, length);
#ifdef LIBSSH2_CLEAR_MEMORY
@@ -2034,7 +2098,7 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len,
#endif
bignum = realloc(bn->bignum, length);
- if (bignum) {
+ if(bignum) {
bn->bignum = bignum;
bn->length = length;
}
@@ -2044,7 +2108,7 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len,
void
_libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin)
{
- if (bin && bn && bn->bignum && bn->length > 0) {
+ if(bin && bn && bn->bignum && bn->length > 0) {
memcpy(bin, bn->bignum, bn->length);
}
}
@@ -2052,8 +2116,8 @@ _libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin)
void
_libssh2_wincng_bignum_free(_libssh2_bn *bn)
{
- if (bn) {
- if (bn->bignum) {
+ if(bn) {
+ if(bn->bignum) {
_libssh2_wincng_safe_free(bn->bignum, bn->length);
bn->bignum = NULL;
}
@@ -2064,13 +2128,41 @@ _libssh2_wincng_bignum_free(_libssh2_bn *bn)
/*
- * Windows CNG backend: other functions
+ * Windows CNG backend: Diffie-Hellman support.
*/
-void _libssh2_init_aes_ctr(void)
+void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
+{
+ *dhctx = _libssh2_wincng_bignum_init(); /* Random from client */
+}
+
+int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+ _libssh2_bn *g, _libssh2_bn *p, int group_order)
+{
+ /* Generate x and e */
+ if(_libssh2_wincng_bignum_rand(*dhctx, group_order * 8 - 1, 0, -1))
+ return -1;
+ if(_libssh2_wincng_bignum_mod_exp(public, g, *dhctx, p))
+ return -1;
+ return 0;
+}
+
+int
+_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
+ _libssh2_bn *f, _libssh2_bn *p)
+{
+ /* Compute the shared secret */
+ _libssh2_wincng_bignum_mod_exp(secret, f, *dhctx, p);
+ return 0;
+}
+
+void
+_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
{
- /* no implementation */
- (void)0;
+ _libssh2_wincng_bignum_free(*dhctx);
+ *dhctx = NULL;
}
#endif /* LIBSSH2_WINCNG */
diff --git a/libs/libssh2/src/wincng.h b/libs/libssh2/src/wincng.h
index 5219db7f8a..f5838d0e64 100644
--- a/libs/libssh2/src/wincng.h
+++ b/libs/libssh2/src/wincng.h
@@ -55,7 +55,7 @@
#define LIBSSH2_HMAC_SHA512 1
#define LIBSSH2_AES 1
-#define LIBSSH2_AES_CTR 0
+#define LIBSSH2_AES_CTR 1
#define LIBSSH2_BLOWFISH 0
#define LIBSSH2_RC4 1
#define LIBSSH2_CAST 0
@@ -63,12 +63,20 @@
#define LIBSSH2_RSA 1
#define LIBSSH2_DSA 1
+#define LIBSSH2_ECDSA 0
+#define LIBSSH2_ED25519 0
#define MD5_DIGEST_LENGTH 16
#define SHA_DIGEST_LENGTH 20
#define SHA256_DIGEST_LENGTH 32
#define SHA512_DIGEST_LENGTH 64
+#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
+
+#if LIBSSH2_ECDSA
+#else
+#define _libssh2_ec_key void
+#endif
/*******************************************************************/
/*
@@ -88,6 +96,7 @@ struct _libssh2_wincng_ctx {
BCRYPT_ALG_HANDLE hAlgRSA;
BCRYPT_ALG_HANDLE hAlgDSA;
BCRYPT_ALG_HANDLE hAlgAES_CBC;
+ BCRYPT_ALG_HANDLE hAlgAES_ECB;
BCRYPT_ALG_HANDLE hAlgRC4_NA;
BCRYPT_ALG_HANDLE hAlg3DES_CBC;
};
@@ -285,9 +294,11 @@ struct _libssh2_wincng_cipher_ctx {
BCRYPT_KEY_HANDLE hKey;
unsigned char *pbKeyObject;
unsigned char *pbIV;
+ unsigned char *pbCtr;
unsigned long dwKeyObject;
unsigned long dwIV;
unsigned long dwBlockLength;
+ unsigned long dwCtrLength;
};
#define _libssh2_cipher_ctx struct _libssh2_wincng_cipher_ctx
@@ -299,21 +310,21 @@ struct _libssh2_wincng_cipher_ctx {
struct _libssh2_wincng_cipher_type {
BCRYPT_ALG_HANDLE *phAlg;
unsigned long dwKeyLength;
- unsigned long dwUseIV;
+ int useIV; /* TODO: Convert to bool when a C89 compatible bool type
+ is defined */
+ int ctrMode;
};
#define _libssh2_cipher_type(type) struct _libssh2_wincng_cipher_type type
-#define _libssh2_cipher_aes256ctr { NULL, 32, 1 } /* not supported */
-#define _libssh2_cipher_aes192ctr { NULL, 24, 1 } /* not supported */
-#define _libssh2_cipher_aes128ctr { NULL, 16, 1 } /* not supported */
-#define _libssh2_cipher_aes256 { &_libssh2_wincng.hAlgAES_CBC, 32, 1 }
-#define _libssh2_cipher_aes192 { &_libssh2_wincng.hAlgAES_CBC, 24, 1 }
-#define _libssh2_cipher_aes128 { &_libssh2_wincng.hAlgAES_CBC, 16, 1 }
-#define _libssh2_cipher_blowfish { NULL, 16, 0 } /* not supported */
-#define _libssh2_cipher_arcfour { &_libssh2_wincng.hAlgRC4_NA, 16, 0 }
-#define _libssh2_cipher_cast5 { NULL, 16, 0 } /* not supported */
-#define _libssh2_cipher_3des { &_libssh2_wincng.hAlg3DES_CBC, 24, 1 }
+#define _libssh2_cipher_aes256ctr { &_libssh2_wincng.hAlgAES_ECB, 32, 0, 1 }
+#define _libssh2_cipher_aes192ctr { &_libssh2_wincng.hAlgAES_ECB, 24, 0, 1 }
+#define _libssh2_cipher_aes128ctr { &_libssh2_wincng.hAlgAES_ECB, 16, 0, 1 }
+#define _libssh2_cipher_aes256 { &_libssh2_wincng.hAlgAES_CBC, 32, 1, 0 }
+#define _libssh2_cipher_aes192 { &_libssh2_wincng.hAlgAES_CBC, 24, 1, 0 }
+#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 }
/*
* Windows CNG backend: Cipher functions
@@ -358,10 +369,6 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void);
_libssh2_wincng_bignum_init()
#define _libssh2_bn_init_from_bin() \
_libssh2_bn_init()
-#define _libssh2_bn_rand(bn, bits, top, bottom) \
- _libssh2_wincng_bignum_rand(bn, bits, top, bottom)
-#define _libssh2_bn_mod_exp(r, a, p, m, ctx) \
- _libssh2_wincng_bignum_mod_exp(r, a, p, m, ctx)
#define _libssh2_bn_set_word(bn, word) \
_libssh2_wincng_bignum_set_word(bn, word)
#define _libssh2_bn_from_bin(bn, len, bin) \
@@ -374,6 +381,18 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void);
#define _libssh2_bn_free(bn) \
_libssh2_wincng_bignum_free(bn)
+/*
+ * Windows CNG backend: Diffie-Hellman support
+ */
+
+#define _libssh2_dh_ctx struct _libssh2_wincng_bignum *
+#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
+#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
+ _libssh2_dh_key_pair(dhctx, public, g, p, group_order)
+#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \
+ _libssh2_dh_secret(dhctx, secret, f, p)
+#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx)
+
/*******************************************************************/
/*
* Windows CNG backend: forward declarations
@@ -381,7 +400,6 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void);
void _libssh2_wincng_init(void);
void _libssh2_wincng_free(void);
int _libssh2_wincng_random(void *buf, int len);
-void _libssh2_init_aes_ctr(void);
int
_libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx,
@@ -531,14 +549,6 @@ _libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx);
_libssh2_bn *
_libssh2_wincng_bignum_init(void);
int
-_libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom);
-int
-_libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
- _libssh2_bn *a,
- _libssh2_bn *p,
- _libssh2_bn *m,
- _libssh2_bn_ctx *bnctx);
-int
_libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word);
unsigned long
_libssh2_wincng_bignum_bits(const _libssh2_bn *bn);
@@ -549,3 +559,13 @@ void
_libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin);
void
_libssh2_wincng_bignum_free(_libssh2_bn *bn);
+extern void
+_libssh2_dh_init(_libssh2_dh_ctx *dhctx);
+extern int
+_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
+ _libssh2_bn *g, _libssh2_bn *p, int group_order);
+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);