1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Upgrade libssh2 to 1.10.0

This commit is contained in:
dmiller
2022-06-29 20:40:29 +00:00
parent d969fd00ca
commit 51139a637f
63 changed files with 9140 additions and 2376 deletions

View File

@@ -1,5 +1,7 @@
#Nmap Changelog ($Id$); -*-text-*-
o Upgrade libssh2 to 1.10.0.
o [NSE][GH#2496] Fix newtargets support: since Nmap 7.92, scripts could not add
targets in script pre-scanning phase. [Daniel Miller]

View File

@@ -98,6 +98,14 @@ if(BUILD_TESTING)
add_subdirectory(tests)
endif()
option(LINT "Check style while building" OFF)
if(LINT)
add_custom_target(lint ALL
./ci/checksrc.sh
WORKING_DIRECTORY ${libssh2_SOURCE_DIR})
add_dependencies(libssh2 lint)
endif()
add_subdirectory(docs)
feature_summary(WHAT ALL)

View File

@@ -2,8 +2,10 @@
* Copyright (c) 2005,2006 Mikhail Gusarov <dottedmag@dottedmag.net>
* Copyright (c) 2006-2007 The Written Word, Inc.
* Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
* Copyright (c) 2009-2014 Daniel Stenberg
* Copyright (c) 2009-2021 Daniel Stenberg
* Copyright (C) 2008, 2009 Simon Josefsson
* Copyright (c) 2000 Markus Friedl
* Copyright (c) 2015 Microsoft Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms,

View File

@@ -43,7 +43,7 @@ os400/libssh2rpg/libssh2_publickey.rpgle \
os400/libssh2rpg/libssh2_sftp.rpgle \
Makefile.os400qc3.inc
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk \
EXTRA_DIST = $(WIN32FILES) $(NETWAREFILES) get_ver.awk \
maketgz NMakefile RELEASE-NOTES libssh2.pc.in $(VMSFILES) config.rpath \
CMakeLists.txt cmake $(OS400FILES)
@@ -119,7 +119,7 @@ $(DSP): win32/msvcproj.head win32/msvcproj.foot Makefile.am
for file in $$sorted_hdrs; do \
echo "# Begin Source File"; \
echo ""; \
if [ "$$file" == "libssh2_config.h" ]; \
if [ "$$file" = "libssh2_config.h" ]; \
then \
echo "SOURCE=.\\"$$file; \
else \
@@ -149,4 +149,6 @@ $(VCPROJ): win32/vc8proj.head win32/vc8proj.foot Makefile.am
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )
checksrc:
perl src/checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT -AFOPENMODE -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c
perl src/checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT \
-AFOPENMODE -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c \
tests/*.[ch]

View File

@@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# Makefile.in generated by automake 1.16.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -105,8 +105,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/src/libssh2_config.h \
$(top_builddir)/example/libssh2_config.h
CONFIG_HEADER = $(top_builddir)/src/libssh2_config.h
CONFIG_CLEAN_FILES = libssh2.pc
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
@@ -192,9 +191,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
DIST_SUBDIRS = src tests docs example
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.inc \
$(srcdir)/libssh2.pc.in COPYING ChangeLog NEWS README compile \
@@ -238,6 +234,8 @@ am__relativize = \
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
DIST_TARGETS = dist-gzip
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@@ -257,6 +255,12 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@@ -267,6 +271,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
@@ -300,6 +305,7 @@ LIBSSL_PREFIX = @LIBSSL_PREFIX@
LIBTOOL = @LIBTOOL@
LIBZ = @LIBZ@
LIBZ_PREFIX = @LIBZ_PREFIX@
LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBBCRYPT = @LTLIBBCRYPT@
@@ -341,6 +347,7 @@ abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
@@ -425,7 +432,7 @@ os400/libssh2rpg/libssh2_publickey.rpgle \
os400/libssh2rpg/libssh2_sftp.rpgle \
Makefile.os400qc3.inc
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk \
EXTRA_DIST = $(WIN32FILES) $(NETWAREFILES) get_ver.awk \
maketgz NMakefile RELEASE-NOTES libssh2.pc.in $(VMSFILES) config.rpath \
CMakeLists.txt cmake $(OS400FILES)
@@ -438,10 +445,10 @@ CRYPTO_HHEADERS = openssl.h wincng.h mbedtls.h
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 \
blowfish.c bcrypt_pbkdf.c
blowfish.c bcrypt_pbkdf.c agent_win.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 blf.h
mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h agent.h
# Makefile.inc provides the CSOURCES and HHEADERS defines
WIN32SOURCES = $(CSOURCES)
@@ -642,7 +649,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
@@ -729,6 +735,10 @@ dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
dist-zstd: distdir
tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@@ -771,6 +781,8 @@ distcheck: dist
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
*.tar.zst*) \
zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
@@ -786,7 +798,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
@@ -952,7 +964,7 @@ uninstall-am: uninstall-includeHEADERS uninstall-pkgconfigDATA
am--refresh check check-am clean clean-cscope clean-generic \
clean-libtool cscope cscopelist-am ctags ctags-am dist \
dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \
dist-tarZ dist-xz dist-zip distcheck distclean \
dist-tarZ dist-xz dist-zip dist-zstd distcheck distclean \
distclean-generic distclean-libtool distclean-tags \
distcleancheck distdir distuninstallcheck dvi dvi-am html \
html-am info info-am install install-am install-data \
@@ -1028,7 +1040,7 @@ $(DSP): win32/msvcproj.head win32/msvcproj.foot Makefile.am
for file in $$sorted_hdrs; do \
echo "# Begin Source File"; \
echo ""; \
if [ "$$file" == "libssh2_config.h" ]; \
if [ "$$file" = "libssh2_config.h" ]; \
then \
echo "SOURCE=.\\"$$file; \
else \
@@ -1058,7 +1070,9 @@ $(VCPROJ): win32/vc8proj.head win32/vc8proj.foot Makefile.am
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )
checksrc:
perl src/checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT -AFOPENMODE -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c
perl src/checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT \
-AFOPENMODE -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c \
tests/*.[ch]
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View File

@@ -1,7 +1,7 @@
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 \
blowfish.c bcrypt_pbkdf.c
blowfish.c bcrypt_pbkdf.c agent_win.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 blf.h
mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h agent.h

File diff suppressed because it is too large Load Diff

View File

@@ -1,44 +1,62 @@
libssh2 1.9.0
libssh2 1.10
This release includes the following enhancements and bugfixes:
o adds ECDSA keys and host key support when using OpenSSL
o adds ED25519 key and host key support when using OpenSSL 1.1.1
o adds OpenSSH style key file reading
o adds AES CTR mode support when using WinCNG
o adds PEM passphrase protected file support for Libgcrypt and WinCNG
o adds SHA256 hostkey fingerprint
o adds libssh2_agent_get_identity_path() and libssh2_agent_set_identity_path()
o adds explicit zeroing of sensitive data in memory
o adds additional bounds checks to network buffer reads
o adds the ability to use the server default permissions when creating sftp directories
o adds support for building with OpenSSL no engine flag
o adds support for building with LibreSSL
o increased sftp packet size to 256k
o fixed oversized packet handling in sftp
o fixed building with OpenSSL 1.1
o fixed a possible crash if sftp stat gets an unexpected response
o fixed incorrect parsing of the KEX preference string value
o fixed conditional RSA and AES-CTR support
o fixed a small memory leak during the key exchange process
o fixed a possible memory leak of the ssh banner string
o fixed various small memory leaks in the backends
o fixed possible out of bounds read when parsing public keys from the server
o fixed possible out of bounds read when parsing invalid PEM files
o no longer null terminates the scp remote exec command
o now handle errors when diffie hellman key pair generation fails
o fixed compiling on Windows with the flag STDCALL=ON
o improved building instructions
o adds agent forwarding support
o adds OpenSSH Agent support on Windows
o adds ECDSA key support using the Mbed TLS backend
o adds ECDSA cert authentication
o adds diffie-hellman-group14-sha256, diffie-hellman-group16-sha512,
diffie-hellman-group18-sha512 key exchanges
o adds support for PKIX key reading when using ed25519 with OpenSSL
o adds support for EWOULDBLOCK on VMS systems
o adds support for building with OpenSSL 3
o adds support for using FIPS mode in OpenSSL
o adds debug symbols when building with MSVC
o adds support for building on the 3DS
o adds unicode build support on Windows
o restores os400 building
o increases min, max and opt Diffie Hellman group values
o improves portiablity of the make file
o improves timeout behavior with 2FA keyboard auth
o various improvements to the Wincng backend
o fixes reading parital packet replies when using an agent
o fixes Diffie Hellman key exchange on Windows 1903+ builds
o fixes building tests with older versions of OpenSSL
o fixes possible multiple definition warnings
o fixes potential cast issues _libssh2_ecdsa_key_get_curve_type()
o fixes potential use after free if libssh2_init() is called twice
o improved linking when using Mbed TLS
o fixes call to libssh2_crypto_exit() if crypto hasn't been initialized
o fixes crash when loading public keys with no id
o fixes possible out of bounds read when exchanging keys
o fixes possible out of bounds read when reading packets
o fixes possible out of bounds read when opening an X11 connection
o fixes possible out of bounds read when ecdh host keys
o fixes possible hang when trying to read a disconnected socket
o fixes a crash when using the delayed compression option
o fixes read error with large known host entries
o fixes various warnings
o fixes various small memory leaks
o improved error handling, various detailed errors will now be reported
o builds are now using OSS-Fuzz
o builds now use autoreconf instead of a custom build script
o cmake now respects install directory
o improved CI backend
o updated HACKING-CRYPTO documentation
o use markdown file extensions
o improved unit tests
This release would not have looked like this without help, code, reports and
advice from friends like these:
Peter Surge, Will Cosgrove, Daniel Stenberg, Alex Arslan, Alex Crichton,
Thomas Bleeker, Keno Fischer, Marc Hörsken, Marcel Raad, Viktor Szakats,
Kamil Dudka, Panos, Etienne Samson, Tseng Jun, Brendan Shanks, doublex,
Erik B, Jakob Egger, Thomas Lochmatter, alex-weaver, Adrian Moran, Zenju,
gartens, Matthew D. Fuller, Ryan Kelley, Zhen-Huan HWANG, Orivej Desh,
Alexander Curtiss
katzer, Orgad Shaneh, mark-i-m, Zenju, axjowa, Thilo Schulz,
Etienne Samson, hlefebvre, seba30, Panos, jethrogb, Fabrice Fontaine,
Will Cosgrove, Daniel Stenberg, Michael Buckley, Wallace Souza Silva,
Romain-Geissler-1A, meierha, Tseng Jun, Thomas Klausner, Brendan Shanks,
Harry Sintonen, monnerat, Koutheir Attouchi, Marc Hörsken, yann-morin-1998,
Wez Furlong, TDi-jonesds, David Benjamin, Max Dymond, Igor Klevanets,
Viktor Szakats, Laurent Stacul, Mstrodl, Gabriel Smith, MarcT512,
Paul Capron, teottin, Tor Erik Ottinsen, Brian Inglis
(29 contributors)
(40 contributors)

View File

@@ -441,6 +441,7 @@ m4_case([$1],
[mbedtls], [
LIBSSH2_LIB_HAVE_LINKFLAGS([mbedcrypto], [], [#include <mbedtls/version.h>], [
AC_DEFINE(LIBSSH2_MBEDTLS, 1, [Use $1])
LIBS="$LIBS -lmbedcrypto"
found_crypto="$1"
support_clear_memory=yes
])

77
libssh2/aclocal.m4 vendored
View File

@@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
# generated automatically by aclocal 1.16.4 -*- Autoconf -*-
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -14,13 +14,13 @@
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
[m4_warning([this file was generated for autoconf 2.69.
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
[m4_warning([this file was generated for autoconf 2.71.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# Copyright (C) 2002-2018 Free Software Foundation, Inc.
# Copyright (C) 2002-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -35,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.16.1], [],
m4_if([$1], [1.16.4], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.1])dnl
[AM_AUTOMAKE_VERSION([1.16.4])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -110,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2018 Free Software Foundation, Inc.
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -141,7 +141,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -332,7 +332,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -371,7 +371,9 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
done
if test $am_rc -ne 0; then
AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
for automatic dependency tracking. Try re-running configure with the
for automatic dependency tracking. If GNU make was not used, consider
re-running the configure script with MAKE="gmake" (or whatever is
necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).])
fi
@@ -398,7 +400,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -462,7 +464,7 @@ m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
[ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
@@ -514,6 +516,20 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
])
# Variables for tags utilities; see am/tags.am
if test -z "$CTAGS"; then
CTAGS=ctags
fi
AC_SUBST([CTAGS])
if test -z "$ETAGS"; then
ETAGS=etags
fi
AC_SUBST([ETAGS])
if test -z "$CSCOPE"; then
CSCOPE=cscope
fi
AC_SUBST([CSCOPE])
AC_REQUIRE([AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
@@ -595,7 +611,7 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -616,7 +632,7 @@ if test x"${install_sh+set}" != xset; then
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2018 Free Software Foundation, Inc.
# Copyright (C) 2003-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -638,7 +654,7 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -673,7 +689,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -716,7 +732,7 @@ AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2018 Free Software Foundation, Inc.
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -737,12 +753,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
@@ -755,7 +766,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -784,7 +795,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -831,7 +842,7 @@ AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -850,7 +861,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -931,7 +942,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file
])
# Copyright (C) 2009-2018 Free Software Foundation, Inc.
# Copyright (C) 2009-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -991,7 +1002,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001-2018 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -1019,7 +1030,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2018 Free Software Foundation, Inc.
# Copyright (C) 2006-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -1038,7 +1049,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2018 Free Software Foundation, Inc.
# Copyright (C) 2004-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,

View File

@@ -1,22 +0,0 @@
#!/bin/sh
LIBTOOLIZE="libtoolize"
if [ "x`which $LIBTOOLIZE`" = "x" ]; then
LIBTOOLIZE="glibtoolize"
fi
if [ "x`which $LIBTOOLIZE`" = "x" ]; then
echo "Neither libtoolize nor glibtoolize could be found!"
exit 1
fi
${LIBTOOLIZE} --copy --automake --force
${ACLOCAL:-aclocal} -I m4 $ACLOCAL_FLAGS
${AUTOHEADER:-autoheader}
# copy the private libssh2_config.h.in to the examples dir so that
# it can be included without pointing the include path to the private
# source dir
cp src/libssh2_config.h.in example/libssh2_config.h.in
${AUTOCONF:-autoconf}
${AUTOMAKE:-automake} --add-missing --copy

View File

@@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
@@ -53,7 +53,7 @@ func_file_conv ()
MINGW*)
file_conv=mingw
;;
CYGWIN*)
CYGWIN* | MSYS*)
file_conv=cygwin
;;
*)
@@ -67,7 +67,7 @@ func_file_conv ()
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
cygwin/* | msys/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)

4339
libssh2/configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -35,9 +35,6 @@ case "$host" in
*-mingw*)
CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
LIBS="$LIBS -lws2_32"
;;
*-cygwin)
CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
;;
*darwin*)
CFLAGS="$CFLAGS -DLIBSSH2_DARWIN"
@@ -69,13 +66,10 @@ AC_SEARCH_LIBS(inet_addr, nsl)
AC_SUBST(LIBS)
AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PATH_PROGS(SSHD, [sshd], [],
[$PATH$PATH_SEPARATOR/usr/libexec$PATH_SEPARATOR]dnl
[/usr/sbin$PATH_SEPARATOR/usr/etc$PATH_SEPARATOR/etc])
AM_CONDITIONAL(SSHD, test -n "$SSHD")
AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL
AC_C_BIGENDIAN
@@ -127,8 +121,6 @@ fi
m4_set_foreach([crypto_backends], [backend],
[AM_CONDITIONAL(m4_toupper(backend), test "$found_crypto" = "backend")]
)
m4_undefine([backend])
# libz
@@ -268,6 +260,37 @@ AC_HELP_STRING([--disable-hidden-symbols],[Leave all symbols with default visibi
AC_MSG_RESULT(no)
)
# Build example applications?
AC_MSG_CHECKING([whether to build example applications])
AC_ARG_ENABLE([examples-build],
AC_HELP_STRING([--enable-examples-build], [Build example applications (this is the default)])
AC_HELP_STRING([--disable-examples-build], [Do not build example applications]),
[case "$enableval" in
no | false)
build_examples='no'
;;
*)
build_examples='yes'
;;
esac], [build_examples='yes'])
AC_MSG_RESULT($build_examples)
AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"])
# Build OSS fuzzing targets?
AC_ARG_ENABLE([ossfuzzers],
[AS_HELP_STRING([--enable-ossfuzzers],
[Whether to generate the fuzzers for OSS-Fuzz])],
[have_ossfuzzers=yes], [have_ossfuzzers=no])
AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$have_ossfuzzers" = "xyes"])
# Set the correct flags for the given fuzzing engine.
AC_SUBST([LIB_FUZZING_ENGINE])
AM_CONDITIONAL([USE_OSSFUZZ_FLAG], [test "x$LIB_FUZZING_ENGINE" = "x-fsanitize=fuzzer"])
AM_CONDITIONAL([USE_OSSFUZZ_STATIC], [test -f "$LIB_FUZZING_ENGINE"])
# Checks for header files.
# AC_HEADER_STDC
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h])
@@ -370,6 +393,6 @@ AC_MSG_NOTICE([summary of build options:
Crypto library: ${found_crypto_str}
Clear memory: $enable_clear_memory
Debug build: $enable_debug
Path to sshd: $ac_cv_path_SSHD (only for self-tests)
Build examples: $build_examples
zlib compression: ${found_libz}
])

View File

@@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@@ -46,12 +46,12 @@
to make the BANNER define (used by src/session.c) be a valid SSH
banner. Release versions have no appended strings and may of course not
have dashes either. */
#define LIBSSH2_VERSION "1.9.0"
#define LIBSSH2_VERSION "1.10.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBSSH2_VERSION_MAJOR 1
#define LIBSSH2_VERSION_MINOR 9
#define LIBSSH2_VERSION_MINOR 10
#define LIBSSH2_VERSION_PATCH 0
/* This is the numeric version of the libssh2 version number, meant for easier
@@ -69,7 +69,7 @@
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
*/
#define LIBSSH2_VERSION_NUM 0x010900
#define LIBSSH2_VERSION_NUM 0x010a00
/*
* This is the date and time when the full source package was created. The
@@ -80,7 +80,7 @@
*
* "Mon Feb 12 11:35:33 UTC 2007"
*/
#define LIBSSH2_TIMESTAMP "Thu Jun 20 06:19:26 UTC 2019"
#define LIBSSH2_TIMESTAMP "Sun 29 Aug 2021 08:37:50 PM UTC"
#ifndef RC_INVOKED
@@ -235,9 +235,11 @@ typedef off_t libssh2_struct_stat_size;
/* Default generate and safe prime sizes for
diffie-hellman-group-exchange-sha1 */
#define LIBSSH2_DH_GEX_MINGROUP 1024
#define LIBSSH2_DH_GEX_OPTGROUP 1536
#define LIBSSH2_DH_GEX_MAXGROUP 2048
#define LIBSSH2_DH_GEX_MINGROUP 2048
#define LIBSSH2_DH_GEX_OPTGROUP 4096
#define LIBSSH2_DH_GEX_MAXGROUP 8192
#define LIBSSH2_DH_MAX_MODULUS_BITS 16384
/* Defaults for pty requests */
#define LIBSSH2_TERM_WIDTH 80
@@ -503,6 +505,7 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_KNOWN_HOSTS -46
#define LIBSSH2_ERROR_CHANNEL_WINDOW_FULL -47
#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48
#define LIBSSH2_ERROR_RANDGEN -49
/* this is a define to provide the old (<= 1.2.7) name */
#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV
@@ -545,7 +548,7 @@ LIBSSH2_API void libssh2_free(LIBSSH2_SESSION *session, void *ptr);
*
* Fills algs with a list of supported acryptographic algorithms. Returns a
* non-negative number (number of supported algorithms) on success or a
* negative number (an eror code) on failure.
* negative number (an error code) on failure.
*
* NOTE: on success, algs must be deallocated (by calling libssh2_free) when
* not needed anymore
@@ -688,7 +691,7 @@ libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION *session,
* response_callback is provided with filled by library prompts array,
* but client must allocate and fill individual responses. Responses
* array is already allocated. Responses data will be freed by libssh2
* after callback return, but before subsequent callback invokation.
* after callback return, but before subsequent callback invocation.
*/
LIBSSH2_API int
libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION* session,
@@ -718,7 +721,7 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds,
#define SSH_EXTENDED_DATA_STDERR 1
/* Returned by any function that would block during a read/write opperation */
/* Returned by any function that would block during a read/write operation */
#define LIBSSH2CHANNEL_EAGAIN LIBSSH2_ERROR_EAGAIN
LIBSSH2_API LIBSSH2_CHANNEL *
@@ -761,6 +764,8 @@ LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel,
(unsigned int)strlen(varname), (value), \
(unsigned int)strlen(value))
LIBSSH2_API int libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel,
const char *term,
unsigned int term_len,
@@ -987,7 +992,7 @@ libssh2_knownhost_init(LIBSSH2_SESSION *session);
#define LIBSSH2_KNOWNHOST_KEYENC_RAW (1<<16)
#define LIBSSH2_KNOWNHOST_KEYENC_BASE64 (2<<16)
/* type of key (3 bits) */
/* type of key (4 bits) */
#define LIBSSH2_KNOWNHOST_KEY_MASK (15<<18)
#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18
#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18)
@@ -1165,7 +1170,7 @@ libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
* libssh2_knownhost_get()
*
* Traverse the internal list of known hosts. Pass NULL to 'prev' to get
* the first one. Or pass a poiner to the previously returned one to get the
* the first one. Or pass a pointer to the previously returned one to get the
* next.
*
* Returns:
@@ -1221,7 +1226,7 @@ libssh2_agent_list_identities(LIBSSH2_AGENT *agent);
* libssh2_agent_get_identity()
*
* Traverse the internal list of public keys. Pass NULL to 'prev' to get
* the first one. Or pass a poiner to the previously returned one to get the
* the first one. Or pass a pointer to the previously returned one to get the
* next.
*
* Returns:

View File

@@ -189,32 +189,32 @@ struct _LIBSSH2_SFTP_STATVFS {
#define LIBSSH2_FXF_EXCL 0x00000020
/* SFTP Status Codes (returned by libssh2_sftp_last_error() ) */
#define LIBSSH2_FX_OK 0
#define LIBSSH2_FX_EOF 1
#define LIBSSH2_FX_NO_SUCH_FILE 2
#define LIBSSH2_FX_PERMISSION_DENIED 3
#define LIBSSH2_FX_FAILURE 4
#define LIBSSH2_FX_BAD_MESSAGE 5
#define LIBSSH2_FX_NO_CONNECTION 6
#define LIBSSH2_FX_CONNECTION_LOST 7
#define LIBSSH2_FX_OP_UNSUPPORTED 8
#define LIBSSH2_FX_INVALID_HANDLE 9
#define LIBSSH2_FX_NO_SUCH_PATH 10
#define LIBSSH2_FX_FILE_ALREADY_EXISTS 11
#define LIBSSH2_FX_WRITE_PROTECT 12
#define LIBSSH2_FX_NO_MEDIA 13
#define LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM 14
#define LIBSSH2_FX_QUOTA_EXCEEDED 15
#define LIBSSH2_FX_UNKNOWN_PRINCIPLE 16 /* Initial mis-spelling */
#define LIBSSH2_FX_UNKNOWN_PRINCIPAL 16
#define LIBSSH2_FX_LOCK_CONFlICT 17 /* Initial mis-spelling */
#define LIBSSH2_FX_LOCK_CONFLICT 17
#define LIBSSH2_FX_DIR_NOT_EMPTY 18
#define LIBSSH2_FX_NOT_A_DIRECTORY 19
#define LIBSSH2_FX_INVALID_FILENAME 20
#define LIBSSH2_FX_LINK_LOOP 21
#define LIBSSH2_FX_OK 0UL
#define LIBSSH2_FX_EOF 1UL
#define LIBSSH2_FX_NO_SUCH_FILE 2UL
#define LIBSSH2_FX_PERMISSION_DENIED 3UL
#define LIBSSH2_FX_FAILURE 4UL
#define LIBSSH2_FX_BAD_MESSAGE 5UL
#define LIBSSH2_FX_NO_CONNECTION 6UL
#define LIBSSH2_FX_CONNECTION_LOST 7UL
#define LIBSSH2_FX_OP_UNSUPPORTED 8UL
#define LIBSSH2_FX_INVALID_HANDLE 9UL
#define LIBSSH2_FX_NO_SUCH_PATH 10UL
#define LIBSSH2_FX_FILE_ALREADY_EXISTS 11UL
#define LIBSSH2_FX_WRITE_PROTECT 12UL
#define LIBSSH2_FX_NO_MEDIA 13UL
#define LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM 14UL
#define LIBSSH2_FX_QUOTA_EXCEEDED 15UL
#define LIBSSH2_FX_UNKNOWN_PRINCIPLE 16UL /* Initial mis-spelling */
#define LIBSSH2_FX_UNKNOWN_PRINCIPAL 16UL
#define LIBSSH2_FX_LOCK_CONFlICT 17UL /* Initial mis-spelling */
#define LIBSSH2_FX_LOCK_CONFLICT 17UL
#define LIBSSH2_FX_DIR_NOT_EMPTY 18UL
#define LIBSSH2_FX_NOT_A_DIRECTORY 19UL
#define LIBSSH2_FX_INVALID_FILENAME 20UL
#define LIBSSH2_FX_LINK_LOOP 21UL
/* Returned by any function that would block during a read/write opperation */
/* Returned by any function that would block during a read/write operation */
#define LIBSSH2SFTP_EAGAIN LIBSSH2_ERROR_EAGAIN
/* SFTP API */

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2018-03-11.20; # UTC
scriptversion=2020-11-14.01; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -69,6 +69,11 @@ posix_mkdir=
# Desired mode of installed file.
mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
@@ -99,18 +104,28 @@ Options:
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-C install only if different (preserve data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Email bug reports to bug-automake@gnu.org.
Automake home page: https://www.gnu.org/software/automake/
"
while test $# -ne 0; do
@@ -137,8 +152,13 @@ while test $# -ne 0; do
-o) chowncmd="$chownprog $2"
shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
@@ -255,6 +275,10 @@ do
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
@@ -301,22 +325,6 @@ do
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
@@ -326,22 +334,20 @@ do
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
# Note that $RANDOM variable is not portable (e.g. dash); Use it
# The $RANDOM variable is not portable (e.g., dash). Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
trap '
ret=$?
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
exit $ret
' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p' feature.
# 'mkdir -p'.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
@@ -371,7 +377,6 @@ do
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
@@ -382,7 +387,7 @@ do
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
@@ -411,7 +416,7 @@ do
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
(umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
@@ -451,7 +456,18 @@ do
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
(umask $cp_umask &&
{ test -z "$stripcmd" || {
# Create $dsttmp read-write so that cp doesn't create it read-only,
# which would cause strip to fail.
if test -z "$doit"; then
: >"$dsttmp" # No need to fork-exec 'touch'.
else
$doit touch "$dsttmp"
fi
}
} &&
$doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
@@ -477,6 +493,13 @@ do
then
rm -f "$dsttmp"
else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
@@ -491,9 +514,9 @@ do
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
$doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1

10
libssh2/ltmain.sh Normal file → Executable file
View File

@@ -31,7 +31,7 @@
PROGRAM=libtool
PACKAGE=libtool
VERSION="2.4.6 Debian-2.4.6-10"
VERSION="2.4.6 Debian-2.4.6-15"
package_revision=2.4.6
@@ -387,7 +387,7 @@ EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
# putting '$debug_cmd' at the start of all your functions, you can get
# bash to show function call trace with:
#
# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
# debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
debug_cmd=${debug_cmd-":"}
exit_cmd=:
@@ -2141,7 +2141,7 @@ include the following information:
compiler: $LTCC
compiler flags: $LTCFLAGS
linker: $LD (gnu? $with_gnu_ld)
version: $progname $scriptversion Debian-2.4.6-10
version: $progname $scriptversion Debian-2.4.6-15
automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
@@ -7368,10 +7368,12 @@ func_mode_link ()
# -stdlib=* select c++ std lib with clang
# -fsanitize=* Clang/GCC memory and address sanitizer
# -fuse-ld=* Linker select flags for GCC
# -static-* direct GCC to link specific libraries statically
# -fcilkplus Cilk Plus language extension features for C/C++
-64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
-t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
-O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
-specs=*|-fsanitize=*|-fuse-ld=*)
-specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus)
func_quote_for_eval "$arg"
arg=$func_quote_for_eval_result
func_append compile_command " $arg"

10
libssh2/m4/libtool.m4 vendored
View File

@@ -1041,8 +1041,8 @@ int forced_loaded() { return 2;}
_LT_EOF
echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
$RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
cat > conftest.c << _LT_EOF
@@ -1071,11 +1071,11 @@ _LT_EOF
# to the OS version, if on x86, and 10.4, the deployment
# target defaults to 10.4. Don't you love it?
case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
10.0,*86*-darwin8*|10.0,*-darwin[[912]]*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
10.[[012]][[,.]]*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
10.*)
10.*|11.*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
esac
;;
@@ -1492,7 +1492,7 @@ need_locks=$enable_libtool_lock
m4_defun([_LT_PROG_AR],
[AC_CHECK_TOOLS(AR, [ar], false)
: ${AR=ar}
: ${AR_FLAGS=cru}
: ${AR_FLAGS=cr}
_LT_DECL([], [AR], [1], [The archiver])
_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])

View File

@@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify

View File

@@ -176,6 +176,7 @@ include(GNUInstallDirs)
set(SOURCES
${CRYPTO_SOURCES}
agent.c
agent_win.c
blf.h
bcrypt_pbkdf.c
blowfish.c
@@ -359,6 +360,11 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
target_compile_definitions(libssh2 PRIVATE LIBSSH2_DARWIN)
endif()
if(MSVC)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi /Od")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG")
endif()
if(CMAKE_VERSION VERSION_LESS "2.8.12")
# Fall back to over-linking dependencies
target_link_libraries(libssh2 ${LIBRARIES})
@@ -392,7 +398,7 @@ set(RUNTIME_DEPENDENCIES ${_RUNTIME_DEPENDENCIES} CACHE INTERNAL
## During package installation, install Libssh2Config.cmake
install(EXPORT Libssh2Config
NAMESPACE Libssh2::
DESTINATION lib/cmake/libssh2)
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libssh2)
## During build, register directly from build tree
# create Libssh2Config.cmake
@@ -424,4 +430,4 @@ write_basic_package_version_file(
COMPATIBILITY SameMajorVersion)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/Libssh2ConfigVersion.cmake
DESTINATION lib/cmake/libssh2)
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libssh2)

View File

@@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# Makefile.in generated by automake 1.16.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -100,8 +100,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = libssh2_config.h \
$(top_builddir)/example/libssh2_config.h
CONFIG_HEADER = libssh2_config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
@@ -138,10 +137,10 @@ 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 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
global.c blowfish.c bcrypt_pbkdf.c agent_win.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 agent.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
@@ -151,7 +150,7 @@ 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 blowfish.lo \
bcrypt_pbkdf.lo
bcrypt_pbkdf.lo agent_win.lo
am__objects_3 =
am__objects_4 = $(am__objects_3)
am_libssh2_la_OBJECTS = $(am__objects_2) $(am__objects_4)
@@ -178,7 +177,7 @@ am__v_at_1 =
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/agent.Plo \
am__depfiles_remade = ./$(DEPDIR)/agent.Plo ./$(DEPDIR)/agent_win.Plo \
./$(DEPDIR)/bcrypt_pbkdf.Plo ./$(DEPDIR)/blowfish.Plo \
./$(DEPDIR)/channel.Plo ./$(DEPDIR)/comp.Plo \
./$(DEPDIR)/crypt.Plo ./$(DEPDIR)/global.Plo \
@@ -218,8 +217,8 @@ am__can_run_installinfo = \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
$(LISP)libssh2_config.h.in
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
libssh2_config.h.in
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
@@ -236,8 +235,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/../Makefile.OpenSSL.inc \
$(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.inc \
$(srcdir)/../Makefile.libgcrypt.inc \
@@ -259,6 +256,12 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@@ -269,6 +272,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
@@ -302,6 +306,7 @@ LIBSSL_PREFIX = @LIBSSL_PREFIX@
LIBTOOL = @LIBTOOL@
LIBZ = @LIBZ@
LIBZ_PREFIX = @LIBZ_PREFIX@
LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBBCRYPT = @LTLIBBCRYPT@
@@ -343,6 +348,7 @@ abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
@@ -408,10 +414,10 @@ AUTOMAKE_OPTIONS = foreign nostdinc
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 \
blowfish.c bcrypt_pbkdf.c
blowfish.c bcrypt_pbkdf.c agent_win.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 blf.h
mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h agent.h
# Get the CRYPTO_CSOURCES, CRYPTO_HHEADERS and CRYPTO_LTLIBS defines
@@ -554,6 +560,7 @@ 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)/agent_win.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
@@ -664,7 +671,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
@@ -742,6 +748,7 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
distclean: distclean-am
-rm -f ./$(DEPDIR)/agent.Plo
-rm -f ./$(DEPDIR)/agent_win.Plo
-rm -f ./$(DEPDIR)/bcrypt_pbkdf.Plo
-rm -f ./$(DEPDIR)/blowfish.Plo
-rm -f ./$(DEPDIR)/channel.Plo
@@ -813,6 +820,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/agent.Plo
-rm -f ./$(DEPDIR)/agent_win.Plo
-rm -f ./$(DEPDIR)/bcrypt_pbkdf.Plo
-rm -f ./$(DEPDIR)/blowfish.Plo
-rm -f ./$(DEPDIR)/channel.Plo

View File

@@ -38,6 +38,7 @@
*/
#include "libssh2_priv.h"
#include "agent.h"
#include "misc.h"
#include <errno.h>
#ifdef HAVE_SYS_UN_H
@@ -50,6 +51,9 @@
#endif
#include "userauth.h"
#include "session.h"
#ifdef WIN32
#include <stdlib.h>
#endif
/* Requests from client to agent for protocol 1 key operations */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
@@ -90,58 +94,6 @@
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
/* non-blocking mode on agent connection is not yet implemented, but
for future use. */
typedef enum {
agent_NB_state_init = 0,
agent_NB_state_request_created,
agent_NB_state_request_length_sent,
agent_NB_state_request_sent,
agent_NB_state_response_length_received,
agent_NB_state_response_received
} agent_nonblocking_states;
typedef struct agent_transaction_ctx {
unsigned char *request;
size_t request_len;
unsigned char *response;
size_t response_len;
agent_nonblocking_states state;
} *agent_transaction_ctx_t;
typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent);
typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent,
agent_transaction_ctx_t transctx);
typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent);
struct agent_publickey {
struct list_node node;
/* this is the struct we expose externally */
struct libssh2_agent_publickey external;
};
struct agent_ops {
agent_connect_func connect;
agent_transact_func transact;
agent_disconnect_func disconnect;
};
struct _LIBSSH2_AGENT
{
LIBSSH2_SESSION *session; /* the session this "belongs to" */
libssh2_socket_t fd;
struct agent_ops *ops;
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
static int
agent_connect_unix(LIBSSH2_AGENT *agent)
@@ -175,6 +127,38 @@ agent_connect_unix(LIBSSH2_AGENT *agent)
return LIBSSH2_ERROR_NONE;
}
#define RECV_SEND_ALL(func, socket, buffer, length, flags, abstract) \
int rc; \
size_t finished = 0; \
\
while(finished < length) { \
rc = func(socket, \
(char *)buffer + finished, length - finished, \
flags, abstract); \
if(rc < 0) \
return rc; \
\
finished += rc; \
} \
\
return finished;
static ssize_t _send_all(LIBSSH2_SEND_FUNC(func), libssh2_socket_t socket,
const void *buffer, size_t length,
int flags, void **abstract)
{
RECV_SEND_ALL(func, socket, buffer, length, flags, abstract);
}
static ssize_t _recv_all(LIBSSH2_RECV_FUNC(func), libssh2_socket_t socket,
void *buffer, size_t length,
int flags, void **abstract)
{
RECV_SEND_ALL(func, socket, buffer, length, flags, abstract);
}
#undef RECV_SEND_ALL
static int
agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
{
@@ -184,7 +168,8 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Send the length of the request */
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);
rc = _send_all(agent->session->send, agent->fd,
buf, sizeof buf, 0, &agent->session->abstract);
if(rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
else if(rc < 0)
@@ -195,8 +180,8 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Send the request body */
if(transctx->state == agent_NB_state_request_length_sent) {
rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request,
transctx->request_len, 0);
rc = _send_all(agent->session->send, agent->fd, transctx->request,
transctx->request_len, 0, &agent->session->abstract);
if(rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
else if(rc < 0)
@@ -207,7 +192,8 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Receive the length of a response */
if(transctx->state == agent_NB_state_request_sent) {
rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0);
rc = _recv_all(agent->session->recv, agent->fd,
buf, sizeof buf, 0, &agent->session->abstract);
if(rc < 0) {
if(rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
@@ -225,8 +211,8 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Receive the response body */
if(transctx->state == agent_NB_state_response_length_received) {
rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response,
transctx->response_len, 0);
rc = _recv_all(agent->session->recv, agent->fd, transctx->response,
transctx->response_len, 0, &agent->session->abstract);
if(rc < 0) {
if(rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
@@ -274,7 +260,7 @@ static int
agent_connect_pageant(LIBSSH2_AGENT *agent)
{
HWND hwnd;
hwnd = FindWindow("Pageant", "Pageant");
hwnd = FindWindowA("Pageant", "Pageant");
if(!hwnd)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"failed connecting agent");
@@ -297,14 +283,14 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL,
"illegal input");
hwnd = FindWindow("Pageant", "Pageant");
hwnd = FindWindowA("Pageant", "Pageant");
if(!hwnd)
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"found no pageant");
snprintf(mapname, sizeof(mapname),
"PageantRequest%08x%c", (unsigned)GetCurrentThreadId(), '\0');
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
filemap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, PAGEANT_MAX_MSGLEN, mapname);
if(filemap == NULL || filemap == INVALID_HANDLE_VALUE)
@@ -370,6 +356,7 @@ static struct {
} supported_backends[] = {
#ifdef WIN32
{"Pageant", &agent_ops_pageant},
{"OpenSSH", &agent_ops_openssh},
#endif /* WIN32 */
#ifdef PF_UNIX
{"Unix", &agent_ops_unix},
@@ -407,6 +394,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
_libssh2_store_u32(&s, 0);
transctx->request_len = s - transctx->request;
transctx->send_recv_total = 0;
transctx->state = agent_NB_state_request_created;
}
@@ -507,6 +495,7 @@ agent_list_identities(LIBSSH2_AGENT *agent)
if(transctx->state == agent_NB_state_init) {
transctx->request = &c;
transctx->request_len = 1;
transctx->send_recv_total = 0;
transctx->state = agent_NB_state_request_created;
}
@@ -522,7 +511,9 @@ agent_list_identities(LIBSSH2_AGENT *agent)
rc = agent->ops->transact(agent, transctx);
if(rc) {
goto error;
LIBSSH2_FREE(agent->session, transctx->response);
transctx->response = NULL;
return rc;
}
transctx->request = NULL;
@@ -681,6 +672,12 @@ libssh2_agent_init(LIBSSH2_SESSION *session)
agent->identity_agent_path = NULL;
_libssh2_list_init(&agent->head);
#ifdef WIN32
agent->pipe = INVALID_HANDLE_VALUE;
memset(&agent->overlapped, 0, sizeof(OVERLAPPED));
agent->pending_io = FALSE;
#endif
return agent;
}

112
libssh2/src/agent.h Normal file
View File

@@ -0,0 +1,112 @@
#ifndef __LIBSSH2_AGENT_H
#define __LIBSSH2_AGENT_H
/*
* Copyright (c) 2009 by Daiki Ueno
* Copyright (C) 2010-2014 by Daniel Stenberg
* 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"
#include "misc.h"
#include "session.h"
#ifdef WIN32
#include <stdlib.h>
#endif
/* non-blocking mode on agent connection is not yet implemented, but
for future use. */
typedef enum {
agent_NB_state_init = 0,
agent_NB_state_request_created,
agent_NB_state_request_length_sent,
agent_NB_state_request_sent,
agent_NB_state_response_length_received,
agent_NB_state_response_received
} agent_nonblocking_states;
typedef struct agent_transaction_ctx {
unsigned char *request;
size_t request_len;
unsigned char *response;
size_t response_len;
agent_nonblocking_states state;
size_t send_recv_total;
} *agent_transaction_ctx_t;
typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent);
typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent,
agent_transaction_ctx_t transctx);
typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent);
struct agent_publickey {
struct list_node node;
/* this is the struct we expose externally */
struct libssh2_agent_publickey external;
};
struct agent_ops {
agent_connect_func connect;
agent_transact_func transact;
agent_disconnect_func disconnect;
};
struct _LIBSSH2_AGENT
{
LIBSSH2_SESSION *session; /* the session this "belongs to" */
libssh2_socket_t fd;
struct agent_ops *ops;
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 WIN32
OVERLAPPED overlapped;
HANDLE pipe;
BOOL pending_io;
#endif
};
#ifdef WIN32
extern struct agent_ops agent_ops_openssh;
#endif
#endif /* __LIBSSH2_AGENT_H */

361
libssh2/src/agent_win.c Normal file
View File

@@ -0,0 +1,361 @@
/*
* Copyright (c) 2009 by Daiki Ueno
* Copyright (C) 2010-2014 by Daniel Stenberg
* 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"
#include "agent.h"
#include "misc.h"
#include <errno.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#else
/* Use the existence of sys/un.h as a test if Unix domain socket is
supported. winsock*.h define PF_UNIX/AF_UNIX but do not actually
support them. */
#undef PF_UNIX
#endif
#include "userauth.h"
#include "session.h"
#ifdef WIN32
#include <stdlib.h>
#endif
#ifdef WIN32
/* Code to talk to OpenSSH was taken and modified from the Win32 port of
* Portable OpenSSH by the PowerShell team. Commit
* 8ab565c53f3619d6a1f5ac229e212cad8a52852c of
* https://github.com/PowerShell/openssh-portable.git was used as the base,
* specificaly the following files:
*
* - contrib\win32\win32compat\fileio.c
* - Structure of agent_connect_openssh from ssh_get_authentication_socket
* - Structure of agent_transact_openssh from ssh_request_reply
* - contrib\win32\win32compat\wmain_common.c
* - Windows equivalent functions for common Unix functions, inlined into
* this implementation
* - fileio_connect replacing connect
* - fileio_read replacing read
* - fileio_write replacing write
* - fileio_close replacing close
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for connecting the local authentication agent.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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.
*
* 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.
*
* Copyright (c) 2015 Microsoft Corp.
* All rights reserved
*
* Microsoft openssh win32 port
*
* 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.
*
* 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.
*/
#define WIN32_OPENSSH_AGENT_SOCK "\\\\.\\pipe\\openssh-ssh-agent"
static int
agent_connect_openssh(LIBSSH2_AGENT *agent)
{
int ret = LIBSSH2_ERROR_NONE;
const char *path;
HANDLE pipe = INVALID_HANDLE_VALUE;
HANDLE event = NULL;
path = agent->identity_agent_path;
if(!path) {
path = getenv("SSH_AUTH_SOCK");
if(!path)
path = WIN32_OPENSSH_AGENT_SOCK;
}
for(;;) {
pipe = CreateFileA(
path,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
/* Non-blocking mode for agent connections is not implemented at
* the point this was implemented. The code for Win32 OpenSSH
* should support non-blocking IO, but the code calling it doesn't
* support it as of yet.
* When non-blocking IO is implemented for the surrounding code,
* uncomment the following line to enable support within the Win32
* OpenSSH code.
*/
/* FILE_FLAG_OVERLAPPED | */
SECURITY_SQOS_PRESENT |
SECURITY_IDENTIFICATION,
NULL
);
if(pipe != INVALID_HANDLE_VALUE)
break;
if(GetLastError() != ERROR_PIPE_BUSY)
break;
/* Wait up to 1 second for a pipe instance to become available */
if(!WaitNamedPipeA(path, 1000))
break;
}
if(pipe == INVALID_HANDLE_VALUE) {
ret = _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"unable to connect to agent pipe");
goto cleanup;
}
if(SetHandleInformation(pipe, HANDLE_FLAG_INHERIT, 0) == FALSE) {
ret = _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"unable to set handle information of agent pipe");
goto cleanup;
}
event = CreateEventA(NULL, TRUE, FALSE, NULL);
if(event == NULL) {
ret = _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
"unable to create async I/O event");
goto cleanup;
}
agent->pipe = pipe;
pipe = INVALID_HANDLE_VALUE;
agent->overlapped.hEvent = event;
event = NULL;
agent->fd = 0; /* Mark as the connection has been established */
cleanup:
if(event != NULL)
CloseHandle(event);
if(pipe != INVALID_HANDLE_VALUE)
CloseHandle(pipe);
return ret;
}
#define RECV_SEND_ALL(func, agent, buffer, length, total) \
DWORD bytes_transfered; \
BOOL ret; \
DWORD err; \
int rc; \
\
while(*total < length) { \
if(!agent->pending_io) \
ret = func(agent->pipe, (char *)buffer + *total, \
(DWORD)(length - *total), &bytes_transfered, \
&agent->overlapped); \
else \
ret = GetOverlappedResult(agent->pipe, &agent->overlapped, \
&bytes_transfered, FALSE); \
\
*total += bytes_transfered; \
if(!ret) { \
err = GetLastError(); \
if((!agent->pending_io && ERROR_IO_PENDING == err) \
|| (agent->pending_io && ERROR_IO_INCOMPLETE == err)) { \
agent->pending_io = TRUE; \
return LIBSSH2_ERROR_EAGAIN; \
} \
\
return LIBSSH2_ERROR_SOCKET_NONE; \
} \
agent->pending_io = FALSE; \
} \
\
rc = (int)*total; \
*total = 0; \
return rc;
static int
win32_openssh_send_all(LIBSSH2_AGENT *agent, void *buffer, size_t length,
size_t *send_recv_total)
{
RECV_SEND_ALL(WriteFile, agent, buffer, length, send_recv_total)
}
static int
win32_openssh_recv_all(LIBSSH2_AGENT *agent, void *buffer, size_t length,
size_t *send_recv_total)
{
RECV_SEND_ALL(ReadFile, agent, buffer, length, send_recv_total)
}
#undef RECV_SEND_ALL
static int
agent_transact_openssh(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
{
unsigned char buf[4];
int rc;
/* Send the length of the request */
if(transctx->state == agent_NB_state_request_created) {
_libssh2_htonu32(buf, (uint32_t)transctx->request_len);
rc = win32_openssh_send_all(agent, buf, sizeof buf,
&transctx->send_recv_total);
if(rc == LIBSSH2_ERROR_EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
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) {
rc = win32_openssh_send_all(agent, transctx->request,
transctx->request_len,
&transctx->send_recv_total);
if(rc == LIBSSH2_ERROR_EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
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 the body */
if(transctx->state == agent_NB_state_request_sent) {
rc = win32_openssh_recv_all(agent, buf, sizeof buf,
&transctx->send_recv_total);
if(rc == LIBSSH2_ERROR_EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
else if(rc < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
"agent recv failed");
transctx->response_len = _libssh2_ntohu32(buf);
transctx->response = LIBSSH2_ALLOC(agent->session,
transctx->response_len);
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) {
rc = win32_openssh_recv_all(agent, transctx->response,
transctx->response_len,
&transctx->send_recv_total);
if(rc == LIBSSH2_ERROR_EAGAIN)
return LIBSSH2_ERROR_EAGAIN;
else if(rc < 0)
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
"agent recv failed");
transctx->state = agent_NB_state_response_received;
}
return LIBSSH2_ERROR_NONE;
}
static int
agent_disconnect_openssh(LIBSSH2_AGENT *agent)
{
if(!CancelIo(agent->pipe))
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
"failed to cancel pending IO of agent pipe");
if(!CloseHandle(agent->overlapped.hEvent))
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
"failed to close handle to async I/O event");
agent->overlapped.hEvent = NULL;
/* let queued APCs (if any) drain */
SleepEx(0, TRUE);
if(!CloseHandle(agent->pipe))
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
"failed to close handle to agent pipe");
agent->pipe = INVALID_HANDLE_VALUE;
agent->fd = LIBSSH2_INVALID_SOCKET;
return LIBSSH2_ERROR_NONE;
}
struct agent_ops agent_ops_openssh = {
agent_connect_openssh,
agent_transact_openssh,
agent_disconnect_openssh
};
#endif /* WIN32 */

View File

@@ -36,7 +36,7 @@
* 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
* 3. Subsequently the magic string to be encrypted is lengthened and modified
* to "OxychromaticBlowfishSwatDynamite"
* 4. The hash function is defined to perform 64 rounds of initial state
* expansion. (More rounds are performed by iterating the hash.)
@@ -81,7 +81,7 @@ bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
&j);
for(i = 0; i < 64; i++)
blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
/* copy out */
for(i = 0; i < BCRYPT_BLOCKS; i++) {
@@ -158,7 +158,7 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
}
/*
* pbkdf2 deviation: ouput the key material non-linearly.
* pbkdf2 deviation: output the key material non-linearly.
*/
amt = MINIMUM(amt, keylen);
for(i = 0; i < amt; i++) {

View File

@@ -1,3 +1,5 @@
#ifndef __LIBSSH2_BLF_H
#define __LIBSSH2_BLF_H
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
/*
* Blowfish - a fast block cipher designed by Bruce Schneier
@@ -31,9 +33,6 @@
* 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.
@@ -87,4 +86,4 @@ int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
uint8_t *key, size_t keylen, unsigned int rounds);
#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */
#endif /* _BLF_H */
#endif /* __LIBSSH2_BLF_H */

View File

@@ -236,6 +236,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
return NULL;
}
else if(rc) {
_libssh2_error(session, rc, "Unexpected error");
goto channel_error;
}
@@ -1021,6 +1022,158 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
"channel request-pty");
}
/**
* channel_request_auth_agent
* The actual re-entrant method which requests an auth agent.
* */
static int channel_request_auth_agent(LIBSSH2_CHANNEL *channel,
const char *request_str,
int request_str_len)
{
LIBSSH2_SESSION *session = channel->session;
unsigned char *s;
static const unsigned char reply_codes[3] =
{ SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
int rc;
if(channel->req_auth_agent_state == libssh2_NB_state_idle) {
/* Only valid options are "auth-agent-req" and
* "auth-agent-req_at_openssh.com" so we make sure it is not
* actually longer than the longest possible. */
if(request_str_len > 26) {
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"request_str length too large");
}
/*
* Length: 24 or 36 = packet_type(1) + channel(4) + req_len(4) +
* request_str (variable) + want_reply (1) */
channel->req_auth_agent_packet_len = 10 + request_str_len;
/* Zero out the requireev state to reset */
memset(&channel->req_auth_agent_requirev_state, 0,
sizeof(channel->req_auth_agent_requirev_state));
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Requesting auth agent on channel %lu/%lu",
channel->local.id, channel->remote.id);
/*
* byte SSH_MSG_CHANNEL_REQUEST
* uint32 recipient channel
* string "auth-agent-req"
* boolean want reply
* */
s = channel->req_auth_agent_packet;
*(s++) = SSH_MSG_CHANNEL_REQUEST;
_libssh2_store_u32(&s, channel->remote.id);
_libssh2_store_str(&s, (char *)request_str, request_str_len);
*(s++) = 0x01;
channel->req_auth_agent_state = libssh2_NB_state_created;
}
if(channel->req_auth_agent_state == libssh2_NB_state_created) {
/* Send the packet, we can use sizeof() on the packet because it
* is always completely filled; there are no variable length fields. */
rc = _libssh2_transport_send(session, channel->req_auth_agent_packet,
channel->req_auth_agent_packet_len,
NULL, 0);
if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, rc,
"Would block sending auth-agent request");
}
else if(rc) {
channel->req_auth_agent_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Unable to send auth-agent request");
}
_libssh2_htonu32(channel->req_auth_agent_local_channel,
channel->local.id);
channel->req_auth_agent_state = libssh2_NB_state_sent;
}
if(channel->req_auth_agent_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->req_auth_agent_local_channel,
4, &channel->req_auth_agent_requirev_state);
if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
else if(rc) {
channel->req_auth_agent_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Failed to request auth-agent");
}
code = data[0];
LIBSSH2_FREE(session, data);
channel->req_auth_agent_state = libssh2_NB_state_idle;
if(code == SSH_MSG_CHANNEL_SUCCESS)
return 0;
}
return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
"Unable to complete request for auth-agent");
}
/**
* libssh2_channel_request_auth_agent
* Requests that agent forwarding be enabled for the session. The
* request must be sent over a specific channel, which starts the agent
* listener on the remote side. Once the channel is closed, the agent
* listener continues to exist.
* */
LIBSSH2_API int
libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel)
{
int rc;
if(!channel)
return LIBSSH2_ERROR_BAD_USE;
/* The current RFC draft for agent forwarding says you're supposed to
* send "auth-agent-req," but most SSH servers out there right now
* actually expect "auth-agent-req@openssh.com", so we try that
* first. */
if(channel->req_auth_agent_try_state == libssh2_NB_state_idle) {
BLOCK_ADJUST(rc, channel->session,
channel_request_auth_agent(channel,
"auth-agent-req@openssh.com",
26));
/* If we failed (but not with EAGAIN), then we move onto
* the next step to try another request type. */
if(rc != 0 && rc != LIBSSH2_ERROR_EAGAIN)
channel->req_auth_agent_try_state = libssh2_NB_state_sent;
}
if(channel->req_auth_agent_try_state == libssh2_NB_state_sent) {
BLOCK_ADJUST(rc, channel->session,
channel_request_auth_agent(channel,
"auth-agent-req", 14));
/* If we failed without an EAGAIN, then move on with this
* state machine. */
if(rc != 0 && rc != LIBSSH2_ERROR_EAGAIN)
channel->req_auth_agent_try_state = libssh2_NB_state_sent1;
}
/* If things are good, reset the try state. */
if(rc == 0)
channel->req_auth_agent_try_state = libssh2_NB_state_idle;
return rc;
}
/*
* libssh2_channel_request_pty_ex
* Duh... Request a PTY
@@ -1185,7 +1338,11 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
border */
unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
_libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
if(_libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2)) {
return _libssh2_error(session, LIBSSH2_ERROR_RANDGEN,
"Unable to get random bytes "
"for x11-req cookie");
}
for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
}

View File

@@ -39,6 +39,7 @@
#include "libssh2_priv.h"
#ifdef LIBSSH2_HAVE_ZLIB
#include <zlib.h>
#undef compress /* dodge name clash with ZLIB macro */
#endif
#include "comp.h"

View File

@@ -1,6 +1,5 @@
#ifndef __LIBSSH2_COMP_H
#define __LIBSSH2_COMP_H
/* Copyright (C) 2009-2010 by Daniel Stenberg
*
* Redistribution and use in source and binary forms,

View File

@@ -1,3 +1,5 @@
#ifndef __LIBSSH2_CRYPTO_H
#define __LIBSSH2_CRYPTO_H
/* Copyright (C) 2009, 2010 Simon Josefsson
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
* Copyright (C) 2010-2019 Daniel Stenberg
@@ -35,8 +37,6 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef LIBSSH2_CRYPTO_H
#define LIBSSH2_CRYPTO_H
#ifdef LIBSSH2_OPENSSL
#include "openssl.h"
@@ -170,7 +170,7 @@ int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
unsigned const char *passphrase);
libssh2_curve_type
_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key);
_libssh2_ecdsa_get_curve_type(libssh2_ecdsa_ctx *ec_ctx);
int
_libssh2_ecdsa_curve_type_from_name(const char *name,
@@ -181,8 +181,8 @@ _libssh2_ecdsa_curve_type_from_name(const char *name,
#if LIBSSH2_ED25519
int
_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_ed25519_ctx **ctx,
uint8_t **out_public_key, uint8_t **out_private_key);
_libssh2_curve25519_new(LIBSSH2_SESSION *session, uint8_t **out_public_key,
uint8_t **out_private_key);
int
_libssh2_curve25519_gen_k(_libssh2_bn **k,
@@ -245,4 +245,4 @@ int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
size_t privatekeydata_len,
const char *passphrase);
#endif
#endif /* __LIBSSH2_CRYPTO_H */

View File

@@ -62,7 +62,8 @@ libssh2_exit(void)
_libssh2_initialized--;
if(!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) {
if(_libssh2_initialized == 0 &&
!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) {
libssh2_crypto_exit();
}

View File

@@ -647,7 +647,7 @@ hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session,
{
unsigned char *r, *s, *name;
size_t r_len, s_len, name_len;
unsigned int len;
uint32_t len;
struct string_buf buf;
libssh2_ecdsa_ctx *ctx = (libssh2_ecdsa_ctx *) (*abstract);
@@ -709,7 +709,7 @@ hostkey_method_ssh_ecdsa_signv(LIBSSH2_SESSION * session,
void **abstract)
{
libssh2_ecdsa_ctx *ec_ctx = (libssh2_ecdsa_ctx *) (*abstract);
libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_ctx);
libssh2_curve_type type = _libssh2_ecdsa_get_curve_type(ec_ctx);
int ret = 0;
if(type == LIBSSH2_EC_CURVE_NISTP256) {
@@ -783,6 +783,42 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521 = {
hostkey_method_ssh_ecdsa_dtor,
};
static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp256_cert = {
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
SHA256_DIGEST_LENGTH,
NULL,
hostkey_method_ssh_ecdsa_initPEM,
hostkey_method_ssh_ecdsa_initPEMFromMemory,
NULL,
hostkey_method_ssh_ecdsa_signv,
NULL, /* encrypt */
hostkey_method_ssh_ecdsa_dtor,
};
static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp384_cert = {
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
SHA384_DIGEST_LENGTH,
NULL,
hostkey_method_ssh_ecdsa_initPEM,
hostkey_method_ssh_ecdsa_initPEMFromMemory,
NULL,
hostkey_method_ssh_ecdsa_signv,
NULL, /* encrypt */
hostkey_method_ssh_ecdsa_dtor,
};
static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521_cert = {
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
SHA512_DIGEST_LENGTH,
NULL,
hostkey_method_ssh_ecdsa_initPEM,
hostkey_method_ssh_ecdsa_initPEMFromMemory,
NULL,
hostkey_method_ssh_ecdsa_signv,
NULL, /* encrypt */
hostkey_method_ssh_ecdsa_dtor,
};
#endif /* LIBSSH2_ECDSA */
#if LIBSSH2_ED25519
@@ -999,6 +1035,9 @@ static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = {
&hostkey_method_ecdsa_ssh_nistp256,
&hostkey_method_ecdsa_ssh_nistp384,
&hostkey_method_ecdsa_ssh_nistp521,
&hostkey_method_ecdsa_ssh_nistp256_cert,
&hostkey_method_ecdsa_ssh_nistp384_cert,
&hostkey_method_ecdsa_ssh_nistp521_cert,
#endif
#if LIBSSH2_ED25519
&hostkey_method_ssh_ed25519,

File diff suppressed because it is too large Load Diff

View File

@@ -955,7 +955,7 @@ libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
{
FILE *file;
int num = 0;
char buf[2048];
char buf[4092];
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
return _libssh2_error(hosts->session,
@@ -1194,7 +1194,7 @@ libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
struct known_host *node;
FILE *file;
int rc = LIBSSH2_ERROR_NONE;
char buffer[2048];
char buffer[4092];
/* we only support this single file type for now, bail out on all other
attempts */

View File

@@ -1,3 +1,5 @@
#ifndef __LIBSSH2_LIBGCRYPT_H
#define __LIBSSH2_LIBGCRYPT_H
/*
* Copyright (C) 2008, 2009, 2010 Simon Josefsson
* Copyright (C) 2006, 2007, The Written Word, Inc.
@@ -66,7 +68,7 @@
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
#define _libssh2_random(buf, len) \
(gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1)
(gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 0)
#define libssh2_prepare_iovec(vec, len) /* Empty. */
@@ -232,3 +234,4 @@ extern int _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
_libssh2_bn *f, _libssh2_bn *p);
extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
#endif /* __LIBSSH2_LIBGCRYPT_H */

View File

@@ -3,19 +3,13 @@
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
#undef CRAY_STACKSEG_END
/* Define to 1 if using `alloca.c'. */
/* Define to 1 if using 'alloca.c'. */
#undef C_ALLOCA
/* Define to 1 if you have `alloca', as a function or macro. */
/* Define to 1 if you have 'alloca', as a function or macro. */
#undef HAVE_ALLOCA
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
/* Define to 1 if <alloca.h> works. */
#undef HAVE_ALLOCA_H
/* Define to 1 if you have the <arpa/inet.h> header file. */
@@ -76,9 +70,6 @@
/* Define to 1 if the compiler supports the 'long long' data type. */
#undef HAVE_LONGLONG
/* 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
@@ -222,7 +213,9 @@
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define to 1 if you have the ANSI C header files. */
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* Version number of package */
@@ -240,11 +233,6 @@
# endif
#endif
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS

View File

@@ -1,3 +1,5 @@
#ifndef __LIBSSH2_PRIV_H
#define __LIBSSH2_PRIV_H
/* Copyright (c) 2004-2008, 2010, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009-2014 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson
@@ -37,9 +39,6 @@
* OF SUCH DAMAGE.
*/
#ifndef LIBSSH2_PRIV_H
#define LIBSSH2_PRIV_H 1
#define LIBSSH2_LIBRARY
#include "libssh2_config.h"
@@ -110,14 +109,19 @@
#define inline __inline
#endif
/* Provide iovec / writev on WIN32 platform. */
#ifdef WIN32
/* 3DS doesn't seem to have iovec */
#if defined(WIN32) || defined(_3DS)
struct iovec {
size_t iov_len;
void *iov_base;
};
#endif
/* Provide iovec / writev on WIN32 platform. */
#ifdef WIN32
static inline int writev(int sock, struct iovec *iov, int nvecs)
{
DWORD ret;
@@ -452,6 +456,13 @@ struct _LIBSSH2_CHANNEL
/* State variables used in libssh2_channel_handle_extended_data2() */
libssh2_nonblocking_states extData2_state;
/* State variables used in libssh2_channel_request_auth_agent() */
libssh2_nonblocking_states req_auth_agent_try_state;
libssh2_nonblocking_states req_auth_agent_state;
unsigned char req_auth_agent_packet[36];
size_t req_auth_agent_packet_len;
unsigned char req_auth_agent_local_channel[4];
packet_requirev_state_t req_auth_agent_requirev_state;
};
struct _LIBSSH2_LISTENER
@@ -1140,4 +1151,4 @@ endings either CRLF or LF so 't' is appropriate.
#define FOPEN_APPENDTEXT "a"
#endif
#endif /* LIBSSH2_H */
#endif /* __LIBSSH2_PRIV_H */

View File

@@ -1,6 +1,5 @@
#ifndef __LIBSSH2_MAC_H
#define __LIBSSH2_MAC_H
/* Copyright (C) 2009-2010 by Daniel Stenberg
*
* Redistribution and use in source and binary forms,

View File

@@ -94,7 +94,7 @@ _libssh2_mbedtls_safe_free(void *buf, int len)
#ifdef LIBSSH2_CLEAR_MEMORY
if(len > 0)
memset(buf, 0, len);
_libssh2_explicit_zero(buf, len);
#endif
mbedtls_free(buf);
@@ -272,7 +272,7 @@ _libssh2_mbedtls_bignum_random(_libssh2_bn *bn, int bits, int top, int bottom)
if(err)
return -1;
/* Zero unsued bits above the most significant bit*/
/* Zero unused bits above the most significant bit*/
for(i = len*8 - 1; bits <= i; --i) {
err = mbedtls_mpi_set_bit(bn, i, 0);
if(err)
@@ -730,4 +730,522 @@ _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
*dhctx = NULL;
}
#if LIBSSH2_ECDSA
/*******************************************************************/
/*
* mbedTLS backend: ECDSA functions
*/
/*
* _libssh2_ecdsa_create_key
*
* Creates a local private key based on input curve
* and returns octal value and octal length
*
*/
int
_libssh2_mbedtls_ecdsa_create_key(LIBSSH2_SESSION *session,
_libssh2_ec_key **privkey,
unsigned char **pubkey_oct,
size_t *pubkey_oct_len,
libssh2_curve_type curve)
{
size_t plen = 0;
*privkey = LIBSSH2_ALLOC(session, sizeof(mbedtls_ecp_keypair));
if(*privkey == NULL)
goto failed;
mbedtls_ecdsa_init(*privkey);
if(mbedtls_ecdsa_genkey(*privkey, (mbedtls_ecp_group_id)curve,
mbedtls_ctr_drbg_random,
&_libssh2_mbedtls_ctr_drbg) != 0)
goto failed;
plen = 2 * mbedtls_mpi_size(&(*privkey)->grp.P) + 1;
*pubkey_oct = LIBSSH2_ALLOC(session, plen);
if(*pubkey_oct == NULL)
goto failed;
if(mbedtls_ecp_point_write_binary(&(*privkey)->grp, &(*privkey)->Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
pubkey_oct_len, *pubkey_oct, plen) == 0)
return 0;
failed:
_libssh2_mbedtls_ecdsa_free(*privkey);
_libssh2_mbedtls_safe_free(*pubkey_oct, plen);
*privkey = NULL;
return -1;
}
/* _libssh2_ecdsa_curve_name_with_octal_new
*
* Creates a new public key given an octal string, length and type
*
*/
int
_libssh2_mbedtls_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx **ctx,
const unsigned char *k,
size_t k_len,
libssh2_curve_type curve)
{
*ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
if(*ctx == NULL)
goto failed;
mbedtls_ecdsa_init(*ctx);
if(mbedtls_ecp_group_load(&(*ctx)->grp, (mbedtls_ecp_group_id)curve) != 0)
goto failed;
if(mbedtls_ecp_point_read_binary(&(*ctx)->grp, &(*ctx)->Q, k, k_len) != 0)
goto failed;
if(mbedtls_ecp_check_pubkey(&(*ctx)->grp, &(*ctx)->Q) == 0)
return 0;
failed:
_libssh2_mbedtls_ecdsa_free(*ctx);
*ctx = NULL;
return -1;
}
/* _libssh2_ecdh_gen_k
*
* Computes the shared secret K given a local private key,
* remote public key and length
*/
int
_libssh2_mbedtls_ecdh_gen_k(_libssh2_bn **k,
_libssh2_ec_key *privkey,
const unsigned char *server_pubkey,
size_t server_pubkey_len)
{
mbedtls_ecp_point pubkey;
int rc = 0;
if(*k == NULL)
return -1;
mbedtls_ecp_point_init(&pubkey);
if(mbedtls_ecp_point_read_binary(&privkey->grp, &pubkey,
server_pubkey, server_pubkey_len) != 0) {
rc = -1;
goto cleanup;
}
if(mbedtls_ecdh_compute_shared(&privkey->grp, *k,
&pubkey, &privkey->d,
mbedtls_ctr_drbg_random,
&_libssh2_mbedtls_ctr_drbg) != 0) {
rc = -1;
goto cleanup;
}
if(mbedtls_ecp_check_privkey(&privkey->grp, *k) != 0)
rc = -1;
cleanup:
mbedtls_ecp_point_free(&pubkey);
return rc;
}
#define LIBSSH2_MBEDTLS_ECDSA_VERIFY(digest_type) \
{ \
unsigned char hsh[SHA##digest_type##_DIGEST_LENGTH]; \
\
if(libssh2_sha##digest_type(m, m_len, hsh) == 0) { \
rc = mbedtls_ecdsa_verify(&ctx->grp, hsh, \
SHA##digest_type##_DIGEST_LENGTH, \
&ctx->Q, &pr, &ps); \
} \
\
}
/* _libssh2_ecdsa_sign
*
* Verifies the ECDSA signature of a hashed message
*
*/
int
_libssh2_mbedtls_ecdsa_verify(libssh2_ecdsa_ctx *ctx,
const unsigned char *r, size_t r_len,
const unsigned char *s, size_t s_len,
const unsigned char *m, size_t m_len)
{
mbedtls_mpi pr, ps;
int rc = -1;
mbedtls_mpi_init(&pr);
mbedtls_mpi_init(&ps);
if(mbedtls_mpi_read_binary(&pr, r, r_len) != 0)
goto cleanup;
if(mbedtls_mpi_read_binary(&ps, s, s_len) != 0)
goto cleanup;
switch(_libssh2_ecdsa_get_curve_type(ctx)) {
case LIBSSH2_EC_CURVE_NISTP256:
LIBSSH2_MBEDTLS_ECDSA_VERIFY(256);
break;
case LIBSSH2_EC_CURVE_NISTP384:
LIBSSH2_MBEDTLS_ECDSA_VERIFY(384);
break;
case LIBSSH2_EC_CURVE_NISTP521:
LIBSSH2_MBEDTLS_ECDSA_VERIFY(512);
break;
default:
rc = -1;
}
cleanup:
mbedtls_mpi_free(&pr);
mbedtls_mpi_free(&ps);
return (rc == 0) ? 0 : -1;
}
static int
_libssh2_mbedtls_parse_eckey(libssh2_ecdsa_ctx **ctx,
mbedtls_pk_context *pkey,
LIBSSH2_SESSION *session,
const unsigned char *data,
size_t data_len,
const unsigned char *pwd)
{
size_t pwd_len;
pwd_len = pwd ? strlen((const char *) pwd) : 0;
if(mbedtls_pk_parse_key(pkey, data, data_len, pwd, pwd_len) != 0)
goto failed;
if(mbedtls_pk_get_type(pkey) != MBEDTLS_PK_ECKEY)
goto failed;
*ctx = LIBSSH2_ALLOC(session, sizeof(libssh2_ecdsa_ctx));
if(*ctx == NULL)
goto failed;
mbedtls_ecdsa_init(*ctx);
if(mbedtls_ecdsa_from_keypair(*ctx, mbedtls_pk_ec(*pkey)) == 0)
return 0;
failed:
_libssh2_mbedtls_ecdsa_free(*ctx);
*ctx = NULL;
return -1;
}
static int
_libssh2_mbedtls_parse_openssh_key(libssh2_ecdsa_ctx **ctx,
LIBSSH2_SESSION *session,
const unsigned char *data,
size_t data_len,
const unsigned char *pwd)
{
libssh2_curve_type type;
unsigned char *name = NULL;
struct string_buf *decrypted = NULL;
size_t curvelen, exponentlen, pointlen;
unsigned char *curve, *exponent, *point_buf;
if(_libssh2_openssh_pem_parse_memory(session, pwd,
(const char *)data, data_len,
&decrypted) != 0)
goto failed;
if(_libssh2_get_string(decrypted, &name, NULL) != 0)
goto failed;
if(_libssh2_mbedtls_ecdsa_curve_type_from_name((const char *)name,
&type) != 0)
goto failed;
if(_libssh2_get_string(decrypted, &curve, &curvelen) != 0)
goto failed;
if(_libssh2_get_string(decrypted, &point_buf, &pointlen) != 0)
goto failed;
if(_libssh2_get_bignum_bytes(decrypted, &exponent, &exponentlen) != 0)
goto failed;
*ctx = LIBSSH2_ALLOC(session, sizeof(libssh2_ecdsa_ctx));
if(*ctx == NULL)
goto failed;
mbedtls_ecdsa_init(*ctx);
if(mbedtls_ecp_group_load(&(*ctx)->grp, (mbedtls_ecp_group_id)type) != 0)
goto failed;
if(mbedtls_mpi_read_binary(&(*ctx)->d, exponent, exponentlen) != 0)
goto failed;
if(mbedtls_ecp_mul(&(*ctx)->grp, &(*ctx)->Q,
&(*ctx)->d, &(*ctx)->grp.G,
mbedtls_ctr_drbg_random,
&_libssh2_mbedtls_ctr_drbg) != 0)
goto failed;
if(mbedtls_ecp_check_privkey(&(*ctx)->grp, &(*ctx)->d) == 0)
goto cleanup;
failed:
_libssh2_mbedtls_ecdsa_free(*ctx);
*ctx = NULL;
cleanup:
if(decrypted) {
_libssh2_string_buf_free(session, decrypted);
}
return (*ctx == NULL) ? -1 : 0;
}
/* _libssh2_ecdsa_new_private
*
* Creates a new private key given a file path and password
*
*/
int
_libssh2_mbedtls_ecdsa_new_private(libssh2_ecdsa_ctx **ctx,
LIBSSH2_SESSION *session,
const char *filename,
const unsigned char *pwd)
{
mbedtls_pk_context pkey;
unsigned char *data;
size_t data_len;
if(mbedtls_pk_load_file(filename, &data, &data_len) != 0)
goto cleanup;
mbedtls_pk_init(&pkey);
if(_libssh2_mbedtls_parse_eckey(ctx, &pkey, session,
data, data_len, pwd) == 0)
goto cleanup;
_libssh2_mbedtls_parse_openssh_key(ctx, session, data, data_len, pwd);
cleanup:
mbedtls_pk_free(&pkey);
_libssh2_mbedtls_safe_free(data, data_len);
return (*ctx == NULL) ? -1 : 0;
}
/* _libssh2_ecdsa_new_private
*
* Creates a new private key given a file data and password
*
*/
int
_libssh2_mbedtls_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx **ctx,
LIBSSH2_SESSION *session,
const char *data,
size_t data_len,
const unsigned char *pwd)
{
unsigned char *ntdata;
mbedtls_pk_context pkey;
mbedtls_pk_init(&pkey);
ntdata = LIBSSH2_ALLOC(session, data_len + 1);
if(ntdata == NULL)
goto cleanup;
memcpy(ntdata, data, data_len);
if(_libssh2_mbedtls_parse_eckey(ctx, &pkey, session,
ntdata, data_len + 1, pwd) == 0)
goto cleanup;
_libssh2_mbedtls_parse_openssh_key(ctx, session,
ntdata, data_len + 1, pwd);
cleanup:
mbedtls_pk_free(&pkey);
_libssh2_mbedtls_safe_free(ntdata, data_len);
return (*ctx == NULL) ? -1 : 0;
}
static unsigned char *
_libssh2_mbedtls_mpi_write_binary(unsigned char *buf,
const mbedtls_mpi *mpi,
size_t bytes)
{
unsigned char *p = buf;
if(sizeof(&p) / sizeof(p[0]) < 4) {
goto done;
}
p += 4;
*p = 0;
if(bytes > 0) {
mbedtls_mpi_write_binary(mpi, p + 1, bytes - 1);
}
if(bytes > 0 && !(*(p + 1) & 0x80)) {
memmove(p, p + 1, --bytes);
}
_libssh2_htonu32(p - 4, bytes);
done:
return p + bytes;
}
/* _libssh2_ecdsa_sign
*
* Computes the ECDSA signature of a previously-hashed message
*
*/
int
_libssh2_mbedtls_ecdsa_sign(LIBSSH2_SESSION *session,
libssh2_ecdsa_ctx *ctx,
const unsigned char *hash,
unsigned long hash_len,
unsigned char **sign,
size_t *sign_len)
{
size_t r_len, s_len, tmp_sign_len = 0;
unsigned char *sp, *tmp_sign = NULL;
mbedtls_mpi pr, ps;
mbedtls_mpi_init(&pr);
mbedtls_mpi_init(&ps);
if(mbedtls_ecdsa_sign(&ctx->grp, &pr, &ps, &ctx->d,
hash, hash_len,
mbedtls_ctr_drbg_random,
&_libssh2_mbedtls_ctr_drbg) != 0)
goto cleanup;
r_len = mbedtls_mpi_size(&pr) + 1;
s_len = mbedtls_mpi_size(&ps) + 1;
tmp_sign_len = r_len + s_len + 8;
tmp_sign = LIBSSH2_CALLOC(session, tmp_sign_len);
if(tmp_sign == NULL)
goto cleanup;
sp = tmp_sign;
sp = _libssh2_mbedtls_mpi_write_binary(sp, &pr, r_len);
sp = _libssh2_mbedtls_mpi_write_binary(sp, &ps, s_len);
*sign_len = (size_t)(sp - tmp_sign);
*sign = LIBSSH2_CALLOC(session, *sign_len);
if(*sign == NULL)
goto cleanup;
memcpy(*sign, tmp_sign, *sign_len);
cleanup:
mbedtls_mpi_free(&pr);
mbedtls_mpi_free(&ps);
_libssh2_mbedtls_safe_free(tmp_sign, tmp_sign_len);
return (*sign == NULL) ? -1 : 0;
}
/* _libssh2_ecdsa_get_curve_type
*
* returns key curve type that maps to libssh2_curve_type
*
*/
libssh2_curve_type
_libssh2_mbedtls_ecdsa_get_curve_type(libssh2_ecdsa_ctx *ctx)
{
return (libssh2_curve_type) ctx->grp.id;
}
/* _libssh2_ecdsa_curve_type_from_name
*
* returns 0 for success, key curve type that maps to libssh2_curve_type
*
*/
int
_libssh2_mbedtls_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;
}
void
_libssh2_mbedtls_ecdsa_free(libssh2_ecdsa_ctx *ctx)
{
mbedtls_ecdsa_free(ctx);
mbedtls_free(ctx);
}
#endif /* LIBSSH2_ECDSA */
#endif /* LIBSSH2_MBEDTLS */

View File

@@ -1,3 +1,5 @@
#ifndef __LIBSSH2_MBEDTLS_H
#define __LIBSSH2_MBEDTLS_H
/* Copyright (c) 2016, Art <https://github.com/wildart>
* All rights reserved.
*
@@ -43,6 +45,12 @@
#include <mbedtls/rsa.h>
#include <mbedtls/bignum.h>
#include <mbedtls/cipher.h>
#ifdef MBEDTLS_ECDH_C
# include <mbedtls/ecdh.h>
#endif
#ifdef MBEDTLS_ECDSA_C
# include <mbedtls/ecdsa.h>
#endif
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/pk.h>
@@ -64,7 +72,11 @@
#define LIBSSH2_RSA 1
#define LIBSSH2_DSA 0
#ifdef MBEDTLS_ECDSA_C
# define LIBSSH2_ECDSA 1
#else
# define LIBSSH2_ECDSA 0
#endif
#define LIBSSH2_ED25519 0
#define MD5_DIGEST_LENGTH 16
@@ -75,10 +87,6 @@
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
#if LIBSSH2_ECDSA
#else
#define _libssh2_ec_key void
#endif
/*******************************************************************/
/*
@@ -208,9 +216,10 @@
#define libssh2_md5(data, datalen, hash) \
_libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_MD5, hash)
/*******************************************************************/
/*
* mbedTLS backend: RSA structure
* mbedTLS backend: RSA functions
*/
#define libssh2_rsa_ctx mbedtls_rsa_context
@@ -239,6 +248,82 @@
#define _libssh2_rsa_free(rsactx) \
_libssh2_mbedtls_rsa_free(rsactx)
/*******************************************************************/
/*
* mbedTLS backend: ECDSA structures
*/
#if LIBSSH2_ECDSA
typedef enum {
#ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
LIBSSH2_EC_CURVE_NISTP256 = MBEDTLS_ECP_DP_SECP256R1,
#else
LIBSSH2_EC_CURVE_NISTP256 = MBEDTLS_ECP_DP_NONE,
#endif
#ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
LIBSSH2_EC_CURVE_NISTP384 = MBEDTLS_ECP_DP_SECP384R1,
#else
LIBSSH2_EC_CURVE_NISTP384 = MBEDTLS_ECP_DP_NONE,
#endif
#ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
LIBSSH2_EC_CURVE_NISTP521 = MBEDTLS_ECP_DP_SECP521R1
#else
LIBSSH2_EC_CURVE_NISTP521 = MBEDTLS_ECP_DP_NONE,
#endif
} libssh2_curve_type;
# define _libssh2_ec_key mbedtls_ecp_keypair
#else
# define _libssh2_ec_key void
#endif /* LIBSSH2_ECDSA */
/*******************************************************************/
/*
* mbedTLS backend: ECDSA functions
*/
#if LIBSSH2_ECDSA
#define libssh2_ecdsa_ctx mbedtls_ecdsa_context
#define _libssh2_ecdsa_create_key(session, privkey, pubkey_octal, \
pubkey_octal_len, curve) \
_libssh2_mbedtls_ecdsa_create_key(session, privkey, pubkey_octal, \
pubkey_octal_len, curve)
#define _libssh2_ecdsa_curve_name_with_octal_new(ctx, k, k_len, curve) \
_libssh2_mbedtls_ecdsa_curve_name_with_octal_new(ctx, k, k_len, curve)
#define _libssh2_ecdh_gen_k(k, privkey, server_pubkey, server_pubkey_len) \
_libssh2_mbedtls_ecdh_gen_k(k, privkey, server_pubkey, server_pubkey_len)
#define _libssh2_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len) \
_libssh2_mbedtls_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len)
#define _libssh2_ecdsa_new_private(ctx, session, filename, passphrase) \
_libssh2_mbedtls_ecdsa_new_private(ctx, session, filename, passphrase)
#define _libssh2_ecdsa_new_private_frommemory(ctx, session, filedata, \
filedata_len, passphrase) \
_libssh2_mbedtls_ecdsa_new_private_frommemory(ctx, session, filedata, \
filedata_len, passphrase)
#define _libssh2_ecdsa_sign(session, ctx, hash, hash_len, sign, sign_len) \
_libssh2_mbedtls_ecdsa_sign(session, ctx, hash, hash_len, sign, sign_len)
#define _libssh2_ecdsa_get_curve_type(ctx) \
_libssh2_mbedtls_ecdsa_get_curve_type(ctx)
#define _libssh2_ecdsa_free(ctx) \
_libssh2_mbedtls_ecdsa_free(ctx)
#endif /* LIBSSH2_ECDSA */
/*******************************************************************/
/*
* mbedTLS backend: Key functions
*/
@@ -255,6 +340,7 @@
/*
* mbedTLS backend: Cipher Context structure
*/
#define _libssh2_cipher_ctx mbedtls_cipher_context_t
#define _libssh2_cipher_type(algo) mbedtls_cipher_type_t algo
@@ -270,6 +356,8 @@
#define _libssh2_cipher_cast5 MBEDTLS_CIPHER_NULL
#define _libssh2_cipher_3des MBEDTLS_CIPHER_DES_EDE3_CBC
/*******************************************************************/
/*
* mbedTLS backend: Cipher functions
*/
@@ -329,6 +417,7 @@
/*
* mbedTLS backend: forward declarations
*/
void
_libssh2_mbedtls_init(void);
@@ -434,6 +523,54 @@ _libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
const char *privatekeydata,
size_t privatekeydata_len,
const char *passphrase);
#if LIBSSH2_ECDSA
int
_libssh2_mbedtls_ecdsa_create_key(LIBSSH2_SESSION *session,
_libssh2_ec_key **privkey,
unsigned char **pubkey_octal,
size_t *pubkey_octal_len,
libssh2_curve_type curve);
int
_libssh2_mbedtls_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx **ctx,
const unsigned char *k,
size_t k_len,
libssh2_curve_type curve);
int
_libssh2_mbedtls_ecdh_gen_k(_libssh2_bn **k,
_libssh2_ec_key *privkey,
const unsigned char *server_pubkey,
size_t server_pubkey_len);
int
_libssh2_mbedtls_ecdsa_verify(libssh2_ecdsa_ctx *ctx,
const unsigned char *r, size_t r_len,
const unsigned char *s, size_t s_len,
const unsigned char *m, size_t m_len);
int
_libssh2_mbedtls_ecdsa_new_private(libssh2_ecdsa_ctx **ctx,
LIBSSH2_SESSION *session,
const char *filename,
const unsigned char *passphrase);
int
_libssh2_mbedtls_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx **ctx,
LIBSSH2_SESSION *session,
const char *filedata,
size_t filedata_len,
const unsigned char *passphrase);
int
_libssh2_mbedtls_ecdsa_sign(LIBSSH2_SESSION *session,
libssh2_ecdsa_ctx *ctx,
const unsigned char *hash,
unsigned long hash_len,
unsigned char **signature,
size_t *signature_len);
libssh2_curve_type
_libssh2_mbedtls_ecdsa_key_get_curve_type(libssh2_ecdsa_ctx *ctx);
int
_libssh2_mbedtls_ecdsa_curve_type_from_name(const char *name,
libssh2_curve_type *type);
void
_libssh2_mbedtls_ecdsa_free(libssh2_ecdsa_ctx *ctx);
#endif /* LIBSSH2_ECDSA */
extern void
_libssh2_dh_init(_libssh2_dh_ctx *dhctx);
@@ -445,3 +582,5 @@ _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
_libssh2_bn *f, _libssh2_bn *p);
extern void
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
#endif /* __LIBSSH2_MBEDTLS_H */

View File

@@ -141,19 +141,16 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length,
#ifdef WIN32
if(rc < 0)
return -wsa2errno();
#elif defined(__VMS)
if(rc < 0) {
if(errno == EWOULDBLOCK)
return -EAGAIN;
else
return -errno;
}
#else
if(rc < 0) {
/* Sometimes the first recv() function call sets errno to ENOENT on
Solaris and HP-UX */
if(errno == ENOENT)
return -EAGAIN;
#ifdef EWOULDBLOCK /* For VMS and other special unixes */
else if(errno == EWOULDBLOCK)
return -EAGAIN;
#endif
else
return -errno;
}
@@ -177,16 +174,14 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
#ifdef WIN32
if(rc < 0)
return -wsa2errno();
#elif defined(__VMS)
#else
if(rc < 0) {
#ifdef EWOULDBLOCK /* For VMS and other special unixes */
if(errno == EWOULDBLOCK)
return -EAGAIN;
else
#endif
return -errno;
}
#else
if(rc < 0)
return -errno;
#endif
return rc;
}
@@ -196,7 +191,10 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
unsigned int
_libssh2_ntohu32(const unsigned char *buf)
{
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
return (((unsigned int)buf[0] << 24)
| ((unsigned int)buf[1] << 16)
| ((unsigned int)buf[2] << 8)
| ((unsigned int)buf[3]));
}

View File

@@ -259,16 +259,16 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
#if LIBSSH2_ECDSA
/* _libssh2_ecdsa_key_get_curve_type
/* _libssh2_ecdsa_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)
_libssh2_ecdsa_get_curve_type(libssh2_ecdsa_ctx *ec_ctx)
{
const EC_GROUP *group = EC_KEY_get0_group(key);
const EC_GROUP *group = EC_KEY_get0_group(ec_ctx);
return EC_GROUP_get_curve_name(group);
}
@@ -355,7 +355,7 @@ _libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx,
{
int ret = 0;
EC_KEY *ec_key = (EC_KEY*)ctx;
libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_key);
libssh2_curve_type type = _libssh2_ecdsa_get_curve_type(ec_key);
#ifdef HAVE_OPAQUE_STRUCTS
ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new();
@@ -427,10 +427,19 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
#else
ret = EVP_Cipher(ctx, buf, block, blocksize);
#endif
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
if(ret != -1) {
#else
if(ret == 1) {
#endif
memcpy(block, buf, blocksize);
}
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
return ret != -1 ? 0 : 1;
#else
return ret == 1 ? 0 : 1;
#endif
}
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
@@ -445,6 +454,10 @@ typedef struct
unsigned char ctr[AES_BLOCK_SIZE];
} aes_ctr_ctx;
static EVP_CIPHER * aes_128_ctr_cipher = NULL;
static EVP_CIPHER * aes_192_ctr_cipher = NULL;
static EVP_CIPHER * aes_256_ctr_cipher = NULL;
static int
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) /* init key */
@@ -589,14 +602,16 @@ const EVP_CIPHER *
_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_128_ctr_cipher ?
make_ctr_evp(16, &aes_128_ctr_cipher, NID_aes_128_ctr) :
aes_128_ctr_cipher;
#else
static EVP_CIPHER 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;
if(!aes_128_ctr_cipher) {
aes_128_ctr_cipher = &aes_ctr_cipher;
make_ctr_evp(16, &aes_128_ctr_cipher, 0);
}
return aes_128_ctr_cipher;
#endif
}
@@ -604,14 +619,16 @@ const EVP_CIPHER *
_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_192_ctr_cipher ?
make_ctr_evp(24, &aes_192_ctr_cipher, NID_aes_192_ctr) :
aes_192_ctr_cipher;
#else
static EVP_CIPHER 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;
if(!aes_192_ctr_cipher) {
aes_192_ctr_cipher = &aes_ctr_cipher;
make_ctr_evp(24, &aes_192_ctr_cipher, 0);
}
return aes_192_ctr_cipher;
#endif
}
@@ -619,24 +636,20 @@ const EVP_CIPHER *
_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_256_ctr_cipher ?
make_ctr_evp(32, &aes_256_ctr_cipher, NID_aes_256_ctr) :
aes_256_ctr_cipher;
#else
static EVP_CIPHER 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;
if(!aes_256_ctr_cipher) {
aes_256_ctr_cipher = &aes_ctr_cipher;
make_ctr_evp(32, &aes_256_ctr_cipher, 0);
}
return aes_256_ctr_cipher;
#endif
}
#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
#endif /* LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR) */
void _libssh2_openssl_crypto_init(void)
{
@@ -655,7 +668,7 @@ void _libssh2_openssl_crypto_init(void)
ENGINE_register_all_complete();
#endif
#endif
#ifndef HAVE_EVP_AES_128_CTR
#if LIBSSH2_AES_CTR && !defined(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();
@@ -664,7 +677,7 @@ void _libssh2_openssl_crypto_init(void)
void _libssh2_openssl_crypto_exit(void)
{
#ifndef HAVE_EVP_AES_128_CTR
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
#ifdef HAVE_OPAQUE_STRUCTS
if(aes_128_ctr_cipher) {
EVP_CIPHER_meth_free(aes_128_ctr_cipher);
@@ -762,7 +775,6 @@ _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
pem_read_bio_func read_rsa =
(pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
(void) session;
_libssh2_init_if_needed();
@@ -834,7 +846,7 @@ gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session,
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
"Computing public key from RSA private key envelop");
"Computing public key from RSA private key envelope");
rsa = EVP_PKEY_get1_RSA(pk);
if(rsa == NULL) {
@@ -1113,7 +1125,6 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
pem_read_bio_func read_rsa =
(pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
(void) session;
_libssh2_init_if_needed();
@@ -1139,7 +1150,6 @@ _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
pem_read_bio_func read_dsa =
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
(void) session;
_libssh2_init_if_needed();
@@ -1225,7 +1235,7 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session,
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
"Computing public key from DSA private key envelop");
"Computing public key from DSA private key envelope");
dsa = EVP_PKEY_get1_DSA(pk);
if(dsa == NULL) {
@@ -1415,7 +1425,6 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
pem_read_bio_func read_dsa =
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
(void) session;
_libssh2_init_if_needed();
@@ -1444,7 +1453,6 @@ _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
pem_read_bio_func read_ec =
(pem_read_bio_func) &PEM_read_bio_ECPrivateKey;
(void) session;
_libssh2_init_if_needed();
@@ -1466,89 +1474,53 @@ _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
#if LIBSSH2_ED25519
int
_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_x25519_ctx **out_ctx,
_libssh2_curve25519_new(LIBSSH2_SESSION *session,
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;
unsigned char *priv = NULL, *pub = NULL;
size_t privLen, pubLen;
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) {
if(EVP_PKEY_keygen_init(pctx) != 1 ||
EVP_PKEY_keygen(pctx, &key) != 1) {
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)
privLen = LIBSSH2_ED25519_KEY_LEN;
priv = LIBSSH2_ALLOC(session, privLen);
if(priv == NULL)
goto cleanExit;
memcpy(*out_private_key, priv, LIBSSH2_ED25519_KEY_LEN);
if(EVP_PKEY_get_raw_private_key(key, priv, &privLen) != 1 ||
privLen != LIBSSH2_ED25519_KEY_LEN) {
goto cleanExit;
}
*out_private_key = priv;
priv = NULL;
}
if(out_public_key != NULL) {
*out_public_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN);
if(*out_public_key == NULL)
pubLen = LIBSSH2_ED25519_KEY_LEN;
pub = LIBSSH2_ALLOC(session, pubLen);
if(pub == 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);
if(EVP_PKEY_get_raw_public_key(key, pub, &pubLen) != 1 ||
pubLen != LIBSSH2_ED25519_KEY_LEN) {
goto cleanExit;
}
*out_ctx = ctx;
*out_public_key = pub;
pub = NULL;
}
/* success */
@@ -1556,20 +1528,84 @@ _libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_x25519_ctx **out_ctx,
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);
if(priv)
LIBSSH2_FREE(session, priv);
if(pub)
LIBSSH2_FREE(session, pub);
return rc;
}
static int
gen_publickey_from_ed_evp(LIBSSH2_SESSION *session,
unsigned char **method,
size_t *method_len,
unsigned char **pubkeydata,
size_t *pubkeydata_len,
EVP_PKEY *pk)
{
const char methodName[] = "ssh-ed25519";
unsigned char *methodBuf = NULL;
size_t rawKeyLen = 0;
unsigned char *keyBuf = NULL;
size_t bufLen = 0;
unsigned char *bufPos = NULL;
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Computing public key from ED private key envelope");
methodBuf = LIBSSH2_ALLOC(session, sizeof(methodName) - 1);
if(!methodBuf) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for private key data");
goto fail;
}
memcpy(methodBuf, methodName, sizeof(methodName) - 1);
if(EVP_PKEY_get_raw_public_key(pk, NULL, &rawKeyLen) != 1) {
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
"EVP_PKEY_get_raw_public_key failed");
goto fail;
}
/* Key form is: type_len(4) + type(11) + pub_key_len(4) + pub_key(32). */
bufLen = 4 + sizeof(methodName) - 1 + 4 + rawKeyLen;
bufPos = keyBuf = LIBSSH2_ALLOC(session, bufLen);
if(!keyBuf) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for private key data");
goto fail;
}
_libssh2_store_str(&bufPos, methodName, sizeof(methodName) - 1);
_libssh2_store_u32(&bufPos, rawKeyLen);
if(EVP_PKEY_get_raw_public_key(pk, bufPos, &rawKeyLen) != 1) {
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
"EVP_PKEY_get_raw_public_key failed");
goto fail;
}
*method = methodBuf;
*method_len = sizeof(methodName) - 1;
*pubkeydata = keyBuf;
*pubkeydata_len = bufLen;
return 0;
fail:
if(methodBuf)
LIBSSH2_FREE(session, methodBuf);
if(keyBuf)
LIBSSH2_FREE(session, keyBuf);
return -1;
}
static int
gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session,
struct string_buf *decrypted,
@@ -1606,26 +1642,12 @@ gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session,
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,
ctx = 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,
@@ -1664,10 +1686,12 @@ gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session,
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
"Computing public key from ED25519 "
"private key envelop");
"private key envelope");
method_buf = LIBSSH2_ALLOC(session, 11); /* ssh-ed25519. */
if(method_buf == NULL) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for ED25519 key");
goto clean_exit;
}
@@ -1676,6 +1700,8 @@ gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session,
key_len = LIBSSH2_ED25519_KEY_LEN + 19;
key = LIBSSH2_CALLOC(session, key_len);
if(key == NULL) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for ED25519 key");
goto clean_exit;
}
@@ -1798,6 +1824,24 @@ _libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx ** ed_ctx,
size_t filedata_len,
unsigned const char *passphrase)
{
libssh2_ed25519_ctx *ctx = NULL;
_libssh2_init_if_needed();
if(read_private_key_from_memory((void **)&ctx,
(pem_read_bio_func)
&PEM_read_bio_PrivateKey,
filedata, filedata_len, passphrase) == 0) {
if(EVP_PKEY_id(ctx) != EVP_PKEY_ED25519) {
_libssh2_ed25519_free(ctx);
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Private key is not an ED25519 key");
}
*ed_ctx = ctx;
return 0;
}
return read_openssh_private_key_from_memory((void **)ed_ctx, session,
"ssh-ed25519",
filedata, filedata_len,
@@ -1811,38 +1855,26 @@ _libssh2_ed25519_new_public(libssh2_ed25519_ctx ** ed_ctx,
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) {
ctx = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
raw_pub_key, key_len);
if(!ctx)
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)
else if(ctx)
_libssh2_ed25519_free(ctx);
return 0;
}
#endif /* LIBSSH2_ED25519 */
int
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx,
@@ -2193,6 +2225,19 @@ _libssh2_sha512(const unsigned char *message, unsigned long len,
int
_libssh2_md5_init(libssh2_md5_ctx *ctx)
{
/* MD5 digest is not supported in OpenSSL FIPS mode
* Trying to init it will result in a latent OpenSSL error:
* "digital envelope routines:FIPS_DIGESTINIT:disabled for fips"
* So, just return 0 in FIPS mode
*/
#if OPENSSL_VERSION_NUMBER >= 0x000907000L && \
defined(OPENSSL_VERSION_MAJOR) && \
OPENSSL_VERSION_MAJOR < 3 && \
!defined(LIBRESSL_VERSION_NUMBER)
if(FIPS_mode() != 0)
return 0;
#endif
#ifdef HAVE_OPAQUE_STRUCTS
*ctx = EVP_MD_CTX_new();
@@ -2237,7 +2282,7 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session,
_libssh2_debug(session,
LIBSSH2_TRACE_AUTH,
"Computing public key from EC private key envelop");
"Computing public key from EC private key envelope");
bn_ctx = BN_CTX_new();
if(bn_ctx == NULL)
@@ -2251,7 +2296,7 @@ gen_publickey_from_ec_evp(LIBSSH2_SESSION *session,
public_key = EC_KEY_get0_public_key(ec);
group = EC_KEY_get0_group(ec);
type = _libssh2_ecdsa_key_get_curve_type(ec);
type = _libssh2_ecdsa_get_curve_type(ec);
method_buf = LIBSSH2_ALLOC(session, 19);
if(method_buf == NULL) {
@@ -2383,6 +2428,7 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session,
if((rc = _libssh2_ecdsa_curve_name_with_octal_new(&ec_key, point_buf,
pointlen, curve_type)) != 0) {
rc = -1;
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
"ECDSA could not create key");
goto fail;
@@ -2391,6 +2437,8 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session,
bn_exponent = BN_new();
if(bn_exponent == NULL) {
rc = -1;
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for private key data");
goto fail;
}
@@ -2417,15 +2465,10 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session,
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");
return rc;
}
static int
@@ -2495,7 +2538,6 @@ _libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx,
int rc;
pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey;
(void) session;
_libssh2_init_if_needed();
@@ -2668,7 +2710,7 @@ _libssh2_ed25519_sign(libssh2_ed25519_ctx *ctx, LIBSSH2_SESSION *session,
unsigned char *sig = NULL;
if(md_ctx != NULL) {
if(EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, ctx->private_key) != 1)
if(EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, ctx) != 1)
goto clean_exit;
if(EVP_DigestSign(md_ctx, NULL, &sig_len, message, message_len) != 1)
goto clean_exit;
@@ -2785,7 +2827,7 @@ _libssh2_ed25519_verify(libssh2_ed25519_ctx *ctx, const uint8_t *s,
if(NULL == md_ctx)
return -1;
ret = EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, ctx->public_key);
ret = EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, ctx);
if(ret != 1)
goto clean_exit;
@@ -2962,6 +3004,12 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
#endif
switch(pktype) {
#if LIBSSH2_ED25519
case EVP_PKEY_ED25519 :
st = gen_publickey_from_ed_evp(
session, method, method_len, pubkeydata, pubkeydata_len, pk);
break;
#endif /* LIBSSH2_ED25519 */
case EVP_PKEY_RSA :
st = gen_publickey_from_rsa_evp(
session, method, method_len, pubkeydata, pubkeydata_len, pk);
@@ -3013,17 +3061,13 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session,
if(key_ctx != NULL)
*key_ctx = NULL;
if(session == NULL) {
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
if(session == NULL)
return _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,
if(key_type != NULL && (strlen(key_type) > 11 || strlen(key_type) < 7))
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"type is invalid");
return -1;
}
_libssh2_init_if_needed();
@@ -3031,20 +3075,18 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session,
privatekeydata,
privatekeydata_len, &decrypted);
if(rc) {
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(rc != 0 || buf == NULL)
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Public key type in decrypted "
"key data not found");
rc = -1;
rc = LIBSSH2_ERROR_FILE;
#if LIBSSH2_ED25519
if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
@@ -3098,6 +3140,11 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session,
}
#endif
if(rc == LIBSSH2_ERROR_FILE)
rc = _libssh2_error(session, LIBSSH2_ERROR_FILE,
"Unable to extract public key from private key file: "
"invalid/unrecognized private key file format");
if(decrypted)
_libssh2_string_buf_free(session, decrypted);
@@ -3137,10 +3184,10 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
"Computing public key from private key.");
bp = BIO_new_mem_buf((char *)privatekeydata, privatekeydata_len);
if(!bp) {
return -1;
}
if(!bp)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory when"
"computing public key");
BIO_reset(bp);
pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase);
BIO_free(bp);
@@ -3155,15 +3202,8 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
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");
}
if(st != 0)
return st;
return 0;
}
@@ -3174,6 +3214,12 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
#endif
switch(pktype) {
#if LIBSSH2_ED25519
case EVP_PKEY_ED25519 :
st = gen_publickey_from_ed_evp(
session, method, method_len, pubkeydata, pubkeydata_len, pk);
break;
#endif /* LIBSSH2_ED25519 */
case EVP_PKEY_RSA :
st = gen_publickey_from_rsa_evp(session, method, method_len,
pubkeydata, pubkeydata_len, pk);

View File

@@ -1,3 +1,5 @@
#ifndef __LIBSSH2_OPENSSL_H
#define __LIBSSH2_OPENSSL_H
/* Copyright (C) 2009, 2010 Simon Josefsson
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
*
@@ -135,7 +137,7 @@
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
#define _libssh2_random(buf, len) RAND_bytes ((buf), (len))
#define _libssh2_random(buf, len) (RAND_bytes((buf), (len)) == 1 ? 0 : -1)
#define libssh2_prepare_iovec(vec, len) /* Empty. */
@@ -306,7 +308,7 @@ extern void _libssh2_openssl_crypto_exit(void);
#define _libssh2_dsa_free(dsactx) DSA_free(dsactx)
#ifdef LIBSSH2_ECDSA
#if LIBSSH2_ECDSA
#define libssh2_ecdsa_ctx EC_KEY
#define _libssh2_ecdsa_free(ecdsactx) EC_KEY_free(ecdsactx)
#define _libssh2_ec_key EC_KEY
@@ -321,27 +323,10 @@ libssh2_curve_type;
#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)
#if LIBSSH2_ED25519
#define libssh2_ed25519_ctx EVP_PKEY
#define _libssh2_ed25519_free(ctx) EVP_PKEY_free(ctx)
#endif /* ED25519 */
#define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void)
@@ -407,3 +392,5 @@ 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);
#endif /* __LIBSSH2_OPENSSL_H */

View File

@@ -85,30 +85,53 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
int rc;
(void) datalen;
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;
unsigned long offset = (sizeof("forwarded-tcpip") - 1) + 5;
size_t temp_len = 0;
struct string_buf buf;
buf.data = data;
buf.dataptr = buf.data;
buf.len = datalen;
listen_state->initial_window_size = _libssh2_ntohu32(s);
s += 4;
listen_state->packet_size = _libssh2_ntohu32(s);
s += 4;
if(datalen < offset) {
return _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
"Unexpected packet size");
}
listen_state->host_len = _libssh2_ntohu32(s);
s += 4;
listen_state->host = s;
s += listen_state->host_len;
listen_state->port = _libssh2_ntohu32(s);
s += 4;
buf.dataptr += offset;
listen_state->shost_len = _libssh2_ntohu32(s);
s += 4;
listen_state->shost = s;
s += listen_state->shost_len;
listen_state->sport = _libssh2_ntohu32(s);
if(_libssh2_get_u32(&buf, &(listen_state->sender_channel))) {
return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short extracting channel");
}
if(_libssh2_get_u32(&buf, &(listen_state->initial_window_size))) {
return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short extracting window size");
}
if(_libssh2_get_u32(&buf, &(listen_state->packet_size))) {
return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short extracting packet");
}
if(_libssh2_get_string(&buf, &(listen_state->host), &temp_len)) {
return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short extracting host");
}
listen_state->host_len = (uint32_t)temp_len;
if(_libssh2_get_u32(&buf, &(listen_state->port))) {
return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short extracting port");
}
if(_libssh2_get_string(&buf, &(listen_state->shost), &temp_len)) {
return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short extracting shost");
}
listen_state->shost_len = (uint32_t)temp_len;
if(_libssh2_get_u32(&buf, &(listen_state->sport))) {
return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"Data too short extracting sport");
}
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"Remote received connection from %s:%ld to %s:%ld",
@@ -272,21 +295,56 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
LIBSSH2_CHANNEL *channel = x11open_state->channel;
int rc;
(void) datalen;
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;
x11open_state->initial_window_size = _libssh2_ntohu32(s);
s += 4;
x11open_state->packet_size = _libssh2_ntohu32(s);
s += 4;
x11open_state->shost_len = _libssh2_ntohu32(s);
s += 4;
x11open_state->shost = s;
s += x11open_state->shost_len;
x11open_state->sport = _libssh2_ntohu32(s);
unsigned long offset = (sizeof("x11") - 1) + 5;
size_t temp_len = 0;
struct string_buf buf;
buf.data = data;
buf.dataptr = buf.data;
buf.len = datalen;
if(datalen < offset) {
_libssh2_error(session, LIBSSH2_ERROR_INVAL,
"unexpected data length");
failure_code = SSH_OPEN_CONNECT_FAILED;
goto x11_exit;
}
buf.dataptr += offset;
if(_libssh2_get_u32(&buf, &(x11open_state->sender_channel))) {
_libssh2_error(session, LIBSSH2_ERROR_INVAL,
"unexpected sender channel size");
failure_code = SSH_OPEN_CONNECT_FAILED;
goto x11_exit;
}
if(_libssh2_get_u32(&buf, &(x11open_state->initial_window_size))) {
_libssh2_error(session, LIBSSH2_ERROR_INVAL,
"unexpected window size");
failure_code = SSH_OPEN_CONNECT_FAILED;
goto x11_exit;
}
if(_libssh2_get_u32(&buf, &(x11open_state->packet_size))) {
_libssh2_error(session, LIBSSH2_ERROR_INVAL,
"unexpected window size");
failure_code = SSH_OPEN_CONNECT_FAILED;
goto x11_exit;
}
if(_libssh2_get_string(&buf, &(x11open_state->shost), &temp_len)) {
_libssh2_error(session, LIBSSH2_ERROR_INVAL,
"unexpected host size");
failure_code = SSH_OPEN_CONNECT_FAILED;
goto x11_exit;
}
x11open_state->shost_len = (uint32_t)temp_len;
if(_libssh2_get_u32(&buf, &(x11open_state->sport))) {
_libssh2_error(session, LIBSSH2_ERROR_INVAL,
"unexpected port size");
failure_code = SSH_OPEN_CONNECT_FAILED;
goto x11_exit;
}
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
"X11 Connection Received from %s:%ld on channel %lu",
@@ -419,8 +477,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
size_t datalen, int macstate)
{
int rc = 0;
char *message = NULL;
char *language = NULL;
unsigned char *message = NULL;
unsigned char *language = NULL;
size_t message_len = 0;
size_t language_len = 0;
LIBSSH2_CHANNEL *channelp = NULL;
@@ -472,33 +530,23 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
case SSH_MSG_DISCONNECT:
if(datalen >= 5) {
size_t reason = _libssh2_ntohu32(data + 1);
uint32_t reason = 0;
struct string_buf buf;
buf.data = (unsigned char *)data;
buf.dataptr = buf.data;
buf.len = datalen;
buf.dataptr++; /* advance past type */
if(datalen >= 9) {
message_len = _libssh2_ntohu32(data + 5);
_libssh2_get_u32(&buf, &reason);
_libssh2_get_string(&buf, &message, &message_len);
_libssh2_get_string(&buf, &language, &language_len);
if(message_len < datalen-13) {
/* 9 = packet_type(1) + reason(4) + message_len(4) */
message = (char *) data + 9;
language_len =
_libssh2_ntohu32(data + 9 + message_len);
language = (char *) data + 9 + message_len + 4;
if(language_len > (datalen-13-message_len)) {
/* bad input, clear info */
language = message = NULL;
language_len = message_len = 0;
}
}
else
/* bad size, clear it */
message_len = 0;
}
if(session->ssh_msg_disconnect) {
LIBSSH2_DISCONNECT(session, reason, message,
message_len, language, language_len);
LIBSSH2_DISCONNECT(session, reason, (const char *)message,
message_len, (const char *)language,
language_len);
}
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"Disconnect(%d): %s(%s)", reason,
message, language);
@@ -539,24 +587,24 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
int always_display = data[1];
if(datalen >= 6) {
message_len = _libssh2_ntohu32(data + 2);
struct string_buf buf;
buf.data = (unsigned char *)data;
buf.dataptr = buf.data;
buf.len = datalen;
buf.dataptr += 2; /* advance past type & always display */
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);
if(language_len <= (datalen - 10 - message_len))
language = (char *) data + 10 + message_len;
}
_libssh2_get_string(&buf, &message, &message_len);
_libssh2_get_string(&buf, &language, &language_len);
}
if(session->ssh_msg_debug) {
LIBSSH2_DEBUG(session, always_display, message,
message_len, language, language_len);
LIBSSH2_DEBUG(session, always_display,
(const char *)message,
message_len, (const char *)language,
language_len);
}
}
/*
* _libssh2_debug will actually truncate this for us so
* that it's not an inordinate about of data
@@ -579,7 +627,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
uint32_t len = 0;
unsigned char want_reply = 0;
len = _libssh2_ntohu32(data + 1);
if(datalen >= (6 + len)) {
if((len <= (UINT_MAX - 6)) && (datalen >= (6 + len))) {
want_reply = data[5 + len];
_libssh2_debug(session,
LIBSSH2_TRACE_CONN,
@@ -1275,9 +1323,11 @@ _libssh2_packet_requirev(LIBSSH2_SESSION *session,
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,
int ret = _libssh2_packet_askv(session, packet_types, data,
data_len, match_ofs, match_buf,
match_len);
state->start = 0;
return ret;
}
}

View File

@@ -1,5 +1,5 @@
#ifndef LIBSSH2_PACKET_H
#define LIBSSH2_PACKET_H
#ifndef __LIBSSH2_PACKET_H
#define __LIBSSH2_PACKET_H
/*
* Copyright (C) 2010 by Daniel Stenberg
* Author: Daniel Stenberg <daniel@haxx.se>
@@ -73,4 +73,4 @@ int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
size_t datalen, int macstate);
#endif /* LIBSSH2_PACKET_H */
#endif /* __LIBSSH2_PACKET_H */

View File

@@ -176,6 +176,8 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session,
linelen = strlen(line);
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
if(!tmp) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for PEM parsing");
ret = -1;
goto out;
}
@@ -319,6 +321,8 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
linelen = strlen(line);
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
if(!tmp) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for PEM parsing");
ret = -1;
goto out;
}
@@ -690,6 +694,8 @@ _libssh2_openssh_pem_parse(LIBSSH2_SESSION * session,
linelen = strlen(line);
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
if(!tmp) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for PEM parsing");
ret = -1;
goto out;
}
@@ -738,17 +744,17 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
size_t off = 0;
int ret;
if(filedata == NULL || filedata_len <= 0) {
return -1;
}
if(filedata == NULL || filedata_len <= 0)
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Error parsing PEM: filedata missing");
do {
*line = '\0';
if(off >= filedata_len) {
return -1;
}
if(off >= filedata_len)
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Error parsing PEM: offset out of bounds");
if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
return -1;
@@ -766,7 +772,9 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
linelen = strlen(line);
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
if(!tmp) {
ret = -1;
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"PEM parsing");
goto out;
}
memcpy(tmp + b64datalen, line, linelen);
@@ -777,7 +785,8 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
*line = '\0';
if(off >= filedata_len) {
ret = -1;
ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Error parsing PEM: offset out of bounds");
goto out;
}
@@ -787,9 +796,9 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
}
} while(strcmp(line, OPENSSH_HEADER_END) != 0);
if(!b64data) {
return -1;
}
if(!b64data)
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Error parsing PEM: base 64 data missing");
ret = _libssh2_openssh_pem_parse_data(session, passphrase, b64data,
b64datalen, decrypted_buf);

View File

@@ -219,7 +219,7 @@ banner_send(LIBSSH2_SESSION * session)
}
else {
memcpy(banner_dup, banner, 255);
banner[255] = '\0';
banner_dup[255] = '\0';
}
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s",
@@ -589,7 +589,7 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
session->err_code = LIBSSH2_ERROR_NONE;
rc = libssh2_keepalive_send(session, &seconds_to_next);
if(rc < 0)
if(rc)
return rc;
ms_to_next = seconds_to_next * 1000;

View File

@@ -1,5 +1,5 @@
#ifndef LIBSSH2_SESSION_H
#define LIBSSH2_SESSION_H
#ifndef __LIBSSH2_SESSION_H
#define __LIBSSH2_SESSION_H
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009-2010 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
@@ -90,4 +90,4 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t entry_time);
/* this is the lib-internal set blocking function */
int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking);
#endif /* LIBSSH2_SESSION_H */
#endif /* __LIBSSH2_SESSION_H */

View File

@@ -1428,7 +1428,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
/* 'count' is how much more data to ask for, and 'already' is how
much data that already has been asked for but not yet returned.
Specificly, 'count' means how much data that have or will be
Specifically, 'count' means how much data that have or will be
asked for by the nodes that are already added to the linked
list. Some of those read requests may not actually have been
sent off successfully yet.

View File

@@ -1,5 +1,5 @@
#ifndef _LIBSSH2_SFTP_H
#define _LIBSSH2_SFTP_H
#ifndef __LIBSSH2_SFTP_H
#define __LIBSSH2_SFTP_H
/*
* Copyright (C) 2010 - 2012 by Daniel Stenberg
* Author: Daniel Stenberg <daniel@haxx.se>
@@ -235,4 +235,4 @@ struct _LIBSSH2_SFTP
uint32_t symlink_request_id;
};
#endif
#endif /* __LIBSSH2_SFTP_H */

View File

@@ -323,7 +323,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
do {
if(session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
return LIBSSH2_ERROR_NONE;
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
if(session->state & LIBSSH2_STATE_NEWKEYS) {
@@ -465,7 +465,7 @@ 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 || total_num == 0) {
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
@@ -488,6 +488,8 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
p->wptr += blocksize - 5; /* advance write pointer */
}
else {
if(p->payload)
LIBSSH2_FREE(session, p->payload);
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
}
@@ -570,6 +572,8 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
memcpy(p->wptr, &p->buf[p->readidx], numbytes);
}
else {
if(p->payload)
LIBSSH2_FREE(session, p->payload);
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
}
@@ -765,7 +769,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 && session->local.comp_abstract) {
/* 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 */
@@ -858,7 +862,10 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
p->outbuf[4] = (unsigned char)padding_length;
/* fill the padding area with random junk */
_libssh2_random(p->outbuf + 5 + data_len, padding_length);
if(_libssh2_random(p->outbuf + 5 + data_len, padding_length)) {
return _libssh2_error(session, LIBSSH2_ERROR_RANDGEN,
"Unable to get random bytes for packet padding");
}
if(encrypted) {
size_t i;

View File

@@ -1,6 +1,5 @@
#ifndef __LIBSSH2_TRANSPORT_H
#define __LIBSSH2_TRANSPORT_H
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
* Copyright (C) 2009-2010 by Daniel Stenberg
* Author: Daniel Stenberg <daniel@haxx.se>

View File

@@ -629,7 +629,7 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
sp1++;
sp_len = sp1 > pubkey ? (sp1 - pubkey) - 1 : 0;
sp_len = sp1 > pubkey ? (sp1 - pubkey) : 0;
sp2 = memchr(sp1, ' ', pubkey_len - sp_len);
if(sp2 == NULL) {
/* Assume that the id string is missing, but that it's okay */
@@ -828,11 +828,6 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
{
int rc;
#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 = NULL;
@@ -1075,7 +1070,21 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
return rc;
}
static int plain_method_len(const char *method, size_t method_len)
{
if(!strncmp("ecdsa-sha2-nistp256-cert-v01@openssh.com",
method,
method_len) ||
!strncmp("ecdsa-sha2-nistp384-cert-v01@openssh.com",
method,
method_len) ||
!strncmp("ecdsa-sha2-nistp521-cert-v01@openssh.com",
method,
method_len)) {
return 19;
}
return method_len;
}
int
_libssh2_userauth_publickey(LIBSSH2_SESSION *session,
@@ -1340,6 +1349,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
s = session->userauth_pblc_packet + session->userauth_pblc_packet_len;
session->userauth_pblc_b = NULL;
session->userauth_pblc_method_len =
plain_method_len((const char *)session->userauth_pblc_method,
session->userauth_pblc_method_len);
_libssh2_store_u32(&s,
4 + session->userauth_pblc_method_len + 4 +
sig_len);
@@ -1438,11 +1451,6 @@ 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;
@@ -1457,15 +1465,14 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session,
}
else if(privatekeydata_len && privatekeydata) {
/* Compute public key from private key. */
if(_libssh2_pub_priv_keyfilememory(session,
rc = _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.");
passphrase);
if(rc)
return rc;
}
else {
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
@@ -1500,11 +1507,6 @@ 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;

View File

@@ -1,5 +1,5 @@
#ifndef LIBSSH2_USERAUTH_H
#define LIBSSH2_USERAUTH_H
#ifndef __LIBSSH2_USERAUTH_H
#define __LIBSSH2_USERAUTH_H
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009-2010 by Daniel Stenberg
* All rights reserved.
@@ -48,4 +48,4 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
((*sign_callback)),
void *abstract);
#endif /* LIBSSH2_USERAUTH_H */
#endif /* __LIBSSH2_USERAUTH_H */

541
libssh2/src/wincng.c Executable file → Normal file
View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2015 Marc Hoersken <info@marc-hoersken.de>
* Copyright (C) 2013-2020 Marc Hoersken <info@marc-hoersken.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -58,6 +58,7 @@
#include <windows.h>
#include <bcrypt.h>
#include <ntstatus.h>
#include <math.h>
#include "misc.h"
@@ -98,6 +99,10 @@
#define BCRYPT_SHA256_ALGORITHM L"SHA256"
#endif
#ifndef BCRYPT_SHA384_ALGORITHM
#define BCRYPT_SHA384_ALGORITHM L"SHA384"
#endif
#ifndef BCRYPT_SHA512_ALGORITHM
#define BCRYPT_SHA512_ALGORITHM L"SHA512"
#endif
@@ -122,6 +127,15 @@
#define BCRYPT_3DES_ALGORITHM L"3DES"
#endif
#ifndef BCRYPT_DH_ALGORITHM
#define BCRYPT_DH_ALGORITHM L"DH"
#endif
/* BCRYPT_KDF_RAW_SECRET is available from Windows 8.1 and onwards */
#ifndef BCRYPT_KDF_RAW_SECRET
#define BCRYPT_KDF_RAW_SECRET L"TRUNCATE"
#endif
#ifndef BCRYPT_ALG_HANDLE_HMAC_FLAG
#define BCRYPT_ALG_HANDLE_HMAC_FLAG 0x00000008
#endif
@@ -208,40 +222,88 @@
* Windows CNG backend: Generic functions
*/
struct _libssh2_wincng_ctx _libssh2_wincng;
void
_libssh2_wincng_init(void)
{
int ret;
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRNG,
memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng));
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRNG,
BCRYPT_RNG_ALGORITHM, NULL, 0);
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgRNG = NULL;
}
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashMD5,
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashMD5,
BCRYPT_MD5_ALGORITHM, NULL, 0);
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA1,
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHashMD5 = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA1,
BCRYPT_SHA1_ALGORITHM, NULL, 0);
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA256,
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHashSHA1 = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA256,
BCRYPT_SHA256_ALGORITHM, NULL, 0);
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA512,
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHashSHA256 = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA384,
BCRYPT_SHA384_ALGORITHM, NULL, 0);
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHashSHA384 = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA512,
BCRYPT_SHA512_ALGORITHM, NULL, 0);
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHashSHA512 = NULL;
}
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacMD5,
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacMD5,
BCRYPT_MD5_ALGORITHM, NULL,
BCRYPT_ALG_HANDLE_HMAC_FLAG);
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA1,
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHmacMD5 = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA1,
BCRYPT_SHA1_ALGORITHM, NULL,
BCRYPT_ALG_HANDLE_HMAC_FLAG);
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA256,
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHmacSHA1 = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA256,
BCRYPT_SHA256_ALGORITHM, NULL,
BCRYPT_ALG_HANDLE_HMAC_FLAG);
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA512,
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHmacSHA256 = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA384,
BCRYPT_SHA384_ALGORITHM, NULL,
BCRYPT_ALG_HANDLE_HMAC_FLAG);
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHmacSHA384 = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA512,
BCRYPT_SHA512_ALGORITHM, NULL,
BCRYPT_ALG_HANDLE_HMAC_FLAG);
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgHmacSHA512 = NULL;
}
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRSA,
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRSA,
BCRYPT_RSA_ALGORITHM, NULL, 0);
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgDSA,
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgRSA = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgDSA,
BCRYPT_DSA_ALGORITHM, NULL, 0);
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgDSA = NULL;
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_CBC,
BCRYPT_AES_ALGORITHM, NULL, 0);
@@ -251,7 +313,10 @@ _libssh2_wincng_init(void)
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
if(!BCRYPT_SUCCESS(ret)) {
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
ret = BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
if(BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgAES_CBC = NULL;
}
}
}
@@ -263,7 +328,10 @@ _libssh2_wincng_init(void)
(PBYTE)BCRYPT_CHAIN_MODE_ECB,
sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
if(!BCRYPT_SUCCESS(ret)) {
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_ECB, 0);
ret = BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_ECB, 0);
if(BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgAES_ECB = NULL;
}
}
}
@@ -275,7 +343,10 @@ _libssh2_wincng_init(void)
(PBYTE)BCRYPT_CHAIN_MODE_NA,
sizeof(BCRYPT_CHAIN_MODE_NA), 0);
if(!BCRYPT_SUCCESS(ret)) {
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
ret = BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
if(BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgRC4_NA = NULL;
}
}
}
@@ -287,29 +358,58 @@ _libssh2_wincng_init(void)
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
if(!BCRYPT_SUCCESS(ret)) {
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC,
ret = BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC,
0);
if(BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlg3DES_CBC = NULL;
}
}
}
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgDH,
BCRYPT_DH_ALGORITHM, NULL, 0);
if(!BCRYPT_SUCCESS(ret)) {
_libssh2_wincng.hAlgDH = NULL;
}
}
void
_libssh2_wincng_free(void)
{
if(_libssh2_wincng.hAlgRNG)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRNG, 0);
if(_libssh2_wincng.hAlgHashMD5)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashMD5, 0);
if(_libssh2_wincng.hAlgHashSHA1)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA1, 0);
if(_libssh2_wincng.hAlgHashSHA256)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA256, 0);
if(_libssh2_wincng.hAlgHashSHA384)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA384, 0);
if(_libssh2_wincng.hAlgHashSHA512)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA512, 0);
if(_libssh2_wincng.hAlgHmacMD5)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacMD5, 0);
if(_libssh2_wincng.hAlgHmacSHA1)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA1, 0);
if(_libssh2_wincng.hAlgHmacSHA256)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA256, 0);
if(_libssh2_wincng.hAlgHmacSHA384)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA384, 0);
if(_libssh2_wincng.hAlgHmacSHA512)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA512, 0);
if(_libssh2_wincng.hAlgRSA)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRSA, 0);
if(_libssh2_wincng.hAlgDSA)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgDSA, 0);
if(_libssh2_wincng.hAlgAES_CBC)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
if(_libssh2_wincng.hAlgRC4_NA)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
if(_libssh2_wincng.hAlg3DES_CBC)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC, 0);
if(_libssh2_wincng.hAlgDH)
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgDH, 0);
memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng));
}
@@ -342,6 +442,24 @@ _libssh2_wincng_safe_free(void *buf, int len)
free(buf);
}
/* Copy a big endian set of bits from src to dest.
* if the size of src is smaller than dest then pad the "left" (MSB)
* end with zeroes and copy the bits into the "right" (LSB) end. */
static void
memcpy_with_be_padding(unsigned char *dest, unsigned long dest_len,
unsigned char *src, unsigned long src_len)
{
if(dest_len > src_len) {
memset(dest, 0, dest_len - src_len);
}
memcpy((dest + dest_len) - src_len, src, src_len);
}
static int
round_down(int number, int multiple)
{
return (number / multiple) * multiple;
}
/*******************************************************************/
/*
@@ -1914,7 +2032,8 @@ _libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom)
if(!rnd)
return -1;
length = (unsigned long)(ceil((float)bits / 8) * sizeof(unsigned char));
length = (unsigned long) (ceil(((double)bits) / 8.0) *
sizeof(unsigned char));
if(_libssh2_wincng_bignum_resize(rnd, length))
return -1;
@@ -1925,15 +2044,17 @@ _libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom)
/* calculate significant bits in most significant byte */
bits %= 8;
if(bits == 0)
bits = 8;
/* fill most significant byte with zero padding */
bignum[0] &= (1 << (8 - bits)) - 1;
bignum[0] &= ((1 << bits) - 1);
/* set some special last bits in most significant byte */
/* set most significant bits in most significant byte */
if(top == 0)
bignum[0] |= (1 << (7 - bits));
bignum[0] |= (1 << (bits - 1));
else if(top == 1)
bignum[0] |= (3 << (6 - bits));
bignum[0] |= (3 << (bits - 2));
/* make odd by setting first bit in least significant byte */
if(bottom)
@@ -1978,11 +2099,10 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
offset += p->length;
memcpy(key + offset, m->bignum, m->length);
offset = 0;
ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen,
BCRYPT_NO_KEY_VALIDATION);
BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen, 0);
if(BCRYPT_SUCCESS(ret)) {
ret = BCryptEncrypt(hKey, a->bignum, a->length, NULL, NULL, 0,
NULL, 0, &length, BCRYPT_PAD_NONE);
@@ -1991,9 +2111,8 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
length = max(a->length, length);
bignum = malloc(length);
if(bignum) {
offset = length - a->length;
memset(bignum, 0, offset);
memcpy(bignum + offset, a->bignum, a->length);
memcpy_with_be_padding(bignum, length,
a->bignum, a->length);
ret = BCryptEncrypt(hKey, bignum, length, NULL, NULL, 0,
r->bignum, r->length, &offset,
@@ -2032,8 +2151,9 @@ _libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word)
number = word;
while(number >>= 1)
bits++;
bits++;
length = (unsigned long) (ceil(((double)(bits + 1)) / 8.0) *
length = (unsigned long) (ceil(((double)bits) / 8.0) *
sizeof(unsigned char));
if(_libssh2_wincng_bignum_resize(bn, length))
return -1;
@@ -2050,21 +2170,18 @@ _libssh2_wincng_bignum_bits(const _libssh2_bn *bn)
unsigned char number;
unsigned long offset, length, bits;
if(!bn)
if(!bn || !bn->bignum || !bn->length)
return 0;
length = bn->length - 1;
offset = 0;
while(!(*(bn->bignum + offset)) && (offset < length))
length = bn->length - 1;
while(!bn->bignum[offset] && offset < length)
offset++;
bits = (length - offset) * 8;
number = bn->bignum[offset];
while(number >>= 1)
bits++;
bits++;
return bits;
@@ -2127,6 +2244,7 @@ _libssh2_wincng_bignum_free(_libssh2_bn *bn)
}
/*******************************************************************/
/*
* Windows CNG backend: Diffie-Hellman support.
*/
@@ -2134,35 +2252,342 @@ _libssh2_wincng_bignum_free(_libssh2_bn *bn)
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;
/* Random from client */
dhctx->bn = NULL;
dhctx->dh_handle = NULL;
dhctx->dh_params = NULL;
}
void
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
{
_libssh2_wincng_bignum_free(*dhctx);
*dhctx = NULL;
if(dhctx->dh_handle) {
BCryptDestroyKey(dhctx->dh_handle);
dhctx->dh_handle = NULL;
}
if(dhctx->dh_params) {
/* Since public dh_params are shared in clear text,
* we don't need to securely zero them out here */
free(dhctx->dh_params);
dhctx->dh_params = NULL;
}
if(dhctx->bn) {
_libssh2_wincng_bignum_free(dhctx->bn);
dhctx->bn = NULL;
}
}
/* Generates a Diffie-Hellman key pair using base `g', prime `p' and the given
* `group_order'. Can use the given big number context `bnctx' if needed. The
* private key is stored as opaque in the Diffie-Hellman context `*dhctx' and
* the public key is returned in `public'. 0 is returned upon success, else
* -1. */
int
_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
_libssh2_bn *g, _libssh2_bn *p, int group_order)
{
const int hasAlgDHwithKDF = _libssh2_wincng.hasAlgDHwithKDF;
while(_libssh2_wincng.hAlgDH && hasAlgDHwithKDF != -1) {
BCRYPT_DH_PARAMETER_HEADER *dh_params = NULL;
unsigned long dh_params_len;
unsigned char *blob = NULL;
int status;
/* Note that the DH provider requires that keys be multiples of 64 bits
* in length. At the time of writing a practical observed group_order
* value is 257, so we need to round down to 8 bytes of length (64/8)
* in order for kex to succeed */
DWORD key_length_bytes = max(round_down(group_order, 8),
max(g->length, p->length));
BCRYPT_DH_KEY_BLOB *dh_key_blob;
LPCWSTR key_type;
/* Prepare a key pair; pass the in the bit length of the key,
* but the key is not ready for consumption until it is finalized. */
status = BCryptGenerateKeyPair(_libssh2_wincng.hAlgDH,
&dhctx->dh_handle,
key_length_bytes * 8, 0);
if(!BCRYPT_SUCCESS(status)) {
return -1;
}
dh_params_len = sizeof(*dh_params) + 2 * key_length_bytes;
blob = malloc(dh_params_len);
if(!blob) {
return -1;
}
/* Populate DH parameters blob; after the header follows the `p`
* value and the `g` value. */
dh_params = (BCRYPT_DH_PARAMETER_HEADER*)blob;
dh_params->cbLength = dh_params_len;
dh_params->dwMagic = BCRYPT_DH_PARAMETERS_MAGIC;
dh_params->cbKeyLength = key_length_bytes;
memcpy_with_be_padding(blob + sizeof(*dh_params), key_length_bytes,
p->bignum, p->length);
memcpy_with_be_padding(blob + sizeof(*dh_params) + key_length_bytes,
key_length_bytes, g->bignum, g->length);
status = BCryptSetProperty(dhctx->dh_handle, BCRYPT_DH_PARAMETERS,
blob, dh_params_len, 0);
if(hasAlgDHwithKDF == -1) {
/* We know that the raw KDF is not supported, so discard this. */
free(blob);
}
else {
/* Pass ownership to dhctx; these parameters will be freed when
* the context is destroyed. We need to keep the parameters more
* easily available so that we have access to the `g` value when
* _libssh2_dh_secret is called later. */
dhctx->dh_params = dh_params;
}
dh_params = NULL;
blob = NULL;
if(!BCRYPT_SUCCESS(status)) {
return -1;
}
status = BCryptFinalizeKeyPair(dhctx->dh_handle, 0);
if(!BCRYPT_SUCCESS(status)) {
return -1;
}
key_length_bytes = 0;
if(hasAlgDHwithKDF == 1) {
/* Now we need to extract the public portion of the key so that we
* set it in the `public` bignum to satisfy our caller.
* First measure up the size of the required buffer. */
key_type = BCRYPT_DH_PUBLIC_BLOB;
}
else {
/* We also need to extract the private portion of the key to
* set it in the `*dhctx' bignum if the raw KDF is not supported.
* First measure up the size of the required buffer. */
key_type = BCRYPT_DH_PRIVATE_BLOB;
}
status = BCryptExportKey(dhctx->dh_handle, NULL, key_type,
NULL, 0, &key_length_bytes, 0);
if(!BCRYPT_SUCCESS(status)) {
return -1;
}
blob = malloc(key_length_bytes);
if(!blob) {
return -1;
}
status = BCryptExportKey(dhctx->dh_handle, NULL, key_type,
blob, key_length_bytes,
&key_length_bytes, 0);
if(!BCRYPT_SUCCESS(status)) {
if(hasAlgDHwithKDF == 1) {
/* We have no private data, because raw KDF is supported */
free(blob);
}
else { /* we may have potentially private data, use secure free */
_libssh2_wincng_safe_free(blob, key_length_bytes);
}
return -1;
}
if(hasAlgDHwithKDF == -1) {
/* We know that the raw KDF is not supported, so discard this */
BCryptDestroyKey(dhctx->dh_handle);
dhctx->dh_handle = NULL;
}
/* BCRYPT_DH_PUBLIC_BLOB corresponds to a BCRYPT_DH_KEY_BLOB header
* followed by the Modulus, Generator and Public data. Those components
* each have equal size, specified by dh_key_blob->cbKey. */
dh_key_blob = (BCRYPT_DH_KEY_BLOB*)blob;
if(_libssh2_wincng_bignum_resize(public, dh_key_blob->cbKey)) {
if(hasAlgDHwithKDF == 1) {
/* We have no private data, because raw KDF is supported */
free(blob);
}
else { /* we may have potentially private data, use secure free */
_libssh2_wincng_safe_free(blob, key_length_bytes);
}
return -1;
}
/* Copy the public key data into the public bignum data buffer */
memcpy(public->bignum,
blob + sizeof(*dh_key_blob) + 2 * dh_key_blob->cbKey,
dh_key_blob->cbKey);
if(dh_key_blob->dwMagic == BCRYPT_DH_PRIVATE_MAGIC) {
/* BCRYPT_DH_PRIVATE_BLOB additionally contains the Private data */
dhctx->bn = _libssh2_wincng_bignum_init();
if(!dhctx->bn) {
_libssh2_wincng_safe_free(blob, key_length_bytes);
return -1;
}
if(_libssh2_wincng_bignum_resize(dhctx->bn, dh_key_blob->cbKey)) {
_libssh2_wincng_safe_free(blob, key_length_bytes);
return -1;
}
/* Copy the private key data into the dhctx bignum data buffer */
memcpy(dhctx->bn->bignum,
blob + sizeof(*dh_key_blob) + 3 * dh_key_blob->cbKey,
dh_key_blob->cbKey);
/* Make sure the private key is an odd number, because only
* odd primes can be used with the RSA-based fallback while
* DH itself does not seem to care about it being odd or not. */
if(!(dhctx->bn->bignum[dhctx->bn->length-1] % 2)) {
_libssh2_wincng_safe_free(blob, key_length_bytes);
/* discard everything first, then try again */
_libssh2_dh_dtor(dhctx);
_libssh2_dh_init(dhctx);
continue;
}
}
return 0;
}
/* Generate x and e */
dhctx->bn = _libssh2_wincng_bignum_init();
if(!dhctx->bn)
return -1;
if(_libssh2_wincng_bignum_rand(dhctx->bn, group_order * 8 - 1, 0, -1))
return -1;
if(_libssh2_wincng_bignum_mod_exp(public, g, dhctx->bn, p))
return -1;
return 0;
}
/* Computes the Diffie-Hellman secret from the previously created context
* `*dhctx', the public key `f' from the other party and the same prime `p'
* used at context creation. The result is stored in `secret'. 0 is returned
* upon success, else -1. */
int
_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
_libssh2_bn *f, _libssh2_bn *p)
{
if(_libssh2_wincng.hAlgDH && _libssh2_wincng.hasAlgDHwithKDF != -1 &&
dhctx->dh_handle && dhctx->dh_params && f) {
BCRYPT_KEY_HANDLE peer_public = NULL;
BCRYPT_SECRET_HANDLE agreement = NULL;
ULONG secret_len_bytes = 0;
unsigned char *blob;
int status;
unsigned char *start, *end;
BCRYPT_DH_KEY_BLOB *public_blob = NULL;
DWORD key_length_bytes = max(f->length, dhctx->dh_params->cbKeyLength);
DWORD public_blob_len = sizeof(*public_blob) + 3 * key_length_bytes;
{
/* Populate a BCRYPT_DH_KEY_BLOB; after the header follows the
* Modulus, Generator and Public data. Those components must have
* equal size in this representation. */
unsigned char *dest;
unsigned char *src;
blob = malloc(public_blob_len);
if(!blob) {
return -1;
}
public_blob = (BCRYPT_DH_KEY_BLOB*)blob;
public_blob->dwMagic = BCRYPT_DH_PUBLIC_MAGIC;
public_blob->cbKey = key_length_bytes;
dest = (unsigned char *)(public_blob + 1);
src = (unsigned char *)(dhctx->dh_params + 1);
/* Modulus (the p-value from the first call) */
memcpy_with_be_padding(dest, key_length_bytes, src,
dhctx->dh_params->cbKeyLength);
/* Generator (the g-value from the first call) */
memcpy_with_be_padding(dest + key_length_bytes, key_length_bytes,
src + dhctx->dh_params->cbKeyLength,
dhctx->dh_params->cbKeyLength);
/* Public from the peer */
memcpy_with_be_padding(dest + 2*key_length_bytes, key_length_bytes,
f->bignum, f->length);
}
/* Import the peer public key information */
status = BCryptImportKeyPair(_libssh2_wincng.hAlgDH, NULL,
BCRYPT_DH_PUBLIC_BLOB, &peer_public, blob,
public_blob_len, 0);
if(!BCRYPT_SUCCESS(status)) {
goto out;
}
/* Set up a handle that we can use to establish the shared secret
* between ourselves (our saved dh_handle) and the peer. */
status = BCryptSecretAgreement(dhctx->dh_handle, peer_public,
&agreement, 0);
if(!BCRYPT_SUCCESS(status)) {
goto out;
}
/* Compute the size of the buffer that is needed to hold the derived
* shared secret. */
status = BCryptDeriveKey(agreement, BCRYPT_KDF_RAW_SECRET, NULL, NULL,
0, &secret_len_bytes, 0);
if(!BCRYPT_SUCCESS(status)) {
if(status == STATUS_NOT_SUPPORTED) {
_libssh2_wincng.hasAlgDHwithKDF = -1;
}
goto out;
}
/* Expand the secret bignum to be ready to receive the derived secret
* */
if(_libssh2_wincng_bignum_resize(secret, secret_len_bytes)) {
status = STATUS_NO_MEMORY;
goto out;
}
/* And populate the secret bignum */
status = BCryptDeriveKey(agreement, BCRYPT_KDF_RAW_SECRET, NULL,
secret->bignum, secret_len_bytes,
&secret_len_bytes, 0);
if(!BCRYPT_SUCCESS(status)) {
if(status == STATUS_NOT_SUPPORTED) {
_libssh2_wincng.hasAlgDHwithKDF = -1;
}
goto out;
}
/* Counter to all the other data in the BCrypt APIs, the raw secret is
* returned to us in host byte order, so we need to swap it to big
* endian order. */
start = secret->bignum;
end = secret->bignum + secret->length - 1;
while(start < end) {
unsigned char tmp = *end;
*end = *start;
*start = tmp;
start++;
end--;
}
status = 0;
_libssh2_wincng.hasAlgDHwithKDF = 1;
out:
if(peer_public) {
BCryptDestroyKey(peer_public);
}
if(agreement) {
BCryptDestroySecret(agreement);
}
if(status == STATUS_NOT_SUPPORTED &&
_libssh2_wincng.hasAlgDHwithKDF == -1) {
goto fb; /* fallback to RSA-based implementation */
}
return BCRYPT_SUCCESS(status) ? 0 : -1;
}
fb:
/* Compute the shared secret */
return _libssh2_wincng_bignum_mod_exp(secret, f, dhctx->bn, p);
}
#endif /* LIBSSH2_WINCNG */

View File

@@ -1,5 +1,7 @@
#ifndef __LIBSSH2_WINCNG_H
#define __LIBSSH2_WINCNG_H
/*
* Copyright (C) 2013-2015 Marc Hoersken <info@marc-hoersken.de>
* Copyright (C) 2013-2020 Marc Hoersken <info@marc-hoersken.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -47,7 +49,6 @@
#include <windows.h>
#include <bcrypt.h>
#define LIBSSH2_MD5 1
#define LIBSSH2_HMAC_RIPEMD 0
@@ -69,6 +70,7 @@
#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)
@@ -88,10 +90,12 @@ struct _libssh2_wincng_ctx {
BCRYPT_ALG_HANDLE hAlgHashMD5;
BCRYPT_ALG_HANDLE hAlgHashSHA1;
BCRYPT_ALG_HANDLE hAlgHashSHA256;
BCRYPT_ALG_HANDLE hAlgHashSHA384;
BCRYPT_ALG_HANDLE hAlgHashSHA512;
BCRYPT_ALG_HANDLE hAlgHmacMD5;
BCRYPT_ALG_HANDLE hAlgHmacSHA1;
BCRYPT_ALG_HANDLE hAlgHmacSHA256;
BCRYPT_ALG_HANDLE hAlgHmacSHA384;
BCRYPT_ALG_HANDLE hAlgHmacSHA512;
BCRYPT_ALG_HANDLE hAlgRSA;
BCRYPT_ALG_HANDLE hAlgDSA;
@@ -99,9 +103,11 @@ struct _libssh2_wincng_ctx {
BCRYPT_ALG_HANDLE hAlgAES_ECB;
BCRYPT_ALG_HANDLE hAlgRC4_NA;
BCRYPT_ALG_HANDLE hAlg3DES_CBC;
BCRYPT_ALG_HANDLE hAlgDH;
volatile int hasAlgDHwithKDF; /* -1=no, 0=maybe, 1=yes */
};
struct _libssh2_wincng_ctx _libssh2_wincng;
extern struct _libssh2_wincng_ctx _libssh2_wincng;
/*******************************************************************/
@@ -162,7 +168,17 @@ typedef struct __libssh2_wincng_hash_ctx {
#define libssh2_sha256(data, datalen, hash) \
_libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA256, \
hash, SHA256_DIGEST_LENGTH)
#define libssh2_sha384_ctx _libssh2_wincng_hash_ctx
#define libssh2_sha384_init(ctx) \
(_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA384, \
SHA384_DIGEST_LENGTH, NULL, 0) == 0)
#define libssh2_sha384_update(ctx, data, datalen) \
_libssh2_wincng_hash_update(&ctx, (unsigned char *) data, datalen)
#define libssh2_sha384_final(ctx, hash) \
_libssh2_wincng_hash_final(&ctx, hash)
#define libssh2_sha384(data, datalen, hash) \
_libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA384, \
hash, SHA384_DIGEST_LENGTH)
#define libssh2_sha512_ctx _libssh2_wincng_hash_ctx
#define libssh2_sha512_init(ctx) \
(_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA512, \
@@ -385,7 +401,17 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void);
* Windows CNG backend: Diffie-Hellman support
*/
#define _libssh2_dh_ctx struct _libssh2_wincng_bignum *
typedef struct {
/* holds our private and public key components */
BCRYPT_KEY_HANDLE dh_handle;
/* records the parsed out modulus and generator
* parameters that are shared with the peer */
BCRYPT_DH_PARAMETER_HEADER *dh_params;
/* records the parsed out private key component for
* fallback if the DH API raw KDF is not supported */
struct _libssh2_wincng_bignum *bn;
} _libssh2_dh_ctx;
#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)
@@ -569,3 +595,5 @@ _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
_libssh2_bn *f, _libssh2_bn *p);
extern void
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
#endif /* __LIBSSH2_WINCNG_H */

View File

@@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 2011-2018 Free Software Foundation, Inc.
# Copyright (C) 2011-2020 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -42,11 +42,13 @@ print_usage ()
{
cat <<END
Usage:
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
[--expect-failure={yes|no}] [--color-tests={yes|no}]
[--enable-hard-errors={yes|no}] [--]
test-driver --test-name NAME --log-file PATH --trs-file PATH
[--expect-failure {yes|no}] [--color-tests {yes|no}]
[--enable-hard-errors {yes|no}] [--]
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
See the GNU Automake documentation for information.
END
}

View File

@@ -29,7 +29,7 @@ $ man2help -a [-.docs]AUTHORS.; libssh2.hlp -b 2
$ man2help -a [-.docs]BINDINGS.; libssh2.hlp -b 2
$ man2help -a [-.docs]HACKING.; libssh2.hlp -b 2
$ if f$search("[]HACKING_CRYPTO.") .nes. "" then delete []HACKING_CRYPTO.;*
$ copy [-.docs]HACKING.CRYPTO; []HACKING_CRYPTO.
$ copy [-.docs]HACKING-CRYPTO; []HACKING_CRYPTO.
$ man2help -a []HACKING_CRYPTO.; libssh2.hlp -b 2
$ man2help -a [-.docs]TODO.; libssh2.hlp -b 2
$!

View File

@@ -263,6 +263,10 @@ SOURCE=..\src\agent.c
# End Source File
# Begin Source File
SOURCE=..\src\agent_win.c
# End Source File
# Begin Source File
SOURCE=..\src\bcrypt_pbkdf.c
# End Source File
# Begin Source File
@@ -363,6 +367,10 @@ SOURCE=..\src\wincng.c
# PROP Default_Filter "h;hpp;hxx"
# Begin Source File
SOURCE=..\src\agent.h
# End Source File
# Begin Source File
SOURCE=..\src\blf.h
# End Source File
# Begin Source File

View File

@@ -141,6 +141,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\agent.c" />
<ClCompile Include="..\src\agent_win.c" />
<ClCompile Include="..\src\bcrypt_pbkdf.c" />
<ClCompile Include="..\src\blowfish.c" />
<ClCompile Include="..\src\channel.c" />
@@ -166,6 +167,7 @@
<ClCompile Include="..\src\wincng.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\agent.h" />
<ClInclude Include="..\src\blf.h" />
<ClInclude Include="..\src\channel.h" />
<ClInclude Include="..\src\comp.h" />