diff --git a/.gitignore b/.gitignore index 2a661f380..dc7feb746 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ libpcap/pcap-savefile.manfile libpcap/pcap-tstamp.manmisc libpcap/pcap_version.h libssh2/src/libssh2_config.h +libssh2/lib/ libpcre/pcre-config ndiff/INSTALLED_FILES libz/contrib/vstudio/vc11/Debug_lib/ diff --git a/CHANGELOG b/CHANGELOG index d0730551c..f08f74380 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ #Nmap Changelog ($Id$); -*-text-*- +o Upgrade libssh2 to 1.9.0, fixing compilation with OpenSSL 1.1.0 API. + o [GH#1717][GH#1718] Processing of IP address CIDR blocks was not working correctly on ppc64, ppc64le, and s390x architectures. [rfrohl, nnposter] diff --git a/libssh2/Makefile.OpenSSL.inc b/libssh2/Makefile.OpenSSL.inc index 76f3e85ca..1e4e8f0bb 100644 --- a/libssh2/Makefile.OpenSSL.inc +++ b/libssh2/Makefile.OpenSSL.inc @@ -1,2 +1,3 @@ CRYPTO_CSOURCES = openssl.c CRYPTO_HHEADERS = openssl.h +CRYPTO_LTLIBS = $(LTLIBSSL) diff --git a/libssh2/Makefile.WinCNG.inc b/libssh2/Makefile.WinCNG.inc index c18350eed..bbcb82bfd 100644 --- a/libssh2/Makefile.WinCNG.inc +++ b/libssh2/Makefile.WinCNG.inc @@ -1,2 +1,3 @@ CRYPTO_CSOURCES = wincng.c CRYPTO_HHEADERS = wincng.h +CRYPTO_LTLIBS = $(LTLIBBCRYPT) $(LTLIBCRYPT32) diff --git a/libssh2/Makefile.am b/libssh2/Makefile.am index 07eb81bc4..6411e8a04 100644 --- a/libssh2/Makefile.am +++ b/libssh2/Makefile.am @@ -1,10 +1,9 @@ AUTOMAKE_OPTIONS = foreign nostdinc -SUBDIRS = src -#SUBDIRS = src tests docs -#if BUILD_EXAMPLES -#SUBDIRS += example -#endif +SUBDIRS = src tests docs +if BUILD_EXAMPLES +SUBDIRS += example +endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libssh2.pc @@ -148,3 +147,6 @@ $(VCPROJ): win32/vc8proj.head win32/vc8proj.foot Makefile.am done; \ cat $(srcdir)/vc8proj.foot) | \ 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 diff --git a/libssh2/Makefile.in b/libssh2/Makefile.in index 4577a04a0..32d97cba7 100644 --- a/libssh2/Makefile.in +++ b/libssh2/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -89,6 +89,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@BUILD_EXAMPLES_TRUE@am__append_1 = example subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \ @@ -173,7 +174,7 @@ am__recursive_targets = \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - cscope distdir dist dist-all distcheck + cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is @@ -194,7 +195,7 @@ am__define_uniq_tagged_files = \ ETAGS = etags CTAGS = ctags CSCOPE = cscope -DIST_SUBDIRS = $(SUBDIRS) +DIST_SUBDIRS = src tests docs example am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.inc \ $(srcdir)/libssh2.pc.in COPYING ChangeLog NEWS README compile \ config.guess config.rpath config.sub depcomp install-sh \ @@ -272,7 +273,7 @@ GREP = @GREP@ HAVE_LIBBCRYPT = @HAVE_LIBBCRYPT@ HAVE_LIBCRYPT32 = @HAVE_LIBCRYPT32@ HAVE_LIBGCRYPT = @HAVE_LIBGCRYPT@ -HAVE_LIBMBEDTLS = @HAVE_LIBMBEDTLS@ +HAVE_LIBMBEDCRYPTO = @HAVE_LIBMBEDCRYPTO@ HAVE_LIBSSL = @HAVE_LIBSSL@ HAVE_LIBZ = @HAVE_LIBZ@ INSTALL = @INSTALL@ @@ -288,8 +289,8 @@ LIBCRYPT32 = @LIBCRYPT32@ LIBCRYPT32_PREFIX = @LIBCRYPT32_PREFIX@ LIBGCRYPT = @LIBGCRYPT@ LIBGCRYPT_PREFIX = @LIBGCRYPT_PREFIX@ -LIBMBEDTLS = @LIBMBEDTLS@ -LIBMBEDTLS_PREFIX = @LIBMBEDTLS_PREFIX@ +LIBMBEDCRYPTO = @LIBMBEDCRYPTO@ +LIBMBEDCRYPTO_PREFIX = @LIBMBEDCRYPTO_PREFIX@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSREQUIRED = @LIBSREQUIRED@ @@ -304,7 +305,7 @@ LN_S = @LN_S@ LTLIBBCRYPT = @LTLIBBCRYPT@ LTLIBCRYPT32 = @LTLIBCRYPT32@ LTLIBGCRYPT = @LTLIBGCRYPT@ -LTLIBMBEDTLS = @LTLIBMBEDTLS@ +LTLIBMBEDCRYPTO = @LTLIBMBEDCRYPTO@ LTLIBOBJS = @LTLIBOBJS@ LTLIBSSL = @LTLIBSSL@ LTLIBZ = @LTLIBZ@ @@ -388,7 +389,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign nostdinc -SUBDIRS = src +SUBDIRS = src tests docs $(am__append_1) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libssh2.pc include_HEADERS = \ @@ -436,10 +437,11 @@ CRYPTO_CSOURCES = openssl.c wincng.c mbedtls.c 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 + version.c knownhost.c agent.c $(CRYPTO_CSOURCES) pem.c keepalive.c global.c \ + blowfish.c bcrypt_pbkdf.c HHEADERS = libssh2_priv.h $(CRYPTO_HHEADERS) transport.h channel.h comp.h \ - mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h + mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h # Makefile.inc provides the CSOURCES and HHEADERS defines WIN32SOURCES = $(CSOURCES) @@ -468,8 +470,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(srcdir)/Makefile.inc $(am__empty): @@ -641,7 +643,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -709,7 +714,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -735,7 +740,7 @@ dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -753,7 +758,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -763,7 +768,7 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac @@ -1052,6 +1057,9 @@ $(VCPROJ): win32/vc8proj.head win32/vc8proj.foot Makefile.am cat $(srcdir)/vc8proj.foot) | \ 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 + # 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. .NOEXPORT: diff --git a/libssh2/Makefile.inc b/libssh2/Makefile.inc index 8f2e570cb..ff8e6efa8 100644 --- a/libssh2/Makefile.inc +++ b/libssh2/Makefile.inc @@ -1,6 +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 + version.c knownhost.c agent.c $(CRYPTO_CSOURCES) pem.c keepalive.c global.c \ + blowfish.c bcrypt_pbkdf.c HHEADERS = libssh2_priv.h $(CRYPTO_HHEADERS) transport.h channel.h comp.h \ - mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h + mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h diff --git a/libssh2/Makefile.libgcrypt.inc b/libssh2/Makefile.libgcrypt.inc index 5d56292ce..0a3aae9aa 100644 --- a/libssh2/Makefile.libgcrypt.inc +++ b/libssh2/Makefile.libgcrypt.inc @@ -1,2 +1,3 @@ CRYPTO_CSOURCES = libgcrypt.c CRYPTO_HHEADERS = libgcrypt.h +CRYPTO_LTLIBS = $(LTLIBGCRYPT) diff --git a/libssh2/Makefile.mbedTLS.inc b/libssh2/Makefile.mbedTLS.inc index 7e9786429..b9f19fce1 100644 --- a/libssh2/Makefile.mbedTLS.inc +++ b/libssh2/Makefile.mbedTLS.inc @@ -1,2 +1,3 @@ CRYPTO_CSOURCES = mbedtls.c CRYPTO_HHEADERS = mbedtls.h +CRYPTO_LTLIBS = $(LTLIBMBEDCRYPTO) diff --git a/libssh2/NEWS b/libssh2/NEWS index 3b1fc259a..4c7f1eacf 100644 --- a/libssh2/NEWS +++ b/libssh2/NEWS @@ -1,52 +1,1260 @@ Changelog for the libssh2 project. Generated with git2news.pl -Version 1.8.1 (14 Mar 2019) +GitHub (19 Jun 2019) +- [Will Cosgrove brought this change] -Will Cosgrove (14 Mar 2019) + 1.9 Formatting + +- [Will Cosgrove brought this change] + + 1.9 Release notes + +Will Cosgrove (17 May 2019) +- [Alexander Curtiss brought this change] + + libgcrypt.c : Fixed _libssh2_rsa_sha1_sign memory leak. (#370) + + File: libgcrypt.c + + Notes : Added calls to gcry_sexp_release to free memory allocated by gcry_sexp_find_token + + Credit : + Reporter : beckmi + PR by: Alexander Curtiss + +- [Orivej Desh brought this change] + + libssh2_priv.h : Fix musl build warning on sys/poll.h (#346) + + File : libssh2_priv.h + + Notes : + musl prints `redirecting incorrect #include to ` + http://git.musl-libc.org/cgit/musl/commit/include/sys/poll.h?id=54446d730cfb17c5f7bcf57f139458678f5066cc + + poll is defined by POSIX to be in poll.h: + http://pubs.opengroup.org/onlinepubs/7908799/xsh/poll.html + + Credit : Orivej Desh + +GitHub (1 May 2019) +- [Will Cosgrove brought this change] + + kex.c : additional bounds checks in diffie_hellman_sha1/256 (#361) + + Files : kex.c, misc.c, misc.h + + Notes : + Fixed possible out of bounds memory access when reading malformed data in diffie_hellman_sha1() and diffie_hellman_sha256(). + + Added _libssh2_copy_string() to misc.c to return an allocated and filled char buffer from a string_buf offset. Removed no longer needed s var in kmdhgGPshakex_state_t. + +Will Cosgrove (26 Apr 2019) +- [Tseng Jun brought this change] + + sftp.c : sftp_bin2attr() Correct attrs->gid assignment (#366) + + Regression with fix for #339 + + Credit : Tseng Jun + +- [Tseng Jun brought this change] + + kex.c : Correct type cast in curve25519_sha256() (#365) + +GitHub (24 Apr 2019) +- [Will Cosgrove brought this change] + + transport.c : scope local total_num var (#364) + + file : transport.c + notes : move local `total_num` variable inside of if block to prevent scope access issues which caused #360. + +Will Cosgrove (24 Apr 2019) +- [doublex brought this change] + + transport.c : fixes bounds check if partial packet is read + + Files : transport.c + + Issue : #360 + + Notes : + 'p->total_num' instead of local value total_num when doing bounds check. + + Credit : Doublex + +GitHub (23 Apr 2019) +- [Will Cosgrove brought this change] + + Editor config file for source files (#322) + + Simple start to an editor config file when editing source files to make sure they are configured correctly. + +- [Will Cosgrove brought this change] + + misc.c : String buffer API improvements (#332) + + Files : misc.c, hostkey.c, kex.c, misc.h, openssl.c, sftp.c + + Notes : + * updated _libssh2_get_bignum_bytes and _libssh2_get_string. Now pass in length as an argument instead of returning it to keep signedness correct. Now returns -1 for failure, 0 for success. + + _libssh2_check_length now returns 0 on success and -1 on failure to match the other string_buf functions. Added comment to _libssh2_check_length. + + Credit : Will Cosgrove + +Will Cosgrove (19 Apr 2019) +- [doublex brought this change] + + mbedtls.c : _libssh2_mbedtls_rsa_new_private_frommemory() allow private-key from memory (#359) + + File : mbedtls.c + + Notes: _libssh2_mbedtls_rsa_new_private_frommemory() fixes private-key from memory reading to by adding NULL terminator before parsing; adds passphrase support. + + Credit: doublex + +- [Ryan Kelley brought this change] + + Session.c : banner_receive() from leaking when accessing non ssh ports (#356) + + File : session.c + + Release previous banner in banner_receive() if the session is reused after a failed connection. + + Credit : Ryan Kelley + +GitHub (11 Apr 2019) +- [Will Cosgrove brought this change] + + Formatting in agent.c + + Removed whitespace. + +- [Will Cosgrove brought this change] + + Fixed formatting in agent.c + + Quiet linter around a couple if blocks and pointer. + +Will Cosgrove (11 Apr 2019) +- [Zhen-Huan HWANG brought this change] + + sftp.c : discard and reset oversized packet in sftp_packet_read() (#269) + + file : sftp.c + + notes : when sftp_packet_read() encounters an sftp packet which exceeds SFTP max packet size it now resets the reading state so it can continue reading. + + credit : Zhen-Huan HWANG + +GitHub (11 Apr 2019) +- [Will Cosgrove brought this change] + + Add agent functions libssh2_agent_get_identity_path() and libssh2_agent_set_identity_path() (#308) + + File : agent.c + + Notes : + Libssh2 uses the SSH_AUTH_SOCK env variable to read the system agent location. However, when using a custom agent path you have to set this value using setenv which is not thread-safe. The new functions allow for a way to set a custom agent socket path in a thread safe manor. + +- [Will Cosgrove brought this change] + + Simplified _libssh2_check_length (#350) + + * Simplified _libssh2_check_length + + misc.c : _libssh2_check_length() + + Removed cast and improved bounds checking and format. + + Credit : Yuriy M. Kaminskiy + +- [Will Cosgrove brought this change] + + _libssh2_check_length() : additional bounds check (#348) + + Misc.c : _libssh2_check_length() + + Ensure the requested length is less than the total length before doing the additional bounds check + +Daniel Stenberg (25 Mar 2019) +- misc: remove 'offset' from string_buf + + It isn't necessary. + + Closes #343 + +- sftp: repair mtime from e1ead35e475 + + A regression from e1ead35e4759 broke the SFTP mtime logic in + sftp_bin2attr + + Also simplified the _libssh2_get_u32/u64 functions slightly. + + Closes #342 + +- session_disconnect: don't zero state, just clear the right bit + + If we clear the entire field, the freeing of data in session_free() is + skipped. Instead just clear the bit that risk making the code get stuck + in the transport functions. + + Regression from 4d66f6762ca3fc45d9. + + Reported-by: dimmaq on github + Fixes #338 + Closes #340 + +- libssh2_sftp.h: restore broken ABI + + Commit 41fbd44 changed variable sizes/types in a public struct which + broke the ABI, which breaks applications! + + This reverts that change. + + Closes #339 + +- style: make includes and examples code style strict + + make travis and the makefile rule verify them too + + Closes #334 + +GitHub (21 Mar 2019) +- [Daniel Stenberg brought this change] + + create a github issue template + +Daniel Stenberg (21 Mar 2019) +- stale-bot: activated + + The stale bot will automatically mark stale issues (inactive for 90 + days) and if still untouched after 21 more days, close them. + + See https://probot.github.io/apps/stale/ + +- libssh2_session_supported_algs.3: fix formatting mistakes + + Reported-by: Max Horn + Fixes #57 + +- [Zenju brought this change] + + libssh2.h: Fix Error C2371 'ssize_t': redefinition + + Closes #331 + +- travis: add code style check + + Closes #324 + +- code style: unify code style + + Indent-level: 4 + Max columns: 79 + No spaces after if/for/while + Unified brace positions + Unified white spaces + +- src/checksrc.pl: code style checker + + imported as-is from curl + +Will Cosgrove (19 Mar 2019) +- Merge branch 'MichaelBuckley-michaelbuckley-security-fixes' + +- Silence unused var warnings (#329) + + Silence warnings about unused variables in this test + +- Removed unneeded > 0 check + + When checking `userauth_kybd_num_prompts > 100` we don't care if it's also above zero. + +- [Matthew D. Fuller brought this change] + + Spell OpenSS_H_ right when talking about their specific private key (#321) + + Good catch, thanks. + +GitHub (19 Mar 2019) +- [Will Cosgrove brought this change] + + Silence unused var warnings (#329) + + Silence warnings about unused variables in this test + +Michael Buckley (19 Mar 2019) +- Fix more scope and printf warning errors + +- Silence unused variable warning + +GitHub (19 Mar 2019) +- [Will Cosgrove brought this change] + + Removed unneeded > 0 check + + When checking `userauth_kybd_num_prompts > 100` we don't care if it's also above zero. + +Will Cosgrove (19 Mar 2019) +- [Matthew D. Fuller brought this change] + + Spell OpenSS_H_ right when talking about their specific private key (#321) + + Good catch, thanks. + +Michael Buckley (18 Mar 2019) +- Fix errors identified by the build process + +- Fix casting errors after merge + +GitHub (18 Mar 2019) - [Michael Buckley brought this change] - More 1.8.0 security fixes (#316) + Merge branch 'master' into michaelbuckley-security-fixes + +Michael Buckley (18 Mar 2019) +- Move fallback SIZE_MAX and UINT_MAX to libssh2_priv.h + +- Fix type and logic issues with _libssh2_get_u64 + +Daniel Stenberg (17 Mar 2019) +- examples: fix various compiler warnings + +- lib: fix various compiler warnings + +- session: ignore pedantic warnings for funcpointer <=> void * + +- travis: add a build using configure - * Defend against possible integer overflows in comp_method_zlib_decomp. + Closes #320 + +- configure: provide --enable-werror + +- appveyor: remove old builds that mostly cause failures - * Defend against writing beyond the end of the payload in _libssh2_transport_read(). + ... and only run on master branch. - * Sanitize padding_length - _libssh2_transport_read(). https://libssh2.org/CVE-2019-3861.html + Closes #323 + +- cmake: add two missing man pages to get installed too + + Both libssh2_session_handshake.3 and + libssh2_userauth_publickey_frommemory.3 were installed by the configure + build already. + + Reported-by: Arfrever on github + Fixes #278 + +- include/libssh2.h: warning: "_WIN64" is not defined, evaluates to 0 + + We don't use #if for defines that might not be defined. + +- pem: //-comments are not allowed + +Will Cosgrove (14 Mar 2019) +- [Daniel Stenberg brought this change] + + userauth: fix "Function call argument is an uninitialized value" (#318) + + Detected by scan-build. + +- fixed unsigned/signed issue + +Daniel Stenberg (15 Mar 2019) +- session_disconnect: clear state + + If authentication is started but not completed before the application + gives up and instead wants to shut down the session, the '->state' field + might still be set and thus effectively dead-lock session_disconnect. + + This happens because both _libssh2_transport_send() and + _libssh2_transport_read() refuse to do anything as long as state is set + without the LIBSSH2_STATE_KEX_ACTIVE bit. + + Reported in curl bug https://github.com/curl/curl/issues/3650 + + Closes #310 + +Will Cosgrove (14 Mar 2019) +- Release notes from 1.8.1 + +Michael Buckley (14 Mar 2019) +- Use string_buf in sftp_init(). + +- Guard against out-of-bounds reads in publickey.c + +- Guard against out-of-bounds reads in session.c + +- Guard against out-of-bounds reads in userauth.c + +- Use LIBSSH2_ERROR_BUFFER_TOO_SMALL instead of LIBSSH2_ERROR_OUT_OF_BOUNDARY in sftp.c + +- Additional bounds checking in sftp.c + +- Additional length checks to prevent out-of-bounds reads and writes in _libssh2_packet_add(). https://libssh2.org/CVE-2019-3862.html + +- Add a required_size parameter to sftp_packet_require et. al. to require callers of these functions to handle packets that are too short. https://libssh2.org/CVE-2019-3860.html + +- Check the length of data passed to sftp_packet_add() to prevent out-of-bounds reads. + +- Prevent zero-byte allocation in sftp_packet_read() which could lead to an out-of-bounds read. https://libssh2.org/CVE-2019-3858.html + +- Sanitize padding_length - _libssh2_transport_read(). https://libssh2.org/CVE-2019-3861.html This prevents an underflow resulting in a potential out-of-bounds read if a server sends a too-large padding_length, possibly with malicious intent. - - * Prevent zero-byte allocation in sftp_packet_read() which could lead to an out-of-bounds read. https://libssh2.org/CVE-2019-3858.html - - * Check the length of data passed to sftp_packet_add() to prevent out-of-bounds reads. - - * Add a required_size parameter to sftp_packet_require et. al. to require callers of these functions to handle packets that are too short. https://libssh2.org/CVE-2019-3860.html - - * Additional length checks to prevent out-of-bounds reads and writes in _libssh2_packet_add(). https://libssh2.org/CVE-2019-3862.html + +- Defend against writing beyond the end of the payload in _libssh2_transport_read(). + +- Defend against possible integer overflows in comp_method_zlib_decomp. GitHub (14 Mar 2019) - [Will Cosgrove brought this change] - 1.8 Security fixes (#314) + Security fixes (#315) - * fixed possible integer overflow in packet_length + * Bounds checks - CVE https://www.libssh2.org/CVE-2019-3861.html + Fixes for CVEs + https://www.libssh2.org/CVE-2019-3863.html + https://www.libssh2.org/CVE-2019-3856.html - * fixed possible interger overflow with userauth_keyboard_interactive + * Packet length bounds check - CVE https://www.libssh2.org/CVE-2019-3856.html + CVE + https://www.libssh2.org/CVE-2019-3855.html - * fixed possible out zero byte/incorrect bounds allocation + * Response length check - CVE https://www.libssh2.org/CVE-2019-3857.html + CVE + https://www.libssh2.org/CVE-2019-3859.html - * bounds checks for response packets + * Bounds check - * fixed integer overflow in userauth_keyboard_interactive + CVE + https://www.libssh2.org/CVE-2019-3857.html - CVE https://www.libssh2.org/CVE-2019-3863.html + * Bounds checking - * 1.8.1 release notes + CVE + https://www.libssh2.org/CVE-2019-3859.html + + and additional data validation + + * Check bounds before reading into buffers + + * Bounds checking + + CVE + https://www.libssh2.org/CVE-2019-3859.html + + * declare SIZE_MAX and UINT_MAX if needed + +- [Will Cosgrove brought this change] + + fixed type warnings (#309) + +- [Will Cosgrove brought this change] + + Bumping version number for pending 1.8.1 release + +Will Cosgrove (4 Mar 2019) +- [Daniel Stenberg brought this change] + + _libssh2_string_buf_free: use correct free (#304) + + Use LIBSSH2_FREE() here, not free(). We allow memory function + replacements so free() is rarely the right choice... + +GitHub (26 Feb 2019) +- [Will Cosgrove brought this change] + + Fix for building against libreSSL #302 + + Changed to use the check we use elsewhere. + +- [Will Cosgrove brought this change] + + Fix for when building against LibreSSL #302 + +Will Cosgrove (25 Feb 2019) +- [gartens brought this change] + + docs: update libssh2_hostkey_hash.3 [ci skip] (#301) + +GitHub (21 Feb 2019) +- [Will Cosgrove brought this change] + + fix malloc/free mismatches #296 (#297) + +- [Will Cosgrove brought this change] + + Replaced malloc with calloc #295 + +- [Will Cosgrove brought this change] + + Abstracted OpenSSL calls out of hostkey.c (#294) + +- [Will Cosgrove brought this change] + + Fix memory dealloc impedance mis-match #292 (#293) + + When using ed25519 host keys and a custom memory allocator. + +- [Will Cosgrove brought this change] + + Added call to OpenSSL_add_all_digests() #288 + + For OpenSSL 1.0.x we need to call OpenSSL_add_all_digests(). + +Will Cosgrove (12 Feb 2019) +- [Zhen-Huan HWANG brought this change] + + SFTP: increase maximum packet size to 256K (#268) + + to match implementations like OpenSSH. + +- [Zenju brought this change] + + Fix https://github.com/libssh2/libssh2/pull/271 (#284) + +GitHub (16 Jan 2019) +- [Will Cosgrove brought this change] + + Agent NULL check in shutdown #281 + +Will Cosgrove (15 Jan 2019) +- [Adrian Moran brought this change] + + mbedtls: Fix leak of 12 bytes by each key exchange. (#280) + + Correctly free ducts by calling _libssh2_mbedtls_bignum_free() in dtor. + +- [alex-weaver brought this change] + + Fix error compiling on Win32 with STDCALL=ON (#275) + +GitHub (8 Nov 2018) +- [Will Cosgrove brought this change] + + Allow default permissions to be used in sftp_mkdir (#271) + + Added constant LIBSSH2_SFTP_DEFAULT_MODE to use the server default permissions when making a new directory + +Will Cosgrove (13 Sep 2018) +- [Giulio Benetti brought this change] + + openssl: fix dereferencing ambiguity potentially causing build failure (#267) + + When dereferencing from *aes_ctr_cipher, being a pointer itself, + ambiguity can occur; fixed possible build errors. + +Viktor Szakats (12 Sep 2018) +- win32/GNUmakefile: define HAVE_WINDOWS_H + + This macro was only used in test/example code before, now it is + also used in library code, but only defined automatically by + automake/cmake, so let's do the same for the standalone win32 + make file. + + It'd be probably better to just rely on the built-in _WIN32 macro + to detect the presence of windows.h though. It's already used + in most of libssh2 library code. There is a 3rd, similar macro + named LIBSSH2_WIN32, which might also be replaced with _WIN32. + + Ref: https://github.com/libssh2/libssh2/commit/8b870ad771cbd9cd29edbb3dbb0878e950f868ab + Closes https://github.com/libssh2/libssh2/pull/266 + +Marc Hoersken (2 Sep 2018) +- Fix conditional check for HAVE_DECL_SECUREZEROMEMORY + + "Unlike the other `AC_CHECK_*S' macros, when a symbol is not declared, + HAVE_DECL_symbol is defined to `0' instead of leaving HAVE_DECL_symbol + undeclared. When you are sure that the check was performed, + use HAVE_DECL_symbol in #if." + + Source: autoconf documentation for AC_CHECK_DECLS. + +- Fix implicit declaration of function 'SecureZeroMemory' + + Include window.h in order to use SecureZeroMemory on Windows. + +- Fix implicit declaration of function 'free' by including stdlib.h + +GitHub (27 Aug 2018) +- [Will Cosgrove brought this change] + + Use malloc abstraction function in pem parse + + Fix warning on WinCNG build. + +- [Will Cosgrove brought this change] + + Fixed possible junk memory read in sftp_stat #258 + +- [Will Cosgrove brought this change] + + removed INT64_C define (#260) + + No longer used. + +- [Will Cosgrove brought this change] + + Added conditional around engine.h include + +Will Cosgrove (6 Aug 2018) +- [Alex Crichton brought this change] + + Fix OpenSSL link error with `no-engine` support (#259) + + This commit fixes linking against an OpenSSL library that was compiled with + `no-engine` support by bypassing the initialization routines as they won't be + available anyway. + +GitHub (2 Aug 2018) +- [Will Cosgrove brought this change] + + ED25519 Key Support #39 (#248) + + OpenSSH Key and ED25519 support #39 + Added _libssh2_explicit_zero() to explicitly zero sensitive data in memory #120 + + * ED25519 Key file support - Requires OpenSSL 1.1.1 or later + * OpenSSH Key format reading support - Supports RSA/DSA/ECDSA/ED25519 types + * New string buffer reading functions - These add build-in bounds checking and convenance methods. Used for OpenSSL PEM file reading. + * Added new tests for OpenSSH formatted Keys + +- [Will Cosgrove brought this change] + + ECDSA key types are now explicit (#251) + + * ECDSA key types are now explicit + + Issue was brough up in pull request #248 + +Will Cosgrove (2 May 2018) +- [Jakob Egger brought this change] + + Add Instructions for building from Master (#249) + +GitHub (27 Apr 2018) +- [Will Cosgrove brought this change] + + Initialize sb_intl #226 + +Will Cosgrove (19 Apr 2018) +- [doublex brought this change] + + buffer overflow (valgrind) (#159) + +- [Brendan Shanks brought this change] + + mbedTLS: Remove some C99-style intermingled variable declarations (#196) + +GitHub (18 Apr 2018) +- [Will Cosgrove brought this change] + + fix for #160 + +Will Cosgrove (18 Apr 2018) +- [doublex brought this change] + + fix memory leak when using mbedtls backend (#158) + + _libssh2_bn_init_from_bin/_libssh2_bn_free would leak bignum from mbedtls_calloc(). + +- [Brendan Shanks brought this change] + + mbedTLS: Avoid multiple definition errors for context handles (#197) + +- [Tseng Jun brought this change] + + Fix the EVP cipher meth memory leakage problem (#244) + + * Fix the EVP cipher meth memory leakage problem + + Looks good, thanks for the fixes. + +Marc Hörsken (31 Mar 2018) +- [Will Cosgrove brought this change] + + Added ECDSA defines for WinCNG (#245) + + Fixed missing defines preventing building using WinCNG + +GitHub (30 Mar 2018) +- [Will Cosgrove brought this change] + + Fix for _libssh2_rsa_new with OpenSSL 1.0.x + + missing d value assignment. + +Will Cosgrove (20 Mar 2018) +- [Etienne Samson brought this change] + + A collection of small fixes (#198) + + * tests: Remove if-pyramids + + * tests: Switch run_command arguments + + * tests: Make run_command a vararg function + + * tests: Xcode doesn't obey CMake's test working directory + + * openssl: move manual AES-CTR cipher into crypto init + + * cmake: Move our include dir before all other include paths + +GitHub (15 Mar 2018) +- [Will Cosgrove brought this change] + + Fixes incorrect indexing of KEX prefs string + + After stripping out an invalid KEX pref entry, it would incorrectly advance again leaving invalid values in the list. + +Viktor Szakats (13 Mar 2018) +- tests: fix checksrc warnings + + Also: + * add 'static' qualifier to file-wide const buffers + * fix a non-ANSI C89 comment + * silence a mismatched fprintf() mask warning by adding a cast + +- cmake: recognize OpenSSL 1.1 .dll names + + Also fix some comment typos and a stray tab. + +- docs: update an URL [ci skip] + +Daniel Stenberg (12 Mar 2018) +- docs/SECURITY: the max embargo is 14 days now + +Viktor Szakats (12 Mar 2018) +- docs: spelling fixes [ci skip] + + Closes https://github.com/libssh2/libssh2/pull/222 + +GitHub (12 Mar 2018) +- [Will Cosgrove brought this change] + + Fixed minor tabs/spacing issues + +- [Will Cosgrove brought this change] + + Update kex.c + +- [Will Cosgrove brought this change] + + Added basic bounds checking #206 + + Basic bounds checking in ecdh_sha2_nistp() + +- [Will Cosgrove brought this change] + + Fixed Clang warning #206 + + Fixed possible garbage value for secret in an error case + +- [Will Cosgrove brought this change] + + Fixed incorrect #if to #ifdef #206 + + When checking HAVE_OPAQUE_STRUCTS. + +Viktor Szakats (12 Mar 2018) +- src: suppress two checksrc warnings + + Ref: https://github.com/libssh2/libssh2/pull/235 + +- src: address fopen() warnings, add missing copyright headers + + Ref: https://github.com/libssh2/libssh2/pull/235 + +- src: replace sprintf() with snprintf() + + Ref: https://github.com/libssh2/libssh2/pull/235 + +- src: fix checksrc warnings + + Use checksrc.pl from the curl project, with (for now) + suppressed long line warnings and indentation set to + 4 spaces. Fixes are whitespace for the most part. + + Warning count went down from 2704 to 12. + + Also fix codespell typos, two non-ANSI C89 comments + and a stray tab in include/libssh2.h. + + Ref: https://github.com/libssh2/libssh2/pull/235 + +- checksrc: add source style checker + + This is a slightly extended version of this original source + from the curl project: + https://github.com/curl/curl/blob/8b754c430b9a4c51aa606c687ee5014faf7c7b06/lib/checksrc.pl + + This version adds the following options to customize it for + libssh2 (plus some whitespace formatting): + + `-i` to override indentation spaces (2) + `-m` to override maximum line length (79) + + Command-line used to check libssh2 sources: + + $ ./checksrc.pl -i4 -m500 *.c *.h + + Closes https://github.com/libssh2/libssh2/pull/236 + +- src: add static qualifier + + To private, const strings. + + Closes https://github.com/libssh2/libssh2/pull/237 + +- [Will Cosgrove brought this change] + + Add support for ECDSA keys and host keys (#41) + + This commit lands full ECDSA key support when using the OpenSSL + backend. Which includes: + + New KEX methods: + ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521 + + Can now read OpenSSL formatted ECDSA key files. + + Now supports known host keys of type ecdsa-sha2-nistp256. + + New curve types: + NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1 + + Default host key preferred ordering is now nistp256, nistp384, + nistp521, rsa, dss. + + Ref: https://github.com/libssh2/libssh2/issues/41 + + Closes https://github.com/libssh2/libssh2/pull/206 + +GitHub (15 Dec 2017) +- [Will Cosgrove brought this change] + + Fixed possible crash when decoding invalid data + + When trying to decode invalid data, it frees the buffer but doesn't nil it so the caller gets a junk memory pointer which they could potentially double free. + +- [Will Cosgrove brought this change] + + Remove call to OpenSSL_add_all_ciphers() + + Now lives in libssh2 init() from PR #189 + +- [Will Cosgrove brought this change] + + Fixed incorrect reference to decrypted block + + Fixed incorrectly copied memory from p->buf into init instead of from the decrypted buffer block. The only reason this worked was because the crypt() function decrypts the value in-place and overwrites p->buf. I'm working on a fork that no longer does this and exposed this bug. + +Will Cosgrove (20 Oct 2017) +- [Pan brought this change] + + Fix typo in crypt.c (#218) + +Kamil Dudka (17 Oct 2017) +- session: avoid printing misleading debug messages + + ... while throwing LIBSSH2_ERROR_EAGAIN out of session_startup() + + If the session runs in blocking mode, LIBSSH2_ERROR_EAGAIN never reaches + the libssh2 API boundary and, in non-blocking mode, these messages are + suppressed by the condition in _libssh2_error_flags() anyway. + + Closes #211 + +Viktor Szakats (15 Oct 2017) +- win32/GNUmakefile: allow customizing dll suffixes + + - New `LIBSSH2_DLL_SUFFIX` envvar will add a suffix to the generated + libssh2 dll name. Useful to add `-x64` to 64-bit builds so that + it can live in the same directory as the 32-bit one. By default + this is empty. + + - New `LIBSSH2_DLL_A_SUFFIX` envvar to customize the suffix of the + generated import library (implib) for libssh2 .dll. It defaults + to `dll`, and it's useful to modify that to `.dll` to have the + standard naming scheme for mingw-built .dlls, i.e. `libssh2.dll.a`. + + Ref: https://github.com/curl/curl/commit/aaa16f80256abc1463fd9374815130a165222257 + + Closes https://github.com/libssh2/libssh2/pull/215 + +- makefile.m32: allow to override gcc, ar and ranlib + + Allow to ovverride certain build tools, making it possible to + use LLVM/Clang to build libssh2. The default behavior is unchanged. + To build with clang (as offered by MSYS2), these settings can + be used: + + LIBSSH2_CC=clang + LIBSSH2_AR=llvm-ar + LIBSSH2_RANLIB=llvm-ranlib + + Also adjust ranlib parameters to be compatible with LLVM/Clang's + ranlib tool. + + Closes https://github.com/libssh2/libssh2/pull/214 + +GitHub (27 Sep 2017) +- [Will Cosgrove brought this change] + + Fixes out of bounds memory access (#210) + + If an invalid PEM file is read and the lines are longer than 128 characters it will go out of bounds and crash on line 91. + +Will Cosgrove (11 Sep 2017) +- [Kamil Dudka brought this change] + + scp: do not NUL-terminate the command for remote exec (#208) + + It breaks SCP download/upload from/to certain server implementations. + + The bug does not manifest with OpenSSH, which silently drops the NUL + byte (eventually with any garbage that follows the NUL byte) before + executing it. + + Bug: https://bugzilla.redhat.com/1489736 + +GitHub (21 Aug 2017) +- [Viktor Szakats brought this change] + + openssl.c: remove no longer used variable (#204) + + after e378d2e30a40bd9bcee06dc3a4250f269098e200 + +- [Will Cosgrove brought this change] + + Fix for #188 (#189) + + * Update openssl.c + + * Create openssl.h + +Will Cosgrove (24 May 2017) +- [Marcel Raad brought this change] + + openssl: fix build with OpenSSL 1.1 API (#176) + + When building with OPENSSL_API_COMPAT=0x10100000L, OpenSSL_add_all_algorithms + and OpenSSL_add_all_ciphers don't exist. The corresponding functionality is + handled automatically with OpenSSL 1.1. + +- [Sune Bredahl brought this change] + + Add support for SHA256 hostkey fingerprints (#180) + + Looks good, thanks! + +GitHub (12 May 2017) +- [Will Cosgrove brought this change] + + Fix memory leak of crypt_ctx->h using openSSL 1.1+ (#177) + + Need to use EVP_CIPHER_CTX_free instead of EVP_CIPHER_CTX_reset. + +Marc Hoersken (2 Mar 2017) +- tests/openssh_server/authorized_keys: add key_rsa_encrypted.pub + +- tests: add simple test for passphrase-protected PEM file support + +- os400qc3: enable passphrase-protected PEM file support using pem.c + +- pem: fix indentation and replace assert after 386e012292 + +- [Keno Fischer brought this change] + + pem: add passphrase-protected PEM file support for libgcrypt and wincng + + Since they use our own PEM parser which did not support encrypted + PEM files, trying to use such files on these backends failed. + Fix that by augmenting the PEM parser to support encrypted PEM files. + +- [Thomas brought this change] + + misc: use time constant implementation for AES CTR increment + +- [Thomas brought this change] + + wincng: add AES CTR mode support (aes128-ctr, aes192-ctr, aes256-ctr) + +- [Thomas brought this change] + + openssl: move shared AES-CTR code into misc + +Daniel Stenberg (20 Dec 2016) +- [Alex Crichton brought this change] + + kex: acknowledge error code from libssh2_dh_key_pair() + + Fixes a segfault using ssh-agent on Windows + + This commit fixes a segfault seen dereferencing a null pointer on + Windows when using ssh-agent. The problem ended up being that errors + weren't being communicated all the way through, causing null pointers to + be used when functions should have bailed out sooner. + + The `_libssh2_dh_key_pair` function for WinCNG was modified to propagate + errors, and then the two callsites in kex.c of + `diffie_hellman_sha{1,256}` were updated to recognize this error and + bail out. + + Fixes #162 + Closes #163 + +Alexander Lamaison (27 Nov 2016) +- [monnerat brought this change] + + Implement Diffie-Hellman computations in crypto backends. (#149) + + Not all backends feature the low level API needed to compute a Diffie-Hellman + secret, but some of them directly implement Diffie-Hellman support with opaque + private data. The later approach is now generalized and backends are + responsible for all Diffie Hellman computations. + As a side effect, procedures/macros _libssh2_bn_rand and _libssh2_bn_mod_exp + are no longer needed outside the backends. + +Peter Stuge (16 Nov 2016) +- acinclude.m4: The mbedtls crypto backend actually requires libmbedcrypto + + Examples can't be linked with libmbedtls but need libmbedcrypto, and + any users of libssh2 which use libtool and libssh2.la would encounter + the same problem. + + This changes the mbedtls detection to search for libmbedcrypto, which + is the actual dependency for the backend. + +- acinclude.m4: Add CPPFLAGS=-I$prefix-dir/include in LIBSSH2_LIB_HAVE_LINKFLAGS + + This is absolutely neccessary for header files to be found when + AC_LIB_HAVE_LINKFLAGS searches for libraries. + +- acinclude.m4: Make saved variables in LIBSSH2_LIB_HAVE_LINKFLAGS uniform + +- docs/HACKING.CRYPTO: Improve documentation for autoconf build system + +Alexander Lamaison (16 Nov 2016) +- [Alex Arslan brought this change] + + Check for netinet/in.h in the tests cmake file (#148) + +- [Patrick Monnerat brought this change] + + Define new Diffie-Hellman context for mbedTLS + +- [monnerat brought this change] + + Make libssh2 work again on os400. (#118) + + * os400: minimum supported OS version is now V6R1. + Do not log compiler informational messages. + + * Implement crypto backend specific Diffie-Hellman computation. + + This feature is now needed on os400 because the QC3 library does not + implement bn_mod_exp() natively. Up to now, this function was emulated using + an RSA encryption, but commits ca5222ea819cc5ed797860070b4c6c1aeeb28420 and + 7934c9ce2a029c43e3642a492d3b9e494d1542be (CVE-2016-0787) broke the emulation + because QC3 only supports RSA exponents up to 512 bits. + + Happily, QC3 supports a native API for Diffie-Hellman computation, with + opaque random value: this commit implements the use of this API and, as a + side effect, enables support of this feature for any other crypto backend that + would use it. + + A "generic" Diffie-Hellman computation internal API supports crypto backends + not implementing their own: this generic API uses the same functions as before. + + * Fix typos in docs/HACKING.CRYPTO. + +- [Peter Stuge brought this change] + + acinclude.m4: Fixup OpenSSL EVP_aes_128_ctr() detection + +- [Peter Stuge brought this change] + + configure.ac: Add --with-crypto= instead of many different --with-$backend + + The new --with-crypto option replaces the previous backend-specific + --with-{openssl,libgcrypt,mbedtls,wincng} options and fixes some issues. + + * libgcrypt or mbedtls would previously be used whenever found, even + if configure was passed --without-libgcrypt or --without-mbedtls. + + * If --with-$backend was specified then configure would not fail even + if that library could not be found, and would instead use whichever + crypto library was found first. + + The new option defaults to `auto`, which makes configure check for all + supported crypto libraries in turn, choosing the first one found, or + exiting with an error if none can be found. + +- [Tony Kelman brought this change] + + Build mbedtls from source on Travis (#133) + + * Revert "Revert "travis: Test mbedtls too"" + + This reverts commit c4c60eac5ca756333034b07dd9e0b97741493ed3. + + * travis: Build mbedtls from source on Travis + + Use TOOLCHAIN_OPTION when calling cmake on mbedtls + + * tests: only run DSA tests for non-mbedtls + + crypto backends + +- [Peter Stuge brought this change] + + configure.ac src/Makefile.am: Remove dead AM_CONDITIONAL(OS400QC3) + + According to os400/README400 this backend can not be built + with configure+make, and the conditional is hard coded to false. + +- [Peter Stuge brought this change] + + configure.ac: Add -DNDEBUG to CPPFLAGS in non-debug builds + + There are a few uses of assert() in channel.c, sftp.c and transport.c. + +- [Peter Stuge brought this change] + + src/global.c: Fix conditional AES-CTR support + + Most of libssh2 already has conditional support for AES-CTR according to + the LIBSSH2_AES_CTR crypto backend #define, but global.c needed fixing. + +- [Peter Stuge brought this change] + + src/crypto.h src/userauth.c: Fix conditional RSA support + + Most of libssh2 already has conditional support for RSA according to + the LIBSSH2_RSA crypto backend #define, but crypto.h and userauth.c + needed a few small fixes. + +- [Peter Stuge brought this change] + + src/kex.c: Cast libssh2_sha{1,256}_update data arguments properly + + The update functions take a const unsigned char * but were called + with (const) char * in some places, causing unneccessary warnings. + +- [Peter Stuge brought this change] + + docs/HACKING.CRYPTO: Fix two type typos + +- [Sergei Trofimovich brought this change] + + acinclude.m4: fix ./configure --with-libgcrypt + + The change fixes passing of bogus gcrypt prefix. + Reproducible as: + + $ ./configure --with-libgcrypt + $ make V=1 + ... + /bin/sh ../libtool --tag=CC --mode=link gcc -g -O2 -Iyes/include -version-info 1:1:0 -no-undefined -export-symbols-regex '^libssh2_.*' -lgcrypt -lz -Lyes/lib -o libssh2.la -rpath /usr/local/lib 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 libgcrypt.lo pem.lo keepalive.lo global.lo -lgcrypt + ../libtool: line 7475: cd: yes/lib: No such file or directory + libtool: error: cannot determine absolute directory name of 'yes/lib' + + These + -Iyes/include + -Lyes/lib + come from libgcrypt code autodetection: + if test -n "$use_libgcrypt" && test "$use_libgcrypt" != "no"; then + LDFLAGS="$LDFLAGS -L$use_libgcrypt/lib" + CFLAGS="$CFLAGS -I$use_libgcrypt/include" + + I assume it's a typo to use yes/no flag as a prefix and changed + it to '$with_libgcrypt_prefix'. + + Reported-by: Mikhail Pukhlikov + Signed-off-by: Sergei Trofimovich + +- [Zenju brought this change] + + libssh2_sftp_init hang: last error not set + + The problem is that the original if statement simply returns NULL, but does not set the session last error code. The consequence is that libssh2_sftp_init() also returns NULL and libssh2_session_last_errno(sshSession) == LIBSSH2_ERROR_NONE. + + In my test the LIBSSH2_ERROR_EAGAIN is coming from sftp.c row 337: + if(4 != sftp->partial_size_len) + /* we got a short read for the length part */ + return LIBSSH2_ERROR_EAGAIN; + + with "partial_size_len == 0". Not sure if this is expected. + +- [Aidan Hobson Sayers brought this change] + + docs: correctly describe channel_wait_eof + + channel_wait_eof waits for channel->remote.eof, which is set on + receiving a `SSH_MSG_CHANNEL_EOF` message. This message is sent + when a party has no more data to send on a channel. + +- [Zenju brought this change] + + Fix MSVC 14 compilation warning (#92) + + 1> sftp.c + 1>libssh2-files\src\sftp.c(3393): warning C4456: declaration of 'retcode' hides previous local declaration + 1> libssh2-files\src\sftp.c(3315): note: see declaration of 'retcode' + +- [Salvador Fandino brought this change] + + LIBSSH2_ERROR_CHANNEL_WINDOW_FULL: add new error code + + In order to signal that the requested operation can not succeed + because the receiving window had been exhausted, the error code + LIBSSH2_ERROR_BUFFER_TOO_SMALL has been reused but I have found + that in certain context it may be ambigous. + + This patch introduces a new error code, + LIBSSH2_ERROR_CHANNEL_WINDOW_FULL, exclusive to signal that condition. + +- [Salvador Fandino brought this change] + + channel_wait_eof: handle receive window exhaustion + + Until now, in blocking mode, if the remote receiving window is + exhausted this function hangs forever as data is not read and the + remote side just keeps waiting for the window to grow before sending + more data. + + This patch, makes this function check for that condition and abort + with an error when it happens. + +- [Salvador Fandino brought this change] + + channel_wait_closed: don't fail when unread data is queued + + This function was calling channel_wait_eof to ensure that the EOF + packet has already been received, but that function also checks that + the read data queue is empty before reporting the EOF. That caused + channel_wait_closed to fail with a LIBSSH2_ERROR_INVAL when some data + was queued even after a successful call to libssh2_channel_wait_eof. + + This patch changes libssh2_channel_wait_closed to look directly into + channel->remote.eof so that both libssh2_channel_wait_eof and + libssh2_channel_wait_closed bahave consistently. + +- [Salvador Fandino brought this change] + + channel_wait_eof: fix debug message + +Daniel Stenberg (25 Oct 2016) +- libssh2.h: start working on 1.8.1 Version 1.8.0 (25 Oct 2016) @@ -4731,802 +5939,3 @@ Daniel Stenberg (24 Apr 2010) - libssh2_knownhost_check: Value stored to 'keylen' is never read - hostkey: fix compiler warning - -- remove unused variable - -- data types: convert more to use size_t and uint32_t - -- channel: variable type cleanups - -- cleanups: better binary packet gen, size_t fixes and PACKET_* removal - - I'll introduce a new internal function set named - - _libssh2_store_u32 - _libssh2_store_u64 - _libssh2_store_str - - That can be used all through the library to build binary outgoing - packets. Using these instead of the current approach removes - hundreds of lines from the library while at the same time greatly - enhances readability. I've not yet fully converted everything to - use these functions. - - I've converted LOTS of 'unsigned long' to 'size_t' where - data/string lengths are dealt with internally. This is The Right - Thing and it will help us make the transition to our - size_t-polished API later on as well. - - I'm removing the PACKET_* error codes. They were originally - introduced as a set of separate error codes from the transport - layer, but having its own set of errors turned out to be very - awkward and they were then converted into a set of #defines that - simply maps them to the global libssh2 error codes instead. Now, - I'l take the next logical step and simply replace the PACKET_* - defines with the actual LIBSSH2_ERROR_* defines. It will increase - readability and decrease confusion. - - I also separated packet stuff into its own packet.h header file. - -- clarified the return code - -- rename libssh2_error to the correct _libssh2_error - - We reserve ^libssh2_ for public symbols and we use _libssh2 as - prefix for internal ones. I fixed the intendation of all these - edits with emacs afterwards, which then changed it slightly more - than just _libssh2_error() expressions but I didn't see any - obvious problems. - -- data type cleanup: made lots of code use size_t etc - - A lot of code used 'unsigned long' and the likes when it should - rather just use plain 'int' or use size_t for data lengths. - -- wait_socket: make c89 compliant and use two fd_sets for select() - -- sftp_readdir: always zero terminate, detail the return code - - I also added a description for the 'longentry' field which was - previously undocumented! - -- sftp_readdir: simplified and bugfixed - - This function no longer has any special purpose code for the - single entry case, as it was pointless. - - The previous code would overflow the buffers with an off-by-one - in case the file name or longentry data fields received from the - server were exactly as long as the buffer provided to - libssh2_sftp_readdir_ex. - - We now make sure that libssh2_sftp_readdir_ex() ALWAYS zero - terminate the buffers it fills in. - - The function no longer calls the libssh2_* function again, but - properly uses the internal sftp_* instead. - -- channel/transport: we now drain the outgoing send buffer when we ignore EAGAIN - - When we ignore the EAGAIN from the transport layer within channel_write, we - now drain the outgoing transport layer buffer so that remainders in that - won't cause any problems in the next invoke of _libssh2_transport_write() - -- channel_write: if data has been sent, don't return EAGAIN - - When sending data in a loop, we must not return EAGAIN if we - managed to send data in an earlier round. This was reported in - bug #126 => http://libssh2.stuge.se/ticket/126 - -Simon Josefsson (14 Apr 2010) -- Fix OpenSSL AES-128-CTR detection. - - Patch from Paul Howarth . - -Daniel Stenberg (13 Apr 2010) -- version in header file now says 1.2.6-DEV - -- 1.2.6: clean the RELEASE-NOTES for next release round - -- NEWS: add the stuff from the version 1.2.5 RELEASE-NOTES - -Version 1.2.5 (13 Apr 2010) - -Daniel Stenberg (13 Apr 2010) -- channel_close: no longer wait for the SSH_MSG_CHANNEL_CLOSE message - - As the packet may simply not arrive we cannot have the close - function wait for it unconditionally. - -- less code duplication in the poll vs select code flows - - libssh2_keepalive_send and libssh2_session_block_directions are - now used outside of the #ifdef blocks. - -- make it C90 compliant - -- updated with all changes and bugs since 1.2.4 - -- Added LIBSSH2_SFTP_S_IS***() macros and updated docs - - libssh2_sftp_fstat_ex.3 is now extended quite a lot to describe a - lot of the struct and the bits it uses and how to test for them. - -- sftp_init() deal with _libssh2_channel_write() returns short - - When _libssh2_channel_write() is asked to send off 9 bytes, the - code needs to deal with the situation where less than 9 bytes - were sent off and prepare to send the remaining piece at a later - time. - -- handle a NULL password as if it was "" - - libssh2_userauth_publickey_fromfile_ex() takes a "passphrase" - but didn't deal with it being set to NULL. - -- Reduce used window sizes by factor 10 - - As reported in bug report #166 http://libssh2.stuge.se/ticket/166 - by 'ptjm', the maximum window size must be less crazy for libssh2 - to do better with more server implementations. I did not do any - testing to see how this changes raw SCP performance, but the - maximum window size is still almost 4MB. This also has the upside - that libssh2 will use less memory. - -Peter Stuge (28 Mar 2010) -- Correctly clear blocking flag after sending multipart packet - - commit 7317edab61d2179febc38a2c2c4da0b951d74cbc cleared the outbound - blocking bit when send_existing() returned PACKET_NONE and *ret=0, as - opposed to before even calling send_existing(), but because *ret=1 when - sending parts 2..n of an existing packet, the bit would only be cleared - when calling libssh2_transport_write() for a new packet. - - Clear the direction flag after the final part of a packet has been sent. - -Daniel Stenberg (24 Mar 2010) -- Added man page for libssh2_knownhost_addc() - - Added mention in libssh2_knownhost_add() docs that - libssh2_knownhost_addc() is the preferred function now. - -- at next soname bump remove libssh2_knownhost_add() - -- ignore TAGS ("make tags" makes them) - -- fix memory leak - - we must not assign the pointer a NULL since it keeps allocated - data and at least parts of an error string - -- fixed the pattern for avoiding the poll check - - added some comments about known problems with poll on darwin - -- avoid checking for poll on some systems - - darwin and interix are known to have broken poll implementations - so we skip the check on those and thus have them use select - unconditionally - -- ignore libssh2.dsp - -Simon Josefsson (23 Mar 2010) -- Fix logic in "on-the-fly" crypto init. - -- Make sure keepalive is working even when poll is used. - -- [Paul Querna brought this change] - - Use poll when available on blocking API. - - Signed-off-by: Simon Josefsson - -Peter Stuge (20 Mar 2010) -- Fix speling - -Daniel Stenberg (19 Mar 2010) -- fix NULL dereference when window adjusting a non-existing channel - - Suyog Jadhav pointed out that when receiving a window adjust to - a channel not found, the code would reference a NULL pointer. - Now it will instead output a message about that fact. - -Simon Josefsson (19 Mar 2010) -- Fix build problem. - -- Eat our own dog food, call libssh2_init and libssh2_exit in the examples. - -- Fix init/exit logic. Add self-test of it. - -Daniel Stenberg (19 Mar 2010) -- fix typo - -Simon Josefsson (19 Mar 2010) -- Add man page for libssh2_init and libssh2_exit. Fix libssh2_exit prototype. - -- Shorten constant a bit. More documentation. - -- Fix namespace pollution. - -- Add global init/exit points, to do crypto initialization in one place. - - By Lars Nordin. - -Daniel Stenberg (14 Mar 2010) -- libssh2 is released under the Modifed BSD license, not GPL - -Alexander Lamaison (14 Mar 2010) -- Add libssh2_knownhost_addc to handle comments. - - Comments in known_hosts file were not handle properly. They were parsed as - part of the key causing key matching to return a mismatch if the entry had a - comment. This adds a new API function that takes an optional comment and - changes libssh2_knownhost_readline to parse the comment as pass it to the - new function. - - Fixes #164. - -- Fix gettimeofday to compile with Visual C++ 6. - - Reported by Steven Van Ingelgem. - -Simon Josefsson (10 Mar 2010) -- Add. - -- keepalive.c: Fix libssh2_error usage. - -- Fix typo in last commit. - -- Tidy up build option notice. - -- Add entry about keep alive stuff. - -- Add keep-alive support. - -Alexander Lamaison (7 Mar 2010) -- Untabify. - -- Fix memory leak in libssh2_knownhost_add. - -Daniel Stenberg (6 Mar 2010) -- change 'int' to 'libssh2_socket_t' in the public API for sockets - -- reduce code duplication and return underlying error better - -- acknowledge when _libssh2_packet_requirev() returns error - - when _libssh2_packet_requirev() returns an error when waiting for - SSH_MSG_USERAUTH_SUCCESS or SSH_MSG_USERAUTH_FAILURE, it is an - error and it should be treated as such - -- wrap long lines - -- polished the phrasing in two error strings - -- silence picky compiler warnings - -- silence picky compiler warnings - -- removed libssh2_error()'s forth argument - - libssh2_error() no longer allocates a string and only accepts a const - error string. I also made a lot of functions use the construct of - return libssh2_error(...) instead of having one call to - libssh2_error() and then a separate return call. In several of those - cases I then also changed the former -1 return code to a more - detailed one - something that I think will not change behaviors - anywhere but it's worth keeping an eye open for any such. - -- repaired --enable-debug - -Simon Josefsson (1 Mar 2010) -- Make ./configure output a summary of build options. - -Daniel Stenberg (1 Mar 2010) -- let the err_msg in the session struct be const too - -Simon Josefsson (1 Mar 2010) -- Revert #ifdef change that pulled in AES-CTR code when explicitly disabled. - -Daniel Stenberg (1 Mar 2010) -- fix #ifdefs - -- make function match the new proto - -Simon Josefsson (1 Mar 2010) -- Improve AES-CTR check. - -Daniel Stenberg (1 Mar 2010) -- use const to silence a bazillion warnings - -Simon Josefsson (1 Mar 2010) -- Use AES-CTR from OpenSSL when available. - - Reported by Lars Nordin . - -- Make it possible to disable DSA. - - Patch from Lars Nordin . - -Peter Stuge (1 Mar 2010) -- Send and receive channel EOF before sending SSH_MSG_CHANNEL_CLOSE - - Sending SSH_MSG_CHANNEL_CLOSE without channel EOF is explicitly allowed - in RFC 4254, but some non-conforming servers will hang or time out when - the channel is closed before EOF. - - Other common clients send and receive EOF before closing, there are no - drawbacks, and some servers need it to work correctly. - -Alexander Lamaison (26 Feb 2010) -- Style improvements to knownhost error handling. - - Made improvements as suggested by Peter Stuge: http://www.libssh2.org/mail/libssh2-devel-archive-2010-02/0161.shtml. - -- Call libssh2_error for every knownhost API failure. - - The libssh2 API calls should set the last error code and a message when - returning a failure by calling libssh2_error. This changeset adds these - calls to the libssh2_knownhost_* API as well as libssh2_base64_decode. - - This change also makes libssh2_error into a function rather than a macro. - Its implementation is moved to misc.c. This function returns the error - code passed to it allowing callers to return the error value directly - without duplicating the error code. - -- Fix LIBSSH2_ALLOC checks. - - These appear to be cut-and paste errors where the wrong variable is checked - for NULLness after calling LIBSSH2_ALLOC. - -Simon Josefsson (23 Feb 2010) -- Silence compiler warning. - -- Make it portable; test uses = for string comparison (not ==). Indent. - -Alexander Lamaison (22 Feb 2010) -- libssh2_knownhost_del: fix write to freed memory. - - When removing a known host, libssh2_knownhost_del would remove the node from the linked list, free its memory and then overwrite the struct parameter (which indicated which node to remove) with 0. However, this struct is actually allocated within the just-freed node meaning we're writing to freed memory. This made Windows very upset. - - The fix is simply to overwrite the struct first before freeing the memory. - -Daniel Stenberg (21 Feb 2010) -- show more verbose error when SCP send fails - -- libssh2_socket_t is done, a library-free function is needed - -- clarify that this frees all data associated with a session - -- improved error handling - -- add missing libssh2_error() calls - - To make sure the public API is functional and that the - BLOCK_ADJUST_ERRNO() macro works correctly we MUST make sure to - call libssh2_error() when we return errors. - -- fix memory leak in userauth_keyboard_interactive() - - Mr anonymous in bug #125 pointed out that the userauth_keyboard_interactive() - function does in fact assign the same pointer a second time to a new allocated - buffer without properly freeing the previous one, which caused a memory leak. - -- added missing error codes - - To allow the libssh2_session_last_error() function to work as - documented, userauth_password() now better makes sure to call - libssh2_error() everywhere before it returns error. - - Pointed out by mr anonymous in bug #128 - -Peter Stuge (16 Feb 2010) -- Fix resource and memory leaks in examples as reported by cppcheck - - Thanks to Ettl Martin for the report and patch. This fixes #132 - -Daniel Stenberg (15 Feb 2010) -- mention the new man pages for macros - -- added man pages for API macros - - all #defined macros in the public headers are considered to be part - of the API and I've generated individual man pages for each of them - to A) make it easier to figure out what each function/macro actually - is for so that automated lookups work better and for B) make sure we - have all public functions document (both macros and functions) to - make it easier for us to work away from all the macros in a future - release. - -- Committed the patch by Yoichi Iwaki in bug #2929647 - - Committed the patch by Yoichi Iwaki in bug #2929647, which fixed a memory - leak when an 'outbuf' was still allocated when a session was freed. - -- free "outbuf" when killing a session - - Fix memoary leak: if there was an "output" still allocated when a - session was torn down it needs to be freed in session_free() - - Patch by Yoichi Iwaki in bug #2929647 - -- the working version name is now 1.2.5_DEV - -Version 1.2.4 (13 Feb 2010) - -Daniel Stenberg (13 Feb 2010) -- updated info for 1.2.4 - -Dan Fandrich (10 Feb 2010) -- Allow compiling with OpenSSL when AES isn't available. - -Peter Stuge (9 Feb 2010) -- [Dave McCaldon brought this change] - - Fix Tru64 socklen_t compile issue with example/direct_tcpip.c - - Building libssh2-1.2.3 on Tru64 fails at line 48 and 166 because socklen_t - isn't defined on Tru64 unless _POSIX_PII_SOCKET is defined. - - This patch updates configure.ac to add -D_POSIX_PII_SOCKET when building - on Tru64 platform(s). - -- [Dave McCaldon brought this change] - - Resolve compile issues on Solaris x64 and UltraSPARC - - Solaris builds of libssh2-1.2.3 failed on both x64 and UltraSPARC - platforms because of two problems: - - 1) src/agent.c:145 sun is a reserved word when using the SUNWspro compiler - 2) example/direct_tcpip.c:84 INADDR_NONE is not defined - -Daniel Stenberg (3 Feb 2010) -- towards 1.2.4 now - -Version 1.2.3 (3 Feb 2010) - -Daniel Stenberg (3 Feb 2010) -- Version 1.2.3 (February 3, 2010) - -- fix building out of source tree by proving better include path - - when building out of source tree, we provide -I$(top_builddir)/example - since the libssh2_config.h gets generated in that dir - -Peter Stuge (1 Feb 2010) -- [Sofian Brabez brought this change] - - Replace : in hexdump with " " (two spaces) - -- Detect when the forwarded connection is closed in example/direct_tcpip.c - -- Fix example/direct_tcpip.c to work also on WIN32 - - read() and write() are no good for WIN32 sockets, use recv() and send(). - -- Ignore libssh2_config.h.in and stamp-h2 in example/ and remove .cvsignore - -- Simplify WIN32 ifdefs in example/direct_tcpip.c to allow standalone compile - -- Always #define INVALID_SOCKET -1 in libssh2_priv.h when not on win32 - - Fix broken builds since commit abd9bd0bbe631efeada1f54552c70b54e1c490c1 - for all non-win32 platforms. - -- Include hmac-md5 and hmac-md5-96 only if crypto backend supports MD5 - -- Use LIBSSH2_HOSTKEY_HASH_SHA1 instead of _MD5 in examples and tests - - MD5 support is optional and may not always be available, while SHA1 is both - required and recommended. - -- Update mailing list address in configure.ac to @cool.haxx.se - -- Make example/direct_tcpip.c compile for win32 - - One warning from FD_SET() remains, it is also in some other examples. - -- Correctly check for an invalid socket in session_startup() - -- Small documentation fix after Dave's _USERAUTH_FAILURE improvement - -- [Dave McCaldon brought this change] - - Handle SSH_MSG_USERAUTH_FAILURE for password and kbd-int authentication - - Neither libssh2_userauth_password_ex() nor - libssh2_userauth_keyboard_interactive_ex() would return a login failure - error if the server responded with a SSH_MSG_USERAUTH_FAILURE, instead - you would see whatever previous error had occurred, typically - LIBSSH2_ERROR_EAGAIN. - - This patch changes error code -18 to LIBSSH2_ERROR_AUTHENTICATION_FAILED - and makes LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED an alias for - LIBSSH2_ERROR_AUTHENTICATION_FAILED. In addition, new logic in - userauth_password() properly handles SSH_MSG_USERAUTH_FAILURE and both - this function and userauth_keyboard_interactive() now properly return - LIBSSH2_ERROR_AUTHENTICATION_FAILED. - -Simon Josefsson (28 Jan 2010) -- Fix. - -- Also deal with GLOBAL_REQUEST keep-alives. - -- Make OpenSSH-style keepalive work against libssh2 clients. - -Daniel Stenberg (27 Jan 2010) -- clarified - -Peter Stuge (26 Jan 2010) -- [Dave McCaldon brought this change] - - Fix trace context lookup in libssh2_debug() - - The trace context is actually a bitmask so that tracing output can be - controlled by setting a bitmask using libssh2_trace(). However, the logic - in libssh2_debug() that converted the context to a string was using the - context value as an array index. Because the code used a bounds check on - the array, there was never a danger of a crash, but you would certainly - either get the wrong string, or "unknown". - - This patch adds a lookup that iterates over the context strings and uses - it's index to check for the corresponding bit in the context. - -- Fix typo in RELEASE-NOTES - -Daniel Stenberg (20 Jan 2010) -- updated for 1.2.3 with all the stuff I found in the log - -- ignore more generated files - -- [Dave McCaldon brought this change] - - Pass user context through libssh2_trace_sethandler() to callback - - The libssh2_trace_sethandler() call allows the user to handle the output of libssh2 rather than having it written to stderr. This patch updates libssh2_trace_sethandler() to allow a user-defined void* context value to be passed back to the output handler. - -- [Dave McCaldon brought this change] - - Add libssh2_trace_sethandler() to the API (even more) - -- [Dave McCaldon brought this change] - - Add libssh2_trace_sethandler() to the API - -- cleanup includes - - We now produce a local libssh2_config.h file in this dir for the - examples to use so I cleaned up the include path at the same time. - -- generate a libssh2_config.h in the example dir - - buildconf copies the template to example/ and configure makes sure - to generate a proper file from it and the direct_tcpip.c example - is the first one to use it - to make sure it builds fine on more - paltforms - -Simon Josefsson (13 Jan 2010) -- Remove redundant #includes and reorder sys/types.h include. - -Daniel Stenberg (10 Jan 2010) -- avoid a free(NULL) - -Simon Josefsson (7 Jan 2010) -- Make it simpler to get more debug info. - -Daiki Ueno (1 Jan 2010) -- Simplify the commit 63457dfa using type cast from size_t * to ulong *. - -Alexander Lamaison (30 Dec 2009) -- Fixed memory leak in userauth_publickey(). - - userauth_publickey_fromfile() reads the key from a - file using file_read_publickey() which returns two - allocated strings, the decoded key and the key - method (such as "ssh-dss"). The latter can be - derived from the former but returning both avoids a - later allocation while doing so. - - Older versions of userauth_publickey_fromfile() used - this method string directly but when - userauth_publickey() was factored out of - userauth_publickey_fromfile() it derived the method - from the key itself. This resulted in the method - being allocated twice. - - This fix, which maintains the optimisation that - avoids an extra allocation, changes - userauth_publickey() so it doesn't allocate and - derive the method when userauth_pblc_method already - has a value. - - Signed-off-by: Alexander Lamaison - -Daiki Ueno (25 Dec 2009) -- Fix the return value description of libssh2_knownhost_free(). - -- Fix compiler warnings for size_t pointers on 32-bit Windows. - -- Define INVALID_SOCKET and use it instead of SOCKET_BAD. - - Revert the part of previous commit that defines SOCKET_BAD library wide. - -- Use libssh2_socket_t in the ssh-agent stuff. - Define a portability macro SOCKET_BAD which means "invalid socket". - -- Mark/unmark connection to Pageant is open/close. - -- Add test to check if the socket is connected. - -Peter Stuge (24 Dec 2009) -- Add libssh2.pc to top-level .gitignore - -- Fix publickey authentication regression - - Commit 70b199f47659a74b8778c528beccf893843e5ecb introduced a parsing - bug in file_read_publickey() which made the algorithm name contain an - extra trailing space character, breaking all publickey authentication. - -- Add a direct-tcpip example which shows local port forwarding - -- Add session parameter and LIBSSH2_TRACE_SOCKET to libssh2_trace(3) man page - -- Add TODO: Expose error messages sent by the server - -Daiki Ueno (23 Dec 2009) -- Fix doc comments. - -- Add man pages for ssh-agent API. - -- Don't request userauthlist after authentication. - -Simon Josefsson (21 Dec 2009) -- Add. - -- [Daiki Ueno brought this change] - - Add an example to use ssh-agent API. - - Signed-off-by: Simon Josefsson - -- [Daiki Ueno brought this change] - - Add ssh-agent API. - - Signed-off-by: Simon Josefsson - -- [Daiki Ueno brought this change] - - Add callback-based API for publickey auth. - - Signed-off-by: Simon Josefsson - -- Move examples from example/simple to example/. - -- Move examples from example/simple to example/. - -Daniel Stenberg (17 Dec 2009) -- _libssh2_list_insert() fixed to work - - While this is code not currently in use, it is part of the generic linked - list code and since I found the error I thought I'd better fix it since we - might bring in this function into the code one day. - -Simon Josefsson (16 Dec 2009) -- Silence compiler warnings. - - Based on patch by Kamil Dudka in - . - -- [Kamil Dudka brought this change] - - libgcrypt: simplify code of _libssh2_dsa_sha1_sign - - Signed-off-by: Simon Josefsson - -- [Kamil Dudka brought this change] - - libgcrypt: follow-up for ssh-dss padding fix - - Signed-off-by: Simon Josefsson - -Dan Fandrich (15 Dec 2009) -- Check for the right environment variable in the test app - -Simon Josefsson (14 Dec 2009) -- Silence warning about unused function parameter. - - Reported by Steven Van Ingelgem . - -Daniel Stenberg (10 Dec 2009) -- avoid returning data to memory already freed - - In case of failure we must make sure that the data we return - doesn't point to a memory area already freed. Reported anonymously - in the bug report #2910103. - -Peter Stuge (8 Dec 2009) -- Use LIBSSH2_TRACE_* internally and remove redundant LIBSSH2_DBG_* - -- Add LIBSSH2_TRACE_SOCKET context for tracing send() and recv() - - Helpful in debugging the -39 errors. - -- Another transport layer fix for bogus -39 (LIBSSH2_ERROR_BAD_USE) errors - - Commit 683aa0f6b52fb1014873c961709102b5006372fc made send_existing() send - more than just the second part of a packet when the kernel did not accept - the full packet, but the function still overlooked the SSH protocol - overhead in each packet, often 48 bytes. - - If only the last few bytes of a packet remained, then the packet would - erroneously be considered completely sent, and the next call to write - more data in the session would return a -39 error. - -Daniel Stenberg (6 Dec 2009) -- move local variable to be more localized - -- fixed some indent mistakes - -Peter Stuge (6 Dec 2009) -- Fix padding in ssh-dss signature blob encoding - - DSA signatures consist of two 160-bit integers called r and s. In ssh-dss - signature blobs r and s are stored directly after each other in binary - representation, making up a 320-bit (40 byte) string. (See RFC4253 p14.) - - The crypto wrappers in libssh2 would either pack r and s incorrectly, or - fail, when at least one integer was small enough to be stored in 19 bytes - or less. - - The patch ensures that r and s are always stored as two 160 bit numbers. - -- Don't always clear write direction blocking flag - - When libssh2_transport_write() is called to continue sending a - partially sent packet the write direction flag must not be cleared - until the previous packet has been completely sent, or the app would - hang if the packet still isn't sent completely, since select() gets - called by the internal blocking emulation layer in libssh2 but would - then not be watching the socket for writability. - - Clear the flag only once processing of previous packet data is - complete and a new packet is about to be prepared. - -Alexander Lamaison (24 Nov 2009) -- Detabify. - -- [Daniel Stenberg brought this change] - - Fixed memory leak in sftp_fstat(). - -Simon Josefsson (17 Nov 2009) -- Mark date of 1.2.2 release. - -- Merge branch 'master' of ssh://git.stuge.se/var/lib/git/libssh2 - -Version 1.2.2 (16 Nov 2009) - -Daniel Stenberg (16 Nov 2009) -- prepared for 1.2.2 - -Simon Josefsson (16 Nov 2009) -- Improve NEWS items. - -- Support AES-Counter ciphers. - -- Silence compiler warning. - - Reported by Steven Van Ingelgem - in . - -- Mention libssh2-style.el. - -- Use memmove instead of memcpy on overlapping memory areas. - - Reported by Bob Alexander in - . - -- Add. diff --git a/libssh2/RELEASE-NOTES b/libssh2/RELEASE-NOTES index d566bafe0..98cb8033b 100644 --- a/libssh2/RELEASE-NOTES +++ b/libssh2/RELEASE-NOTES @@ -1,12 +1,44 @@ -libssh2 1.8.2 - -This release includes the following bugfixes: - - o Fixed the misapplied userauth patch that broke 1.8.1 - o moved the MAX size declarations from the public header +libssh2 1.9.0 +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 improved unit tests + This release would not have looked like this without help, code, reports and advice from friends like these: - Will Cosgrove - (1 contributors) + 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 + + (29 contributors) diff --git a/libssh2/acinclude.m4 b/libssh2/acinclude.m4 index 734ef070c..a0044fc47 100644 --- a/libssh2/acinclude.m4 +++ b/libssh2/acinclude.m4 @@ -382,86 +382,130 @@ AC_DEFUN([CURL_CONFIGURE_REENTRANT], [ # ]) -AC_DEFUN([LIBSSH2_CHECKFOR_MBEDTLS], [ +dnl LIBSSH2_LIB_HAVE_LINKFLAGS +dnl -------------------------- +dnl Wrapper around AC_LIB_HAVE_LINKFLAGS to also check $prefix/lib, if set. +dnl +dnl autoconf only checks $prefix/lib64 if gcc -print-search-dirs output +dnl includes a directory named lib64. So, to find libraries in $prefix/lib +dnl we append -L$prefix/lib to LDFLAGS before checking. +dnl +dnl For conveniece, $4 is expanded if [lib]$1 is found. - old_LDFLAGS=$LDFLAGS - old_CFLAGS=$CFLAGS - if test -n "$use_mbedtls" && test "$use_mbedtls" != "no"; then - LDFLAGS="$LDFLAGS -L$use_mbedtls/lib" - CFLAGS="$CFLAGS -I$use_mbedtls/include" +AC_DEFUN([LIBSSH2_LIB_HAVE_LINKFLAGS], [ + libssh2_save_CPPFLAGS="$CPPFLAGS" + libssh2_save_LDFLAGS="$LDFLAGS" + + if test "${with_lib$1_prefix+set}" = set; then + CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I${with_lib$1_prefix}/include" + LDFLAGS="$LDFLAGS${LDFLAGS:+ }-L${with_lib$1_prefix}/lib" fi - AC_LIB_HAVE_LINKFLAGS([mbedtls], [], [ - #include - ]) + AC_LIB_HAVE_LINKFLAGS([$1], [$2], [$3]) - if test "$ac_cv_libmbedtls" = "yes"; then - AC_DEFINE(LIBSSH2_MBEDTLS, 1, [Use mbedtls]) - LIBSREQUIRED= # mbedtls doesn't provide a .pc file - LIBS="$LIBS -lmbedtls -lmbedcrypto" - found_crypto=libmbedtls + LDFLAGS="$libssh2_save_LDFLAGS" + + if test "$ac_cv_lib$1" = "yes"; then : + $4 + else + CPPFLAGS="$libssh2_save_CPPFLAGS" + fi +]) + +AC_DEFUN([LIBSSH2_CHECK_CRYPTO], [ +if test "$use_crypto" = "auto" && test "$found_crypto" = "none" || test "$use_crypto" = "$1"; then +m4_case([$1], +[openssl], [ + LIBSSH2_LIB_HAVE_LINKFLAGS([ssl], [crypto], [#include ], [ + AC_DEFINE(LIBSSH2_OPENSSL, 1, [Use $1]) + LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }libssl libcrypto" + + # Not all OpenSSL have AES-CTR functions. + libssh2_save_LIBS="$LIBS" + LIBS="$LIBS $LIBSSL" + AC_CHECK_FUNCS(EVP_aes_128_ctr) + LIBS="$libssh2_save_LIBS" + + found_crypto="$1" + found_crypto_str="OpenSSL (AES-CTR: ${ac_cv_func_EVP_aes_128_ctr:-N/A})" + ]) +], + +[libgcrypt], [ + LIBSSH2_LIB_HAVE_LINKFLAGS([gcrypt], [], [#include ], [ + AC_DEFINE(LIBSSH2_LIBGCRYPT, 1, [Use $1]) + found_crypto="$1" + ]) +], + +[mbedtls], [ + LIBSSH2_LIB_HAVE_LINKFLAGS([mbedcrypto], [], [#include ], [ + AC_DEFINE(LIBSSH2_MBEDTLS, 1, [Use $1]) + found_crypto="$1" support_clear_memory=yes - else - # restore - LDFLAGS=$old_LDFLAGS - CFLAGS=$old_CFLAGS - fi -]) - -AC_DEFUN([LIBSSH2_CHECKFOR_GCRYPT], [ - - old_LDFLAGS=$LDFLAGS - old_CFLAGS=$CFLAGS - if test -n "$use_libgcrypt" && test "$use_libgcrypt" != "no"; then - LDFLAGS="$LDFLAGS -L$use_libgcrypt/lib" - CFLAGS="$CFLAGS -I$use_libgcrypt/include" - fi - AC_LIB_HAVE_LINKFLAGS([gcrypt], [], [ - #include ]) +], - if test "$ac_cv_libgcrypt" = "yes"; then - AC_DEFINE(LIBSSH2_LIBGCRYPT, 1, [Use libgcrypt]) - LIBSREQUIRED= # libgcrypt doesn't provide a .pc file. sad face. - LIBS="$LIBS -lgcrypt" - found_crypto=libgcrypt - else - # restore - LDFLAGS=$old_LDFLAGS - CFLAGS=$old_CFLAGS - fi -]) - - -AC_DEFUN([LIBSSH2_CHECKFOR_WINCNG], [ - +[wincng], [ # Look for Windows Cryptography API: Next Generation - AC_LIB_HAVE_LINKFLAGS([bcrypt], [], [ - #include - #include - ]) - AC_LIB_HAVE_LINKFLAGS([crypt32], [], [ + AC_CHECK_HEADERS([ntdef.h ntstatus.h], [], [], [#include ]) + AC_CHECK_DECLS([SecureZeroMemory], [], [], [#include ]) + + LIBSSH2_LIB_HAVE_LINKFLAGS([crypt32], [], [ #include #include ]) - AC_CHECK_HEADERS([ntdef.h ntstatus.h], [], [], [ - #include - ]) - AC_CHECK_DECLS([SecureZeroMemory], [], [], [ + LIBSSH2_LIB_HAVE_LINKFLAGS([bcrypt], [], [ #include + #include + ], [ + AC_DEFINE(LIBSSH2_WINCNG, 1, [Use $1]) + found_crypto="$1" + found_crypto_str="Windows Cryptography API: Next Generation" + support_clear_memory="$ac_cv_have_decl_SecureZeroMemory" ]) +], +) + test "$found_crypto" = "none" && + crypto_errors="${crypto_errors}No $1 crypto library found! +" +fi +]) - if test "$ac_cv_libbcrypt" = "yes"; then - AC_DEFINE(LIBSSH2_WINCNG, 1, [Use Windows CNG]) - LIBSREQUIRED= # wincng doesn't provide a .pc file. sad face. - LIBS="$LIBS -lbcrypt" - if test "$ac_cv_libcrypt32" = "yes"; then - LIBS="$LIBS -lcrypt32" - fi - found_crypto="Windows Cryptography API: Next Generation" - if test "$ac_cv_have_decl_SecureZeroMemory" = "yes"; then - support_clear_memory=yes - fi + +dnl LIBSSH2_CHECK_OPTION_WERROR +dnl ------------------------------------------------- +dnl Verify if configure has been invoked with option +dnl --enable-werror or --disable-werror, and set +dnl shell variable want_werror as appropriate. + +AC_DEFUN([LIBSSH2_CHECK_OPTION_WERROR], [ + AC_BEFORE([$0],[LIBSSH2_CHECK_COMPILER])dnl + AC_MSG_CHECKING([whether to enable compiler warnings as errors]) + OPT_COMPILER_WERROR="default" + AC_ARG_ENABLE(werror, +AC_HELP_STRING([--enable-werror],[Enable compiler warnings as errors]) +AC_HELP_STRING([--disable-werror],[Disable compiler warnings as errors]), + OPT_COMPILER_WERROR=$enableval) + case "$OPT_COMPILER_WERROR" in + no) + dnl --disable-werror option used + want_werror="no" + ;; + default) + dnl configure option not specified + want_werror="no" + ;; + *) + dnl --enable-werror option used + want_werror="yes" + ;; + esac + AC_MSG_RESULT([$want_werror]) + + if test X"$want_werror" = Xyes; then + CFLAGS="$CFLAGS -Werror" fi ]) + diff --git a/libssh2/config.guess b/libssh2/config.guess index d622a44e5..f50dcdb6d 100755 --- a/libssh2/config.guess +++ b/libssh2/config.guess @@ -1,14 +1,12 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2012-02-10' +timestamp='2018-02-24' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but @@ -17,24 +15,22 @@ timestamp='2012-02-10' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). # -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + me=`echo "$0" | sed -e 's,.*/,,'` @@ -43,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -54,9 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -113,9 +107,9 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; + ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; @@ -138,9 +132,37 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -153,21 +175,31 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -182,40 +214,67 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in os=netbsd ;; esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "$machine-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -232,63 +291,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -300,9 +350,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) + arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) @@ -327,38 +377,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" + eval "$set_cc_for_build" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -367,25 +417,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -396,44 +446,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} + echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} + echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} + echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -442,23 +492,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -484,17 +534,17 @@ EOF AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -511,7 +561,7 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -523,14 +573,14 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -541,7 +591,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -555,26 +605,27 @@ EOF exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -589,28 +640,28 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -643,13 +694,13 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + eval "$set_cc_for_build" # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -660,23 +711,23 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -701,11 +752,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -714,7 +765,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -722,9 +773,9 @@ EOF exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -749,124 +800,109 @@ EOF echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + echo "$UNAME_MACHINE"-pc-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -879,63 +915,64 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el @@ -949,55 +986,74 @@ EOF #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-gnu + echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu + echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1011,34 +1067,34 @@ EOF # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) @@ -1048,12 +1104,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1063,9 +1119,9 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1073,7 +1129,7 @@ EOF # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; @@ -1085,9 +1141,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1107,9 +1163,9 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1118,28 +1174,28 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1150,7 +1206,7 @@ EOF *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1170,23 +1226,23 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1201,66 +1257,97 @@ EOF BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1269,18 +1356,18 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1301,14 +1388,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1317,185 +1404,48 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs exit ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 +echo "$0: unable to guess system type" >&2 -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 </dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi + ;; +esac cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1514,16 +1464,16 @@ hostinfo = `(hostinfo) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/libssh2/config.sub b/libssh2/config.sub index c894da455..1d8e98bce 100755 --- a/libssh2/config.sub +++ b/libssh2/config.sub @@ -1,36 +1,31 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2012-02-10' +timestamp='2018-02-22' -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -38,7 +33,7 @@ timestamp='2012-02-10' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -58,12 +53,11 @@ timestamp='2012-02-10' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -73,9 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -102,7 +94,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -120,24 +112,24 @@ esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -156,7 +148,7 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) + -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; @@ -186,53 +178,56 @@ case $os in ;; -sco6) os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -253,21 +248,25 @@ case $basic_machine in | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ | bfin \ - | c4x | clipper \ + | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ + | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -281,26 +280,30 @@ case $basic_machine in | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ - | nios | nios2 \ + | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ + | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -308,7 +311,8 @@ case $basic_machine in | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ + | visium \ + | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -322,11 +326,14 @@ case $basic_machine in c6x) basic_machine=tic6x-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown @@ -355,7 +362,7 @@ case $basic_machine in ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. @@ -364,26 +371,29 @@ case $basic_machine in | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ + | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ @@ -397,28 +407,34 @@ case $basic_machine in | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ + | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ + | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -426,6 +442,8 @@ case $basic_machine in | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ + | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -439,7 +457,7 @@ case $basic_machine in # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -473,7 +491,7 @@ case $basic_machine in basic_machine=x86_64-pc ;; amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl @@ -502,6 +520,9 @@ case $basic_machine in basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -515,7 +536,7 @@ case $basic_machine in os=-linux ;; blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) @@ -523,13 +544,13 @@ case $basic_machine in os=-cnk ;; c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray @@ -618,10 +639,18 @@ case $basic_machine in basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -711,9 +740,6 @@ case $basic_machine in hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; - hppa-next) - os=-nextstep3 - ;; hppaosf) basic_machine=hppa1.1-hp os=-osf @@ -726,26 +752,26 @@ case $basic_machine in basic_machine=i370-ibm ;; i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -763,17 +789,17 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; - m88k-omron*) - basic_machine=m88k-omron - ;; magnum | m3230) basic_machine=mips-mips os=-sysv @@ -782,11 +808,15 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; - microblaze) + microblaze*) basic_machine=microblaze-xilinx ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; mingw32) - basic_machine=i386-pc + basic_machine=i686-pc os=-mingw32 ;; mingw32ce) @@ -801,10 +831,10 @@ case $basic_machine in os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -814,15 +844,19 @@ case $basic_machine in basic_machine=powerpc-unknown os=-morphos ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) - basic_machine=i386-pc + basic_machine=i686-pc os=-msys ;; mvs) @@ -861,7 +895,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -906,6 +940,12 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -938,7 +978,7 @@ case $basic_machine in os=-linux ;; parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) @@ -954,7 +994,7 @@ case $basic_machine in basic_machine=i386-pc ;; pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc @@ -969,16 +1009,16 @@ case $basic_machine in basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould @@ -988,23 +1028,23 @@ case $basic_machine in ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -1013,7 +1053,11 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; - rdos) + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) basic_machine=i386-pc os=-rdos ;; @@ -1054,17 +1098,10 @@ case $basic_machine in sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; sh5el) basic_machine=sh5le-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -1083,7 +1120,7 @@ case $basic_machine in os=-sysv4 ;; strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun @@ -1205,6 +1242,9 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1213,20 +1253,12 @@ case $basic_machine in basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -1255,10 +1287,6 @@ case $basic_machine in vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; @@ -1268,9 +1296,6 @@ case $basic_machine in sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; cydra) basic_machine=cydra-cydrome ;; @@ -1290,7 +1315,7 @@ case $basic_machine in # Make sure to match an already-canonicalized machine name. ;; *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1298,10 +1323,10 @@ esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1312,8 +1337,8 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1324,45 +1349,48 @@ case $os in -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ + | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1379,12 +1407,12 @@ case $os in -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc @@ -1393,10 +1421,10 @@ case $os in os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition @@ -1407,12 +1435,6 @@ case $os in -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1437,7 +1459,7 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1459,7 +1481,7 @@ case $os in -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1474,35 +1496,38 @@ case $os in -ose*) os=-ose ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; + -ios) + ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1537,6 +1562,12 @@ case $basic_machine in c4x-* | tic4x-*) os=-coff ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; tic54x-*) os=-coff ;; @@ -1586,12 +1617,12 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; @@ -1631,7 +1662,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1646,9 +1677,6 @@ case $basic_machine in i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; *-gould) os=-sysv ;; @@ -1758,15 +1786,15 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$basic_machine$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/libssh2/configure b/libssh2/configure index 8fe15cb88..46d4d0608 100755 --- a/libssh2/configure +++ b/libssh2/configure @@ -639,43 +639,39 @@ LIBOBJS ALLOCA HAVE_SYS_UN_H_FALSE HAVE_SYS_UN_H_TRUE -BUILD_EXAMPLES_FALSE -BUILD_EXAMPLES_TRUE LIBSREQUIRED LIBZ_PREFIX LTLIBZ LIBZ HAVE_LIBZ -OS400QC3_FALSE -OS400QC3_TRUE +WINCNG_FALSE +WINCNG_TRUE MBEDTLS_FALSE MBEDTLS_TRUE LIBGCRYPT_FALSE LIBGCRYPT_TRUE -WINCNG_FALSE -WINCNG_TRUE OPENSSL_FALSE OPENSSL_TRUE -LIBSSL_PREFIX -LTLIBSSL -LIBSSL -HAVE_LIBSSL -LIBMBEDTLS_PREFIX -LTLIBMBEDTLS -LIBMBEDTLS -HAVE_LIBMBEDTLS -LIBCRYPT32_PREFIX -LTLIBCRYPT32 -LIBCRYPT32 -HAVE_LIBCRYPT32 LIBBCRYPT_PREFIX LTLIBBCRYPT LIBBCRYPT HAVE_LIBBCRYPT +LIBCRYPT32_PREFIX +LTLIBCRYPT32 +LIBCRYPT32 +HAVE_LIBCRYPT32 +LIBMBEDCRYPTO_PREFIX +LTLIBMBEDCRYPTO +LIBMBEDCRYPTO +HAVE_LIBMBEDCRYPTO LIBGCRYPT_PREFIX LTLIBGCRYPT LIBGCRYPT HAVE_LIBGCRYPT +LIBSSL_PREFIX +LTLIBSSL +LIBSSL +HAVE_LIBSSL LT_SYS_LIBRARY_PATH OTOOL64 OTOOL @@ -813,17 +809,14 @@ with_gnu_ld with_sysroot enable_libtool_lock enable_largefile -with_openssl -with_libgcrypt +with_crypto enable_rpath -with_libgcrypt_prefix -with_wincng -with_libbcrypt_prefix -with_libcrypt32_prefix -with_mbedtls -with_libmbedtls_prefix -with_libz with_libssl_prefix +with_libgcrypt_prefix +with_libmbedcrypto_prefix +with_libcrypt32_prefix +with_libbcrypt_prefix +with_libz with_libz_prefix enable_crypt_none enable_mac_none @@ -831,7 +824,7 @@ enable_gex_new enable_clear_memory enable_debug enable_hidden_symbols -enable_examples_build +enable_werror ' ac_precious_vars='build_alias host_alias @@ -1498,9 +1491,8 @@ Optional Features: --enable-hidden-symbols Hide internal symbols in library --disable-hidden-symbols Leave all symbols with default visibility in library - --enable-examples-build Build example applications (this is the default) - --disable-examples-build - Do not build example applications + --enable-werror Enable compiler warnings as errors + --disable-werror Disable compiler warnings as errors Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1513,22 +1505,20 @@ Optional Packages: --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). - --with-openssl Use OpenSSL for crypto - --with-libgcrypt Use libgcrypt for crypto + --with-crypto=auto|openssl|libgcrypt|mbedtls|wincng + Select crypto backend (default: auto) --with-gnu-ld assume the C compiler uses GNU ld default=no - --with-libgcrypt-prefix[=DIR] search for libgcrypt in DIR/include and DIR/lib - --without-libgcrypt-prefix don't search for libgcrypt in includedir and libdir - --with-wincng Use Windows CNG for crypto - --with-libbcrypt-prefix[=DIR] search for libbcrypt in DIR/include and DIR/lib - --without-libbcrypt-prefix don't search for libbcrypt in includedir and libdir - --with-libcrypt32-prefix[=DIR] search for libcrypt32 in DIR/include and DIR/lib - --without-libcrypt32-prefix don't search for libcrypt32 in includedir and libdir - --with-mbedtls Use mbedTLS for crypto - --with-libmbedtls-prefix[=DIR] search for libmbedtls in DIR/include and DIR/lib - --without-libmbedtls-prefix don't search for libmbedtls in includedir and libdir - --with-libz Use zlib for compression --with-libssl-prefix[=DIR] search for libssl in DIR/include and DIR/lib --without-libssl-prefix don't search for libssl in includedir and libdir + --with-libgcrypt-prefix[=DIR] search for libgcrypt in DIR/include and DIR/lib + --without-libgcrypt-prefix don't search for libgcrypt in includedir and libdir + --with-libmbedcrypto-prefix[=DIR] search for libmbedcrypto in DIR/include and DIR/lib + --without-libmbedcrypto-prefix don't search for libmbedcrypto in includedir and libdir + --with-libcrypt32-prefix[=DIR] search for libcrypt32 in DIR/include and DIR/lib + --without-libcrypt32-prefix don't search for libcrypt32 in includedir and libdir + --with-libbcrypt-prefix[=DIR] search for libbcrypt in DIR/include and DIR/lib + --without-libbcrypt-prefix don't search for libbcrypt in includedir and libdir + --with-libz Use libz for compression --with-libz-prefix[=DIR] search for libz in DIR/include and DIR/lib --without-libz-prefix don't search for libz in includedir and libdir @@ -14052,18 +14042,31 @@ rm -rf conftest* fi +# Crypto backends + found_crypto=none +found_crypto_str="" +support_clear_memory=no +crypto_errors="" -# Configure parameters -# Check whether --with-openssl was given. -if test "${with_openssl+set}" = set; then : - withval=$with_openssl; use_openssl=$withval + + + + + +# Check whether --with-crypto was given. +if test "${with_crypto+set}" = set; then : + withval=$with_crypto; use_crypto=$withval else - use_openssl=auto + use_crypto=auto + fi +case "${use_crypto}" in + auto|openssl|libgcrypt|mbedtls|wincng) + if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else @@ -14246,16 +14249,15 @@ fi fi -# Check whether --with-libgcrypt was given. -if test "${with_libgcrypt+set}" = set; then : - withval=$with_libgcrypt; use_libgcrypt=$withval +if test "$use_crypto" = "auto" && test "$found_crypto" = "none" || test "$use_crypto" = "openssl"; then - old_LDFLAGS=$LDFLAGS - old_CFLAGS=$CFLAGS - if test -n "$use_libgcrypt" && test "$use_libgcrypt" != "no"; then - LDFLAGS="$LDFLAGS -L$use_libgcrypt/lib" - CFLAGS="$CFLAGS -I$use_libgcrypt/include" + libssh2_save_CPPFLAGS="$CPPFLAGS" + libssh2_save_LDFLAGS="$LDFLAGS" + + if test "${with_libssl_prefix+set}" = set; then + CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I${with_libssl_prefix}/include" + LDFLAGS="$LDFLAGS${LDFLAGS:+ }-L${with_libssl_prefix}/lib" fi @@ -14267,6 +14269,578 @@ if test "${with_libgcrypt+set}" = set; then : + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libssl-prefix was given. +if test "${with_libssl_prefix+set}" = set; then : + withval=$with_libssl_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi + +fi + + LIBSSL= + LTLIBSSL= + INCSSL= + LIBSSL_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='ssl crypto' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBSSL="${LIBSSL}${LIBSSL:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBSSL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBSSL="${LIBSSL}${LIBSSL:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBSSL="${LIBSSL}${LIBSSL:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBSSL="${LIBSSL}${LIBSSL:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBSSL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBSSL="${LIBSSL}${LIBSSL:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBSSL="${LIBSSL}${LIBSSL:+ }$found_so" + else + LIBSSL="${LIBSSL}${LIBSSL:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBSSL="${LIBSSL}${LIBSSL:+ }$found_a" + else + LIBSSL="${LIBSSL}${LIBSSL:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBSSL_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCSSL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCSSL="${INCSSL}${INCSSL:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBSSL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBSSL="${LIBSSL}${LIBSSL:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBSSL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBSSL="${LIBSSL}${LIBSSL:+ }$dep" + LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }$dep" + ;; + esac + done + fi + else + LIBSSL="${LIBSSL}${LIBSSL:+ }-l$name" + LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBSSL="${LIBSSL}${LIBSSL:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBSSL="${LIBSSL}${LIBSSL:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }-R$found_dir" + done + fi + + + ac_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCSSL; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libssl" >&5 +$as_echo_n "checking for libssl... " >&6; } +if ${ac_cv_libssl+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIBSSL" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_libssl=yes +else + ac_cv_libssl=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libssl" >&5 +$as_echo "$ac_cv_libssl" >&6; } + if test "$ac_cv_libssl" = yes; then + HAVE_LIBSSL=yes + +$as_echo "#define HAVE_LIBSSL 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libssl" >&5 +$as_echo_n "checking how to link with libssl... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBSSL" >&5 +$as_echo "$LIBSSL" >&6; } + else + HAVE_LIBSSL=no + CPPFLAGS="$ac_save_CPPFLAGS" + LIBSSL= + LTLIBSSL= + LIBSSL_PREFIX= + fi + + + + + + + + + LDFLAGS="$libssh2_save_LDFLAGS" + + if test "$ac_cv_libssl" = "yes"; then : + + +$as_echo "#define LIBSSH2_OPENSSL 1" >>confdefs.h + + LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }libssl libcrypto" + + # Not all OpenSSL have AES-CTR functions. + libssh2_save_LIBS="$LIBS" + LIBS="$LIBS $LIBSSL" + for ac_func in EVP_aes_128_ctr +do : + ac_fn_c_check_func "$LINENO" "EVP_aes_128_ctr" "ac_cv_func_EVP_aes_128_ctr" +if test "x$ac_cv_func_EVP_aes_128_ctr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EVP_AES_128_CTR 1 +_ACEOF + +fi +done + + LIBS="$libssh2_save_LIBS" + + found_crypto="openssl" + found_crypto_str="OpenSSL (AES-CTR: ${ac_cv_func_EVP_aes_128_ctr:-N/A})" + + else + CPPFLAGS="$libssh2_save_CPPFLAGS" + fi + + + test "$found_crypto" = "none" && + crypto_errors="${crypto_errors}No openssl crypto library found! +" +fi + +if test "$use_crypto" = "auto" && test "$found_crypto" = "none" || test "$use_crypto" = "libgcrypt"; then + + + libssh2_save_CPPFLAGS="$CPPFLAGS" + libssh2_save_LDFLAGS="$LDFLAGS" + + if test "${with_libgcrypt_prefix+set}" = set; then + CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I${with_libgcrypt_prefix}/include" + LDFLAGS="$LDFLAGS${LDFLAGS:+ }-L${with_libgcrypt_prefix}/lib" + fi + + + + + + + + + + + use_additional=yes acl_save_prefix="$prefix" @@ -14734,9 +15308,7 @@ else LIBS="$LIBS $LIBGCRYPT" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - - #include - +#include int main () { @@ -14781,32 +15353,1160 @@ $as_echo "$LIBGCRYPT" >&6; } - if test "$ac_cv_libgcrypt" = "yes"; then + LDFLAGS="$libssh2_save_LDFLAGS" + + if test "$ac_cv_libgcrypt" = "yes"; then : + $as_echo "#define LIBSSH2_LIBGCRYPT 1" >>confdefs.h - LIBSREQUIRED= # libgcrypt doesn't provide a .pc file. sad face. - LIBS="$LIBS -lgcrypt" - found_crypto=libgcrypt + found_crypto="libgcrypt" + else - # restore - LDFLAGS=$old_LDFLAGS - CFLAGS=$old_CFLAGS + CPPFLAGS="$libssh2_save_CPPFLAGS" fi -else - use_libgcrypt=auto + test "$found_crypto" = "none" && + crypto_errors="${crypto_errors}No libgcrypt crypto library found! +" fi +if test "$use_crypto" = "auto" && test "$found_crypto" = "none" || test "$use_crypto" = "mbedtls"; then -# Check whether --with-wincng was given. -if test "${with_wincng+set}" = set; then : - withval=$with_wincng; use_wincng=$withval + libssh2_save_CPPFLAGS="$CPPFLAGS" + libssh2_save_LDFLAGS="$LDFLAGS" + + if test "${with_libmbedcrypto_prefix+set}" = set; then + CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I${with_libmbedcrypto_prefix}/include" + LDFLAGS="$LDFLAGS${LDFLAGS:+ }-L${with_libmbedcrypto_prefix}/lib" + fi + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libmbedcrypto-prefix was given. +if test "${with_libmbedcrypto_prefix+set}" = set; then : + withval=$with_libmbedcrypto_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi + +fi + + LIBMBEDCRYPTO= + LTLIBMBEDCRYPTO= + INCMBEDCRYPTO= + LIBMBEDCRYPTO_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='mbedcrypto ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBMBEDCRYPTO="${LTLIBMBEDCRYPTO}${LTLIBMBEDCRYPTO:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBMBEDCRYPTO; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBMBEDCRYPTO="${LTLIBMBEDCRYPTO}${LTLIBMBEDCRYPTO:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBMBEDCRYPTO; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$found_so" + else + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$found_a" + else + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBMBEDCRYPTO_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCMBEDCRYPTO; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCMBEDCRYPTO="${INCMBEDCRYPTO}${INCMBEDCRYPTO:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBMBEDCRYPTO; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBMBEDCRYPTO; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBMBEDCRYPTO="${LTLIBMBEDCRYPTO}${LTLIBMBEDCRYPTO:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$dep" + LTLIBMBEDCRYPTO="${LTLIBMBEDCRYPTO}${LTLIBMBEDCRYPTO:+ }$dep" + ;; + esac + done + fi + else + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }-l$name" + LTLIBMBEDCRYPTO="${LTLIBMBEDCRYPTO}${LTLIBMBEDCRYPTO:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBMBEDCRYPTO="${LIBMBEDCRYPTO}${LIBMBEDCRYPTO:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBMBEDCRYPTO="${LTLIBMBEDCRYPTO}${LTLIBMBEDCRYPTO:+ }-R$found_dir" + done + fi + + + ac_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCMBEDCRYPTO; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmbedcrypto" >&5 +$as_echo_n "checking for libmbedcrypto... " >&6; } +if ${ac_cv_libmbedcrypto+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIBMBEDCRYPTO" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_libmbedcrypto=yes +else + ac_cv_libmbedcrypto=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libmbedcrypto" >&5 +$as_echo "$ac_cv_libmbedcrypto" >&6; } + if test "$ac_cv_libmbedcrypto" = yes; then + HAVE_LIBMBEDCRYPTO=yes + +$as_echo "#define HAVE_LIBMBEDCRYPTO 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libmbedcrypto" >&5 +$as_echo_n "checking how to link with libmbedcrypto... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBMBEDCRYPTO" >&5 +$as_echo "$LIBMBEDCRYPTO" >&6; } + else + HAVE_LIBMBEDCRYPTO=no + CPPFLAGS="$ac_save_CPPFLAGS" + LIBMBEDCRYPTO= + LTLIBMBEDCRYPTO= + LIBMBEDCRYPTO_PREFIX= + fi + + + + + + + + + LDFLAGS="$libssh2_save_LDFLAGS" + + if test "$ac_cv_libmbedcrypto" = "yes"; then : + + +$as_echo "#define LIBSSH2_MBEDTLS 1" >>confdefs.h + + found_crypto="mbedtls" + support_clear_memory=yes + + else + CPPFLAGS="$libssh2_save_CPPFLAGS" + fi + + + test "$found_crypto" = "none" && + crypto_errors="${crypto_errors}No mbedtls crypto library found! +" +fi + +if test "$use_crypto" = "auto" && test "$found_crypto" = "none" || test "$use_crypto" = "wincng"; then # Look for Windows Cryptography API: Next Generation + for ac_header in ntdef.h ntstatus.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + ac_fn_c_check_decl "$LINENO" "SecureZeroMemory" "ac_cv_have_decl_SecureZeroMemory" "#include +" +if test "x$ac_cv_have_decl_SecureZeroMemory" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SECUREZEROMEMORY $ac_have_decl +_ACEOF + + + + libssh2_save_CPPFLAGS="$CPPFLAGS" + libssh2_save_LDFLAGS="$LDFLAGS" + + if test "${with_libcrypt32_prefix+set}" = set; then + CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I${with_libcrypt32_prefix}/include" + LDFLAGS="$LDFLAGS${LDFLAGS:+ }-L${with_libcrypt32_prefix}/lib" + fi + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libcrypt32-prefix was given. +if test "${with_libcrypt32_prefix+set}" = set; then : + withval=$with_libcrypt32_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi + +fi + + LIBCRYPT32= + LTLIBCRYPT32= + INCCRYPT32= + LIBCRYPT32_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='crypt32 ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBCRYPT32; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBCRYPT32; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_so" + else + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_a" + else + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBCRYPT32_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCCRYPT32; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCCRYPT32="${INCCRYPT32}${INCCRYPT32:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBCRYPT32; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBCRYPT32; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$dep" + LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }$dep" + ;; + esac + done + fi + else + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-l$name" + LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }-R$found_dir" + done + fi + + + ac_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCCRYPT32; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcrypt32" >&5 +$as_echo_n "checking for libcrypt32... " >&6; } +if ${ac_cv_libcrypt32+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIBCRYPT32" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_libcrypt32=yes +else + ac_cv_libcrypt32=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libcrypt32" >&5 +$as_echo "$ac_cv_libcrypt32" >&6; } + if test "$ac_cv_libcrypt32" = yes; then + HAVE_LIBCRYPT32=yes + +$as_echo "#define HAVE_LIBCRYPT32 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libcrypt32" >&5 +$as_echo_n "checking how to link with libcrypt32... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBCRYPT32" >&5 +$as_echo "$LIBCRYPT32" >&6; } + else + HAVE_LIBCRYPT32=no + CPPFLAGS="$ac_save_CPPFLAGS" + LIBCRYPT32= + LTLIBCRYPT32= + LIBCRYPT32_PREFIX= + fi + + + + + + + + + LDFLAGS="$libssh2_save_LDFLAGS" + + if test "$ac_cv_libcrypt32" = "yes"; then : + + else + CPPFLAGS="$libssh2_save_CPPFLAGS" + fi + + + libssh2_save_CPPFLAGS="$CPPFLAGS" + libssh2_save_LDFLAGS="$LDFLAGS" + + if test "${with_libbcrypt_prefix+set}" = set; then + CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I${with_libbcrypt_prefix}/include" + LDFLAGS="$LDFLAGS${LDFLAGS:+ }-L${with_libbcrypt_prefix}/lib" + fi + @@ -15332,1137 +17032,85 @@ $as_echo "$LIBBCRYPT" >&6; } + LDFLAGS="$libssh2_save_LDFLAGS" + if test "$ac_cv_libbcrypt" = "yes"; then : - - - - - - - use_additional=yes - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - -# Check whether --with-libcrypt32-prefix was given. -if test "${with_libcrypt32_prefix+set}" = set; then : - withval=$with_libcrypt32_prefix; - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - else - additional_includedir="$withval/include" - additional_libdir="$withval/$acl_libdirstem" - fi - fi - -fi - - LIBCRYPT32= - LTLIBCRYPT32= - INCCRYPT32= - LIBCRYPT32_PREFIX= - rpathdirs= - ltrpathdirs= - names_already_handled= - names_next_round='crypt32 ' - while test -n "$names_next_round"; do - names_this_round="$names_next_round" - names_next_round= - for name in $names_this_round; do - already_handled= - for n in $names_already_handled; do - if test "$n" = "$name"; then - already_handled=yes - break - fi - done - if test -z "$already_handled"; then - names_already_handled="$names_already_handled $name" - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` - eval value=\"\$HAVE_LIB$uppername\" - if test -n "$value"; then - if test "$value" = yes; then - eval value=\"\$LIB$uppername\" - test -z "$value" || LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$value" - eval value=\"\$LTLIB$uppername\" - test -z "$value" || LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }$value" - else - : - fi - else - found_dir= - found_la= - found_so= - found_a= - eval libname=\"$acl_libname_spec\" # typically: libname=lib$name - if test -n "$acl_shlibext"; then - shrext=".$acl_shlibext" # typically: shrext=.so - else - shrext= - fi - if test $use_additional = yes; then - dir="$additional_libdir" - if test -n "$acl_shlibext"; then - if test -f "$dir/$libname$shrext"; then - found_dir="$dir" - found_so="$dir/$libname$shrext" - else - if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then - ver=`(cd "$dir" && \ - for f in "$libname$shrext".*; do echo "$f"; done \ - | sed -e "s,^$libname$shrext\\\\.,," \ - | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ - | sed 1q ) 2>/dev/null` - if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then - found_dir="$dir" - found_so="$dir/$libname$shrext.$ver" - fi - else - eval library_names=\"$acl_library_names_spec\" - for f in $library_names; do - if test -f "$dir/$f"; then - found_dir="$dir" - found_so="$dir/$f" - break - fi - done - fi - fi - fi - if test "X$found_dir" = "X"; then - if test -f "$dir/$libname.$acl_libext"; then - found_dir="$dir" - found_a="$dir/$libname.$acl_libext" - fi - fi - if test "X$found_dir" != "X"; then - if test -f "$dir/$libname.la"; then - found_la="$dir/$libname.la" - fi - fi - fi - if test "X$found_dir" = "X"; then - for x in $LDFLAGS $LTLIBCRYPT32; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - case "$x" in - -L*) - dir=`echo "X$x" | sed -e 's/^X-L//'` - if test -n "$acl_shlibext"; then - if test -f "$dir/$libname$shrext"; then - found_dir="$dir" - found_so="$dir/$libname$shrext" - else - if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then - ver=`(cd "$dir" && \ - for f in "$libname$shrext".*; do echo "$f"; done \ - | sed -e "s,^$libname$shrext\\\\.,," \ - | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ - | sed 1q ) 2>/dev/null` - if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then - found_dir="$dir" - found_so="$dir/$libname$shrext.$ver" - fi - else - eval library_names=\"$acl_library_names_spec\" - for f in $library_names; do - if test -f "$dir/$f"; then - found_dir="$dir" - found_so="$dir/$f" - break - fi - done - fi - fi - fi - if test "X$found_dir" = "X"; then - if test -f "$dir/$libname.$acl_libext"; then - found_dir="$dir" - found_a="$dir/$libname.$acl_libext" - fi - fi - if test "X$found_dir" != "X"; then - if test -f "$dir/$libname.la"; then - found_la="$dir/$libname.la" - fi - fi - ;; - esac - if test "X$found_dir" != "X"; then - break - fi - done - fi - if test "X$found_dir" != "X"; then - LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }-L$found_dir -l$name" - if test "X$found_so" != "X"; then - if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_so" - else - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $found_dir" - fi - if test "$acl_hardcode_direct" = yes; then - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_so" - else - if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_so" - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $found_dir" - fi - else - haveit= - for x in $LDFLAGS $LIBCRYPT32; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-L$found_dir" - fi - if test "$acl_hardcode_minus_L" != no; then - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_so" - else - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-l$name" - fi - fi - fi - fi - else - if test "X$found_a" != "X"; then - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$found_a" - else - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-L$found_dir -l$name" - fi - fi - additional_includedir= - case "$found_dir" in - */$acl_libdirstem | */$acl_libdirstem/) - basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` - LIBCRYPT32_PREFIX="$basedir" - additional_includedir="$basedir/include" - ;; - esac - if test "X$additional_includedir" != "X"; then - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - for x in $CPPFLAGS $INCCRYPT32; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - INCCRYPT32="${INCCRYPT32}${INCCRYPT32:+ }-I$additional_includedir" - fi - fi - fi - fi - fi - if test -n "$found_la"; then - save_libdir="$libdir" - case "$found_la" in - */* | *\\*) . "$found_la" ;; - *) . "./$found_la" ;; - esac - libdir="$save_libdir" - for dep in $dependency_libs; do - case "$dep" in - -L*) - additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` - if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then - haveit= - if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - haveit= - for x in $LDFLAGS $LIBCRYPT32; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-L$additional_libdir" - fi - fi - haveit= - for x in $LDFLAGS $LTLIBCRYPT32; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }-L$additional_libdir" - fi - fi - fi - fi - ;; - -R*) - dir=`echo "X$dep" | sed -e 's/^X-R//'` - if test "$enable_rpath" != no; then - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $dir" - fi - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $dir" - fi - fi - ;; - -l*) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` - ;; - *.la) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` - ;; - *) - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$dep" - LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }$dep" - ;; - esac - done - fi - else - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }-l$name" - LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }-l$name" - fi - fi - fi - done - done - if test "X$rpathdirs" != "X"; then - if test -n "$acl_hardcode_libdir_separator"; then - alldirs= - for found_dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" - done - acl_save_libdir="$libdir" - libdir="$alldirs" - eval flag=\"$acl_hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$flag" - else - for found_dir in $rpathdirs; do - acl_save_libdir="$libdir" - libdir="$found_dir" - eval flag=\"$acl_hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBCRYPT32="${LIBCRYPT32}${LIBCRYPT32:+ }$flag" - done - fi - fi - if test "X$ltrpathdirs" != "X"; then - for found_dir in $ltrpathdirs; do - LTLIBCRYPT32="${LTLIBCRYPT32}${LTLIBCRYPT32:+ }-R$found_dir" - done - fi - - - ac_save_CPPFLAGS="$CPPFLAGS" - - for element in $INCCRYPT32; do - haveit= - for x in $CPPFLAGS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X$element"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" - fi - done - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcrypt32" >&5 -$as_echo_n "checking for libcrypt32... " >&6; } -if ${ac_cv_libcrypt32+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ac_save_LIBS="$LIBS" - LIBS="$LIBS $LIBCRYPT32" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - #include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_libcrypt32=yes -else - ac_cv_libcrypt32=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LIBS="$ac_save_LIBS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libcrypt32" >&5 -$as_echo "$ac_cv_libcrypt32" >&6; } - if test "$ac_cv_libcrypt32" = yes; then - HAVE_LIBCRYPT32=yes - -$as_echo "#define HAVE_LIBCRYPT32 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libcrypt32" >&5 -$as_echo_n "checking how to link with libcrypt32... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBCRYPT32" >&5 -$as_echo "$LIBCRYPT32" >&6; } - else - HAVE_LIBCRYPT32=no - CPPFLAGS="$ac_save_CPPFLAGS" - LIBCRYPT32= - LTLIBCRYPT32= - LIBCRYPT32_PREFIX= - fi - - - - - - - - for ac_header in ntdef.h ntstatus.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" " - #include - -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - ac_fn_c_check_decl "$LINENO" "SecureZeroMemory" "ac_cv_have_decl_SecureZeroMemory" " - #include - -" -if test "x$ac_cv_have_decl_SecureZeroMemory" = xyes; then : - ac_have_decl=1 -else - ac_have_decl=0 -fi - -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_SECUREZEROMEMORY $ac_have_decl -_ACEOF - - - if test "$ac_cv_libbcrypt" = "yes"; then - $as_echo "#define LIBSSH2_WINCNG 1" >>confdefs.h - LIBSREQUIRED= # wincng doesn't provide a .pc file. sad face. - LIBS="$LIBS -lbcrypt" - if test "$ac_cv_libcrypt32" = "yes"; then - LIBS="$LIBS -lcrypt32" - fi - found_crypto="Windows Cryptography API: Next Generation" - if test "$ac_cv_have_decl_SecureZeroMemory" = "yes"; then - support_clear_memory=yes - fi - fi + found_crypto="wincng" + found_crypto_str="Windows Cryptography API: Next Generation" + support_clear_memory="$ac_cv_have_decl_SecureZeroMemory" - -else - use_wincng=auto -fi - - -# Check whether --with-mbedtls was given. -if test "${with_mbedtls+set}" = set; then : - withval=$with_mbedtls; use_mbedtls=$withval - - - old_LDFLAGS=$LDFLAGS - old_CFLAGS=$CFLAGS - if test -n "$use_mbedtls" && test "$use_mbedtls" != "no"; then - LDFLAGS="$LDFLAGS -L$use_mbedtls/lib" - CFLAGS="$CFLAGS -I$use_mbedtls/include" - fi - - - - - - - - - - - - use_additional=yes - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - -# Check whether --with-libmbedtls-prefix was given. -if test "${with_libmbedtls_prefix+set}" = set; then : - withval=$with_libmbedtls_prefix; - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - else - additional_includedir="$withval/include" - additional_libdir="$withval/$acl_libdirstem" - fi - fi - -fi - - LIBMBEDTLS= - LTLIBMBEDTLS= - INCMBEDTLS= - LIBMBEDTLS_PREFIX= - rpathdirs= - ltrpathdirs= - names_already_handled= - names_next_round='mbedtls ' - while test -n "$names_next_round"; do - names_this_round="$names_next_round" - names_next_round= - for name in $names_this_round; do - already_handled= - for n in $names_already_handled; do - if test "$n" = "$name"; then - already_handled=yes - break - fi - done - if test -z "$already_handled"; then - names_already_handled="$names_already_handled $name" - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` - eval value=\"\$HAVE_LIB$uppername\" - if test -n "$value"; then - if test "$value" = yes; then - eval value=\"\$LIB$uppername\" - test -z "$value" || LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$value" - eval value=\"\$LTLIB$uppername\" - test -z "$value" || LTLIBMBEDTLS="${LTLIBMBEDTLS}${LTLIBMBEDTLS:+ }$value" - else - : - fi - else - found_dir= - found_la= - found_so= - found_a= - eval libname=\"$acl_libname_spec\" # typically: libname=lib$name - if test -n "$acl_shlibext"; then - shrext=".$acl_shlibext" # typically: shrext=.so - else - shrext= - fi - if test $use_additional = yes; then - dir="$additional_libdir" - if test -n "$acl_shlibext"; then - if test -f "$dir/$libname$shrext"; then - found_dir="$dir" - found_so="$dir/$libname$shrext" - else - if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then - ver=`(cd "$dir" && \ - for f in "$libname$shrext".*; do echo "$f"; done \ - | sed -e "s,^$libname$shrext\\\\.,," \ - | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ - | sed 1q ) 2>/dev/null` - if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then - found_dir="$dir" - found_so="$dir/$libname$shrext.$ver" - fi - else - eval library_names=\"$acl_library_names_spec\" - for f in $library_names; do - if test -f "$dir/$f"; then - found_dir="$dir" - found_so="$dir/$f" - break - fi - done - fi - fi - fi - if test "X$found_dir" = "X"; then - if test -f "$dir/$libname.$acl_libext"; then - found_dir="$dir" - found_a="$dir/$libname.$acl_libext" - fi - fi - if test "X$found_dir" != "X"; then - if test -f "$dir/$libname.la"; then - found_la="$dir/$libname.la" - fi - fi - fi - if test "X$found_dir" = "X"; then - for x in $LDFLAGS $LTLIBMBEDTLS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - case "$x" in - -L*) - dir=`echo "X$x" | sed -e 's/^X-L//'` - if test -n "$acl_shlibext"; then - if test -f "$dir/$libname$shrext"; then - found_dir="$dir" - found_so="$dir/$libname$shrext" - else - if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then - ver=`(cd "$dir" && \ - for f in "$libname$shrext".*; do echo "$f"; done \ - | sed -e "s,^$libname$shrext\\\\.,," \ - | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ - | sed 1q ) 2>/dev/null` - if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then - found_dir="$dir" - found_so="$dir/$libname$shrext.$ver" - fi - else - eval library_names=\"$acl_library_names_spec\" - for f in $library_names; do - if test -f "$dir/$f"; then - found_dir="$dir" - found_so="$dir/$f" - break - fi - done - fi - fi - fi - if test "X$found_dir" = "X"; then - if test -f "$dir/$libname.$acl_libext"; then - found_dir="$dir" - found_a="$dir/$libname.$acl_libext" - fi - fi - if test "X$found_dir" != "X"; then - if test -f "$dir/$libname.la"; then - found_la="$dir/$libname.la" - fi - fi - ;; - esac - if test "X$found_dir" != "X"; then - break - fi - done - fi - if test "X$found_dir" != "X"; then - LTLIBMBEDTLS="${LTLIBMBEDTLS}${LTLIBMBEDTLS:+ }-L$found_dir -l$name" - if test "X$found_so" != "X"; then - if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$found_so" - else - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $found_dir" - fi - if test "$acl_hardcode_direct" = yes; then - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$found_so" - else - if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$found_so" - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $found_dir" - fi - else - haveit= - for x in $LDFLAGS $LIBMBEDTLS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }-L$found_dir" - fi - if test "$acl_hardcode_minus_L" != no; then - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$found_so" - else - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }-l$name" - fi - fi - fi - fi - else - if test "X$found_a" != "X"; then - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$found_a" - else - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }-L$found_dir -l$name" - fi - fi - additional_includedir= - case "$found_dir" in - */$acl_libdirstem | */$acl_libdirstem/) - basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` - LIBMBEDTLS_PREFIX="$basedir" - additional_includedir="$basedir/include" - ;; - esac - if test "X$additional_includedir" != "X"; then - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - for x in $CPPFLAGS $INCMBEDTLS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - INCMBEDTLS="${INCMBEDTLS}${INCMBEDTLS:+ }-I$additional_includedir" - fi - fi - fi - fi - fi - if test -n "$found_la"; then - save_libdir="$libdir" - case "$found_la" in - */* | *\\*) . "$found_la" ;; - *) . "./$found_la" ;; - esac - libdir="$save_libdir" - for dep in $dependency_libs; do - case "$dep" in - -L*) - additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` - if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then - haveit= - if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - haveit= - for x in $LDFLAGS $LIBMBEDTLS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }-L$additional_libdir" - fi - fi - haveit= - for x in $LDFLAGS $LTLIBMBEDTLS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LTLIBMBEDTLS="${LTLIBMBEDTLS}${LTLIBMBEDTLS:+ }-L$additional_libdir" - fi - fi - fi - fi - ;; - -R*) - dir=`echo "X$dep" | sed -e 's/^X-R//'` - if test "$enable_rpath" != no; then - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $dir" - fi - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $dir" - fi - fi - ;; - -l*) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` - ;; - *.la) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` - ;; - *) - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$dep" - LTLIBMBEDTLS="${LTLIBMBEDTLS}${LTLIBMBEDTLS:+ }$dep" - ;; - esac - done - fi - else - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }-l$name" - LTLIBMBEDTLS="${LTLIBMBEDTLS}${LTLIBMBEDTLS:+ }-l$name" - fi - fi - fi - done - done - if test "X$rpathdirs" != "X"; then - if test -n "$acl_hardcode_libdir_separator"; then - alldirs= - for found_dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" - done - acl_save_libdir="$libdir" - libdir="$alldirs" - eval flag=\"$acl_hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$flag" - else - for found_dir in $rpathdirs; do - acl_save_libdir="$libdir" - libdir="$found_dir" - eval flag=\"$acl_hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBMBEDTLS="${LIBMBEDTLS}${LIBMBEDTLS:+ }$flag" - done - fi - fi - if test "X$ltrpathdirs" != "X"; then - for found_dir in $ltrpathdirs; do - LTLIBMBEDTLS="${LTLIBMBEDTLS}${LTLIBMBEDTLS:+ }-R$found_dir" - done - fi - - - ac_save_CPPFLAGS="$CPPFLAGS" - - for element in $INCMBEDTLS; do - haveit= - for x in $CPPFLAGS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X$element"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" - fi - done - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmbedtls" >&5 -$as_echo_n "checking for libmbedtls... " >&6; } -if ${ac_cv_libmbedtls+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ac_save_LIBS="$LIBS" - LIBS="$LIBS $LIBMBEDTLS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_libmbedtls=yes -else - ac_cv_libmbedtls=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LIBS="$ac_save_LIBS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libmbedtls" >&5 -$as_echo "$ac_cv_libmbedtls" >&6; } - if test "$ac_cv_libmbedtls" = yes; then - HAVE_LIBMBEDTLS=yes - -$as_echo "#define HAVE_LIBMBEDTLS 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libmbedtls" >&5 -$as_echo_n "checking how to link with libmbedtls... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBMBEDTLS" >&5 -$as_echo "$LIBMBEDTLS" >&6; } else - HAVE_LIBMBEDTLS=no - CPPFLAGS="$ac_save_CPPFLAGS" - LIBMBEDTLS= - LTLIBMBEDTLS= - LIBMBEDTLS_PREFIX= + CPPFLAGS="$libssh2_save_CPPFLAGS" fi - - - - - - - if test "$ac_cv_libmbedtls" = "yes"; then - -$as_echo "#define LIBSSH2_MBEDTLS 1" >>confdefs.h - - LIBSREQUIRED= # mbedtls doesn't provide a .pc file - LIBS="$LIBS -lmbedtls -lmbedcrypto" - found_crypto=libmbedtls - support_clear_memory=yes - else - # restore - LDFLAGS=$old_LDFLAGS - CFLAGS=$old_CFLAGS - fi - - -else - use_mbedtls=auto - + test "$found_crypto" = "none" && + crypto_errors="${crypto_errors}No wincng crypto library found! +" fi + ;; + yes|"") + crypto_errors="No crypto backend specified!" + ;; + *) + crypto_errors="Unknown crypto backend '${use_crypto}' specified!" + ;; +esac + +if test "$found_crypto" = "none"; then + crypto_errors="${crypto_errors} +Specify --with-crypto=\$backend and/or the neccessary library search prefix. + +Known crypto backends: auto, openssl, libgcrypt, mbedtls, wincng" + { $as_echo "$as_me:${as_lineno-$LINENO}: ERROR: ${crypto_errors}" >&5 +$as_echo "$as_me: ERROR: ${crypto_errors}" >&6;} +else + test "$found_crypto_str" = "" && found_crypto_str="$found_crypto" +fi + + if test "$found_crypto" = "openssl"; then + OPENSSL_TRUE= + OPENSSL_FALSE='#' +else + OPENSSL_TRUE='#' + OPENSSL_FALSE= +fi + + if test "$found_crypto" = "libgcrypt"; then + LIBGCRYPT_TRUE= + LIBGCRYPT_FALSE='#' +else + LIBGCRYPT_TRUE='#' + LIBGCRYPT_FALSE= +fi + + if test "$found_crypto" = "mbedtls"; then + MBEDTLS_TRUE= + MBEDTLS_FALSE='#' +else + MBEDTLS_TRUE='#' + MBEDTLS_FALSE= +fi + + if test "$found_crypto" = "wincng"; then + WINCNG_TRUE= + WINCNG_FALSE='#' +else + WINCNG_TRUE='#' + WINCNG_FALSE= +fi + + + + + +# libz + # Check whether --with-libz was given. if test "${with_libz+set}" = set; then : @@ -16472,610 +17120,10 @@ else fi -support_clear_memory=no +found_libz=no +libz_errors="" -# Look for OpenSSL -if test "$found_crypto" = "none" && test "$use_openssl" != "no"; then - - - - - - - - - - - use_additional=yes - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - -# Check whether --with-libssl-prefix was given. -if test "${with_libssl_prefix+set}" = set; then : - withval=$with_libssl_prefix; - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - else - additional_includedir="$withval/include" - additional_libdir="$withval/$acl_libdirstem" - fi - fi - -fi - - LIBSSL= - LTLIBSSL= - INCSSL= - LIBSSL_PREFIX= - rpathdirs= - ltrpathdirs= - names_already_handled= - names_next_round='ssl crypto' - while test -n "$names_next_round"; do - names_this_round="$names_next_round" - names_next_round= - for name in $names_this_round; do - already_handled= - for n in $names_already_handled; do - if test "$n" = "$name"; then - already_handled=yes - break - fi - done - if test -z "$already_handled"; then - names_already_handled="$names_already_handled $name" - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` - eval value=\"\$HAVE_LIB$uppername\" - if test -n "$value"; then - if test "$value" = yes; then - eval value=\"\$LIB$uppername\" - test -z "$value" || LIBSSL="${LIBSSL}${LIBSSL:+ }$value" - eval value=\"\$LTLIB$uppername\" - test -z "$value" || LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }$value" - else - : - fi - else - found_dir= - found_la= - found_so= - found_a= - eval libname=\"$acl_libname_spec\" # typically: libname=lib$name - if test -n "$acl_shlibext"; then - shrext=".$acl_shlibext" # typically: shrext=.so - else - shrext= - fi - if test $use_additional = yes; then - dir="$additional_libdir" - if test -n "$acl_shlibext"; then - if test -f "$dir/$libname$shrext"; then - found_dir="$dir" - found_so="$dir/$libname$shrext" - else - if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then - ver=`(cd "$dir" && \ - for f in "$libname$shrext".*; do echo "$f"; done \ - | sed -e "s,^$libname$shrext\\\\.,," \ - | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ - | sed 1q ) 2>/dev/null` - if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then - found_dir="$dir" - found_so="$dir/$libname$shrext.$ver" - fi - else - eval library_names=\"$acl_library_names_spec\" - for f in $library_names; do - if test -f "$dir/$f"; then - found_dir="$dir" - found_so="$dir/$f" - break - fi - done - fi - fi - fi - if test "X$found_dir" = "X"; then - if test -f "$dir/$libname.$acl_libext"; then - found_dir="$dir" - found_a="$dir/$libname.$acl_libext" - fi - fi - if test "X$found_dir" != "X"; then - if test -f "$dir/$libname.la"; then - found_la="$dir/$libname.la" - fi - fi - fi - if test "X$found_dir" = "X"; then - for x in $LDFLAGS $LTLIBSSL; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - case "$x" in - -L*) - dir=`echo "X$x" | sed -e 's/^X-L//'` - if test -n "$acl_shlibext"; then - if test -f "$dir/$libname$shrext"; then - found_dir="$dir" - found_so="$dir/$libname$shrext" - else - if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then - ver=`(cd "$dir" && \ - for f in "$libname$shrext".*; do echo "$f"; done \ - | sed -e "s,^$libname$shrext\\\\.,," \ - | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ - | sed 1q ) 2>/dev/null` - if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then - found_dir="$dir" - found_so="$dir/$libname$shrext.$ver" - fi - else - eval library_names=\"$acl_library_names_spec\" - for f in $library_names; do - if test -f "$dir/$f"; then - found_dir="$dir" - found_so="$dir/$f" - break - fi - done - fi - fi - fi - if test "X$found_dir" = "X"; then - if test -f "$dir/$libname.$acl_libext"; then - found_dir="$dir" - found_a="$dir/$libname.$acl_libext" - fi - fi - if test "X$found_dir" != "X"; then - if test -f "$dir/$libname.la"; then - found_la="$dir/$libname.la" - fi - fi - ;; - esac - if test "X$found_dir" != "X"; then - break - fi - done - fi - if test "X$found_dir" != "X"; then - LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }-L$found_dir -l$name" - if test "X$found_so" != "X"; then - if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then - LIBSSL="${LIBSSL}${LIBSSL:+ }$found_so" - else - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $found_dir" - fi - if test "$acl_hardcode_direct" = yes; then - LIBSSL="${LIBSSL}${LIBSSL:+ }$found_so" - else - if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then - LIBSSL="${LIBSSL}${LIBSSL:+ }$found_so" - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $found_dir" - fi - else - haveit= - for x in $LDFLAGS $LIBSSL; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - LIBSSL="${LIBSSL}${LIBSSL:+ }-L$found_dir" - fi - if test "$acl_hardcode_minus_L" != no; then - LIBSSL="${LIBSSL}${LIBSSL:+ }$found_so" - else - LIBSSL="${LIBSSL}${LIBSSL:+ }-l$name" - fi - fi - fi - fi - else - if test "X$found_a" != "X"; then - LIBSSL="${LIBSSL}${LIBSSL:+ }$found_a" - else - LIBSSL="${LIBSSL}${LIBSSL:+ }-L$found_dir -l$name" - fi - fi - additional_includedir= - case "$found_dir" in - */$acl_libdirstem | */$acl_libdirstem/) - basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` - LIBSSL_PREFIX="$basedir" - additional_includedir="$basedir/include" - ;; - esac - if test "X$additional_includedir" != "X"; then - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - for x in $CPPFLAGS $INCSSL; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - INCSSL="${INCSSL}${INCSSL:+ }-I$additional_includedir" - fi - fi - fi - fi - fi - if test -n "$found_la"; then - save_libdir="$libdir" - case "$found_la" in - */* | *\\*) . "$found_la" ;; - *) . "./$found_la" ;; - esac - libdir="$save_libdir" - for dep in $dependency_libs; do - case "$dep" in - -L*) - additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` - if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then - haveit= - if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - haveit= - for x in $LDFLAGS $LIBSSL; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LIBSSL="${LIBSSL}${LIBSSL:+ }-L$additional_libdir" - fi - fi - haveit= - for x in $LDFLAGS $LTLIBSSL; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }-L$additional_libdir" - fi - fi - fi - fi - ;; - -R*) - dir=`echo "X$dep" | sed -e 's/^X-R//'` - if test "$enable_rpath" != no; then - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $dir" - fi - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $dir" - fi - fi - ;; - -l*) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` - ;; - *.la) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` - ;; - *) - LIBSSL="${LIBSSL}${LIBSSL:+ }$dep" - LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }$dep" - ;; - esac - done - fi - else - LIBSSL="${LIBSSL}${LIBSSL:+ }-l$name" - LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }-l$name" - fi - fi - fi - done - done - if test "X$rpathdirs" != "X"; then - if test -n "$acl_hardcode_libdir_separator"; then - alldirs= - for found_dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" - done - acl_save_libdir="$libdir" - libdir="$alldirs" - eval flag=\"$acl_hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBSSL="${LIBSSL}${LIBSSL:+ }$flag" - else - for found_dir in $rpathdirs; do - acl_save_libdir="$libdir" - libdir="$found_dir" - eval flag=\"$acl_hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBSSL="${LIBSSL}${LIBSSL:+ }$flag" - done - fi - fi - if test "X$ltrpathdirs" != "X"; then - for found_dir in $ltrpathdirs; do - LTLIBSSL="${LTLIBSSL}${LTLIBSSL:+ }-R$found_dir" - done - fi - - - ac_save_CPPFLAGS="$CPPFLAGS" - - for element in $INCSSL; do - haveit= - for x in $CPPFLAGS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X$element"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" - fi - done - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libssl" >&5 -$as_echo_n "checking for libssl... " >&6; } -if ${ac_cv_libssl+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ac_save_LIBS="$LIBS" - LIBS="$LIBS $LIBSSL" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_libssl=yes -else - ac_cv_libssl=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LIBS="$ac_save_LIBS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libssl" >&5 -$as_echo "$ac_cv_libssl" >&6; } - if test "$ac_cv_libssl" = yes; then - HAVE_LIBSSL=yes - -$as_echo "#define HAVE_LIBSSL 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libssl" >&5 -$as_echo_n "checking how to link with libssl... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBSSL" >&5 -$as_echo "$LIBSSL" >&6; } - else - HAVE_LIBSSL=no - CPPFLAGS="$ac_save_CPPFLAGS" - LIBSSL= - LTLIBSSL= - LIBSSL_PREFIX= - fi - - - - - - - -fi -if test "$ac_cv_libssl" = "yes"; then - -$as_echo "#define LIBSSH2_OPENSSL 1" >>confdefs.h - - LIBSREQUIRED=libssl,libcrypto - - # Not all OpenSSL have AES-CTR functions. - save_LIBS="$LIBS" - LIBS="$LIBS $LIBSSL" - for ac_func in EVP_aes_128_ctr -do : - ac_fn_c_check_func "$LINENO" "EVP_aes_128_ctr" "ac_cv_func_EVP_aes_128_ctr" -if test "x$ac_cv_func_EVP_aes_128_ctr" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_EVP_AES_128_CTR 1 -_ACEOF - -fi -done - - LIBS="$save_LIBS" - - found_crypto="OpenSSL (AES-CTR: ${ac_cv_func_EVP_aes_128_ctr:-N/A})" -fi - - if test "$ac_cv_libssl" = "yes"; then - OPENSSL_TRUE= - OPENSSL_FALSE='#' -else - OPENSSL_TRUE='#' - OPENSSL_FALSE= -fi - - if test "$ac_cv_libbcrypt" = "yes"; then - WINCNG_TRUE= - WINCNG_FALSE='#' -else - WINCNG_TRUE='#' - WINCNG_FALSE= -fi - - if test "$ac_cv_libgcrypt" = "yes"; then - LIBGCRYPT_TRUE= - LIBGCRYPT_FALSE='#' -else - LIBGCRYPT_TRUE='#' - LIBGCRYPT_FALSE= -fi - - if test "$ac_cv_libmbedtls" = "yes"; then - MBEDTLS_TRUE= - MBEDTLS_FALSE='#' -else - MBEDTLS_TRUE='#' - MBEDTLS_FALSE= -fi - - if false; then - OS400QC3_TRUE= - OS400QC3_FALSE='#' -else - OS400QC3_TRUE='#' - OS400QC3_FALSE= -fi - - -# Check if crypto library was found -if test "$found_crypto" = "none"; then - as_fn_error $? "No crypto library found! -Try --with-libssl-prefix=PATH - or --with-libgcrypt-prefix=PATH - or --with-libmbedtls-prefix=PATH - or --with-wincng on Windows\ -" "$LINENO" 5 -fi - -# Look for Libz -if test "$use_libz" != "no"; then +if test "$use_libz" != no; then @@ -17598,18 +17646,22 @@ $as_echo "$LIBZ" >&6; } if test "$ac_cv_libz" != yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot find zlib, disabling compression" >&5 -$as_echo "$as_me: Cannot find zlib, disabling compression" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Try --with-libz-prefix=PATH if you know you have it" >&5 -$as_echo "$as_me: Try --with-libz-prefix=PATH if you know you have it" >&6;} + if test "$use_libz" = auto; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Cannot find libz, disabling compression" >&5 +$as_echo "$as_me: Cannot find libz, disabling compression" >&6;} + found_libz="disabled; no libz found" + else + libz_errors="No libz found! +Try --with-libz-prefix=PATH if you know that you have it." + { $as_echo "$as_me:${as_lineno-$LINENO}: ERROR: $libz_errors" >&5 +$as_echo "$as_me: ERROR: $libz_errors" >&6;} + fi else $as_echo "#define LIBSSH2_HAVE_ZLIB 1" >>confdefs.h - if test "${LIBSREQUIRED}" != ""; then - LIBSREQUIRED="${LIBSREQUIRED}," - fi - LIBSREQUIRED="${LIBSREQUIRED}zlib" + LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }zlib" + found_libz="yes" fi fi @@ -17683,6 +17735,7 @@ if test "${enable_debug+set}" = set; then : no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } + CPPFLAGS="$CPPFLAGS -DNDEBUG" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -17861,34 +17914,6 @@ $as_echo "no" >&6; } fi -# Build example applications? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build example applications" >&5 -$as_echo_n "checking whether to build example applications... " >&6; } -# Check whether --enable-examples-build was given. -if test "${enable_examples_build+set}" = set; then : - enableval=$enable_examples_build; case "$enableval" in - no | false) - build_examples='no' - ;; - *) - build_examples='yes' - ;; -esac -else - build_examples='yes' -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $build_examples" >&5 -$as_echo "$build_examples" >&6; } - if test "x$build_examples" != "xno"; then - BUILD_EXAMPLES_TRUE= - BUILD_EXAMPLES_FALSE='#' -else - BUILD_EXAMPLES_TRUE='#' - BUILD_EXAMPLES_FALSE= -fi - - # Checks for header files. # AC_HEADER_STDC for ac_header in errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h @@ -17994,7 +18019,7 @@ done ;; esac -for ac_func in gettimeofday select strtoll +for ac_func in gettimeofday select strtoll memset_s do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -18583,6 +18608,53 @@ $as_echo "$as_me: WARNING: non-block sockets disabled" >&2;} fi +missing_required_deps=0 + +if test "${libz_errors}" != ""; then + { $as_echo "$as_me:${as_lineno-$LINENO}: ERROR: ${libz_errors}" >&5 +$as_echo "$as_me: ERROR: ${libz_errors}" >&6;} + missing_required_deps=1 +fi + +if test "$found_crypto" = "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: ERROR: ${crypto_errors}" >&5 +$as_echo "$as_me: ERROR: ${crypto_errors}" >&6;} + missing_required_deps=1 +fi + +if test $missing_required_deps = 1; then + as_fn_error $? "Required dependencies are missing!" "$LINENO" 5 +fi + +# Configure parameters + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable compiler warnings as errors" >&5 +$as_echo_n "checking whether to enable compiler warnings as errors... " >&6; } + OPT_COMPILER_WERROR="default" + # Check whether --enable-werror was given. +if test "${enable_werror+set}" = set; then : + enableval=$enable_werror; OPT_COMPILER_WERROR=$enableval +fi + + case "$OPT_COMPILER_WERROR" in + no) + want_werror="no" + ;; + default) + want_werror="no" + ;; + *) + want_werror="yes" + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $want_werror" >&5 +$as_echo "$want_werror" >&6; } + + if test X"$want_werror" = Xyes; then + CFLAGS="$CFLAGS -Werror" + fi + + ac_config_files="$ac_config_files Makefile src/Makefile libssh2.pc" cat >confcache <<\_ACEOF @@ -18735,10 +18807,6 @@ if test -z "${OPENSSL_TRUE}" && test -z "${OPENSSL_FALSE}"; then as_fn_error $? "conditional \"OPENSSL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${WINCNG_TRUE}" && test -z "${WINCNG_FALSE}"; then - as_fn_error $? "conditional \"WINCNG\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${LIBGCRYPT_TRUE}" && test -z "${LIBGCRYPT_FALSE}"; then as_fn_error $? "conditional \"LIBGCRYPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -18747,12 +18815,8 @@ if test -z "${MBEDTLS_TRUE}" && test -z "${MBEDTLS_FALSE}"; then as_fn_error $? "conditional \"MBEDTLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${OS400QC3_TRUE}" && test -z "${OS400QC3_FALSE}"; then - as_fn_error $? "conditional \"OS400QC3\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${BUILD_EXAMPLES_TRUE}" && test -z "${BUILD_EXAMPLES_FALSE}"; then - as_fn_error $? "conditional \"BUILD_EXAMPLES\" was never defined. +if test -z "${WINCNG_TRUE}" && test -z "${WINCNG_FALSE}"; then + as_fn_error $? "conditional \"WINCNG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_SYS_UN_H_TRUE}" && test -z "${HAVE_SYS_UN_H_FALSE}"; then @@ -20923,12 +20987,11 @@ fi Compiler: ${CC} Compiler flags: ${CFLAGS} Library types: Shared=${enable_shared}, Static=${enable_static} - Crypto library: ${found_crypto} + Crypto library: ${found_crypto_str} Clear memory: $enable_clear_memory Debug build: $enable_debug - Build examples: $build_examples Path to sshd: $ac_cv_path_SSHD (only for self-tests) - zlib compression: $ac_cv_libz + zlib compression: ${found_libz} " >&5 $as_echo "$as_me: summary of build options: @@ -20938,10 +21001,9 @@ $as_echo "$as_me: summary of build options: Compiler: ${CC} Compiler flags: ${CFLAGS} Library types: Shared=${enable_shared}, Static=${enable_static} - Crypto library: ${found_crypto} + Crypto library: ${found_crypto_str} Clear memory: $enable_clear_memory Debug build: $enable_debug - Build examples: $build_examples Path to sshd: $ac_cv_path_SSHD (only for self-tests) - zlib compression: $ac_cv_libz + zlib compression: ${found_libz} " >&6;} diff --git a/libssh2/configure.ac b/libssh2/configure.ac index 72ee735bf..686dddb4f 100644 --- a/libssh2/configure.ac +++ b/libssh2/configure.ac @@ -83,79 +83,78 @@ AC_C_BIGENDIAN dnl check for how to do large files AC_SYS_LARGEFILE +# Crypto backends + found_crypto=none - -# Configure parameters -AC_ARG_WITH(openssl, - AC_HELP_STRING([--with-openssl],[Use OpenSSL for crypto]), - use_openssl=$withval,use_openssl=auto) -AC_ARG_WITH(libgcrypt, - AC_HELP_STRING([--with-libgcrypt],[Use libgcrypt for crypto]), - [ use_libgcrypt=$withval - LIBSSH2_CHECKFOR_GCRYPT - ], use_libgcrypt=auto) -AC_ARG_WITH(wincng, - AC_HELP_STRING([--with-wincng],[Use Windows CNG for crypto]), - [ use_wincng=$withval - LIBSSH2_CHECKFOR_WINCNG - ] ,use_wincng=auto) -AC_ARG_WITH([mbedtls], - AC_HELP_STRING([--with-mbedtls],[Use mbedTLS for crypto]), - [ use_mbedtls=$withval - LIBSSH2_CHECKFOR_MBEDTLS - ], use_mbedtls=auto -) -AC_ARG_WITH(libz, - AC_HELP_STRING([--with-libz],[Use zlib for compression]), - use_libz=$withval,use_libz=auto) - +found_crypto_str="" support_clear_memory=no +crypto_errors="" -# Look for OpenSSL -if test "$found_crypto" = "none" && test "$use_openssl" != "no"; then - AC_LIB_HAVE_LINKFLAGS([ssl], [crypto], [#include ]) -fi -if test "$ac_cv_libssl" = "yes"; then - AC_DEFINE(LIBSSH2_OPENSSL, 1, [Use OpenSSL]) - LIBSREQUIRED=libssl,libcrypto +m4_set_add([crypto_backends], [openssl]) +m4_set_add([crypto_backends], [libgcrypt]) +m4_set_add([crypto_backends], [mbedtls]) +m4_set_add([crypto_backends], [wincng]) - # Not all OpenSSL have AES-CTR functions. - save_LIBS="$LIBS" - LIBS="$LIBS $LIBSSL" - AC_CHECK_FUNCS(EVP_aes_128_ctr) - LIBS="$save_LIBS" +AC_ARG_WITH([crypto], + AC_HELP_STRING([--with-crypto=auto|]m4_set_contents([crypto_backends], [|]), + [Select crypto backend (default: auto)]), + use_crypto=$withval, + use_crypto=auto +) - found_crypto="OpenSSL (AES-CTR: ${ac_cv_func_EVP_aes_128_ctr:-N/A})" -fi +case "${use_crypto}" in + auto|m4_set_contents([crypto_backends], [|])) + m4_set_map([crypto_backends], [LIBSSH2_CHECK_CRYPTO]) + ;; + yes|"") + crypto_errors="No crypto backend specified!" + ;; + *) + crypto_errors="Unknown crypto backend '${use_crypto}' specified!" + ;; +esac -AM_CONDITIONAL(OPENSSL, test "$ac_cv_libssl" = "yes") -AM_CONDITIONAL(WINCNG, test "$ac_cv_libbcrypt" = "yes") -AM_CONDITIONAL(LIBGCRYPT, test "$ac_cv_libgcrypt" = "yes") -AM_CONDITIONAL(MBEDTLS, test "$ac_cv_libmbedtls" = "yes") -AM_CONDITIONAL(OS400QC3, false) - -# Check if crypto library was found if test "$found_crypto" = "none"; then - AC_MSG_ERROR([No crypto library found! -Try --with-libssl-prefix=PATH - or --with-libgcrypt-prefix=PATH - or --with-libmbedtls-prefix=PATH - or --with-wincng on Windows\ -]) + crypto_errors="${crypto_errors} +Specify --with-crypto=\$backend and/or the neccessary library search prefix. + +Known crypto backends: auto, m4_set_contents([crypto_backends], [, ])" + AS_MESSAGE([ERROR: ${crypto_errors}]) +else + test "$found_crypto_str" = "" && found_crypto_str="$found_crypto" fi -# Look for Libz -if test "$use_libz" != "no"; then +m4_set_foreach([crypto_backends], [backend], + [AM_CONDITIONAL(m4_toupper(backend), test "$found_crypto" = "backend")] +) +m4_undefine([backend]) + + +# libz + +AC_ARG_WITH([libz], + AC_HELP_STRING([--with-libz],[Use libz for compression]), + use_libz=$withval, + use_libz=auto) + +found_libz=no +libz_errors="" + +if test "$use_libz" != no; then AC_LIB_HAVE_LINKFLAGS([z], [], [#include ]) if test "$ac_cv_libz" != yes; then - AC_MSG_NOTICE([Cannot find zlib, disabling compression]) - AC_MSG_NOTICE([Try --with-libz-prefix=PATH if you know you have it]) + if test "$use_libz" = auto; then + AC_MSG_NOTICE([Cannot find libz, disabling compression]) + found_libz="disabled; no libz found" + else + libz_errors="No libz found! +Try --with-libz-prefix=PATH if you know that you have it." + AS_MESSAGE([ERROR: $libz_errors]) + fi else AC_DEFINE(LIBSSH2_HAVE_ZLIB, 1, [Compile in zlib support]) - if test "${LIBSREQUIRED}" != ""; then - LIBSREQUIRED="${LIBSREQUIRED}," - fi - LIBSREQUIRED="${LIBSREQUIRED}zlib" + LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }zlib" + found_libz="yes" fi fi @@ -213,6 +212,7 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]), [ case "$enable_debug" in no) AC_MSG_RESULT(no) + CPPFLAGS="$CPPFLAGS -DNDEBUG" ;; *) AC_MSG_RESULT(yes) enable_debug=yes @@ -268,22 +268,6 @@ 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"]) - # Checks for header files. # AC_HEADER_STDC AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h]) @@ -319,7 +303,7 @@ case $host in ;; esac -AC_CHECK_FUNCS(gettimeofday select strtoll) +AC_CHECK_FUNCS(gettimeofday select strtoll memset_s) dnl Check for select() into ws2_32 for Msys/Mingw if test "$ac_cv_func_select" != "yes"; then @@ -351,6 +335,25 @@ AC_C_INLINE CURL_CHECK_NONBLOCKING_SOCKET +missing_required_deps=0 + +if test "${libz_errors}" != ""; then + AS_MESSAGE([ERROR: ${libz_errors}]) + missing_required_deps=1 +fi + +if test "$found_crypto" = "none"; then + AS_MESSAGE([ERROR: ${crypto_errors}]) + missing_required_deps=1 +fi + +if test $missing_required_deps = 1; then + AC_MSG_ERROR([Required dependencies are missing!]) +fi + +# Configure parameters +LIBSSH2_CHECK_OPTION_WERROR + AC_CONFIG_FILES([Makefile src/Makefile libssh2.pc]) @@ -364,10 +367,9 @@ AC_MSG_NOTICE([summary of build options: Compiler: ${CC} Compiler flags: ${CFLAGS} Library types: Shared=${enable_shared}, Static=${enable_static} - Crypto library: ${found_crypto} + Crypto library: ${found_crypto_str} Clear memory: $enable_clear_memory Debug build: $enable_debug - Build examples: $build_examples Path to sshd: $ac_cv_path_SSHD (only for self-tests) - zlib compression: $ac_cv_libz + zlib compression: ${found_libz} ]) diff --git a/libssh2/include/libssh2.h b/libssh2/include/libssh2.h index fdcf6163d..d33df03c3 100644 --- a/libssh2/include/libssh2.h +++ b/libssh2/include/libssh2.h @@ -40,19 +40,19 @@ #ifndef LIBSSH2_H #define LIBSSH2_H 1 -#define LIBSSH2_COPYRIGHT "2004-2016 The libssh2 project and its contributors." +#define LIBSSH2_COPYRIGHT "2004-2019 The libssh2 project and its contributors." /* We use underscore instead of dash when appending DEV in dev versions just to make the BANNER define (used by src/session.c) be a valid SSH banner. Release versions have no appended strings and may of course not have dashes either. */ -#define LIBSSH2_VERSION "1.8.2" +#define LIBSSH2_VERSION "1.9.0" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBSSH2_VERSION_MAJOR 1 -#define LIBSSH2_VERSION_MINOR 8 -#define LIBSSH2_VERSION_PATCH 2 +#define LIBSSH2_VERSION_MINOR 9 +#define LIBSSH2_VERSION_PATCH 0 /* This is the numeric version of the libssh2 version number, meant for easier parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will @@ -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 0x010802 +#define LIBSSH2_VERSION_NUM 0x010900 /* * 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 "Mon Mar 25 19:29:57 UTC 2019" +#define LIBSSH2_TIMESTAMP "Thu Jun 20 06:19:26 UTC 2019" #ifndef RC_INVOKED @@ -121,18 +121,28 @@ extern "C" { #if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) # include typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned long long uint64_t; +typedef long long int64_t; #endif #ifdef _MSC_VER typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; typedef unsigned int uint32_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; typedef unsigned __int64 libssh2_uint64_t; typedef __int64 libssh2_int64_t; -#ifndef ssize_t +#if (!defined(HAVE_SSIZE_T) && !defined(ssize_t)) typedef SSIZE_T ssize_t; +#define HAVE_SSIZE_T #endif #else +#include typedef unsigned long long libssh2_uint64_t; typedef long long libssh2_int64_t; #endif @@ -203,7 +213,8 @@ typedef off_t libssh2_struct_stat_size; #ifndef LIBSSH2_STRUCT_STAT_SIZE_FORMAT # ifdef __VMS -/* We have to roll our own format here because %z is a C99-ism we don't have. */ +/* We have to roll our own format here because %z is a C99-ism we don't + have. */ # if __USE_OFF64_T || __USING_STD_STAT # define LIBSSH2_STRUCT_STAT_SIZE_FORMAT "%Ld" # else @@ -219,11 +230,11 @@ typedef off_t libssh2_struct_stat_size; /* Part of every banner, user specified or not */ #define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION -/* We *could* add a comment here if we so chose */ -#define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER -#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n" +#define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER +#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n" -/* Default generate and safe prime sizes for diffie-hellman-group-exchange-sha1 */ +/* 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 @@ -259,14 +270,14 @@ typedef off_t libssh2_struct_stat_size; typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT { - char* text; + char *text; unsigned int length; unsigned char echo; } LIBSSH2_USERAUTH_KBDINT_PROMPT; typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE { - char* text; + char *text; unsigned int length; } LIBSSH2_USERAUTH_KBDINT_RESPONSE; @@ -277,10 +288,10 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE /* 'keyboard-interactive' authentication callback */ #define LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(name_) \ - void name_(const char* name, int name_len, const char* instruction, \ + void name_(const char *name, int name_len, const char *instruction, \ int instruction_len, int num_prompts, \ - const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, \ - LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, void **abstract) + const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, \ + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, void **abstract) /* Callbacks for special SSH packets */ #define LIBSSH2_IGNORE_FUNC(name) \ @@ -314,12 +325,14 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE LIBSSH2_CHANNEL *channel, void **channel_abstract) /* I/O callbacks */ -#define LIBSSH2_RECV_FUNC(name) ssize_t name(libssh2_socket_t socket, \ - void *buffer, size_t length, \ - int flags, void **abstract) -#define LIBSSH2_SEND_FUNC(name) ssize_t name(libssh2_socket_t socket, \ - const void *buffer, size_t length,\ - int flags, void **abstract) +#define LIBSSH2_RECV_FUNC(name) \ + ssize_t name(libssh2_socket_t socket, \ + void *buffer, size_t length, \ + int flags, void **abstract) +#define LIBSSH2_SEND_FUNC(name) \ + ssize_t name(libssh2_socket_t socket, \ + const void *buffer, size_t length, \ + int flags, void **abstract) /* libssh2_session_callback_set() constants */ #define LIBSSH2_CALLBACK_IGNORE 0 @@ -403,11 +416,16 @@ typedef struct _LIBSSH2_POLLFD { /* Hash Types */ #define LIBSSH2_HOSTKEY_HASH_MD5 1 #define LIBSSH2_HOSTKEY_HASH_SHA1 2 +#define LIBSSH2_HOSTKEY_HASH_SHA256 3 /* Hostkey Types */ -#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0 -#define LIBSSH2_HOSTKEY_TYPE_RSA 1 -#define LIBSSH2_HOSTKEY_TYPE_DSS 2 +#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0 +#define LIBSSH2_HOSTKEY_TYPE_RSA 1 +#define LIBSSH2_HOSTKEY_TYPE_DSS 2 +#define LIBSSH2_HOSTKEY_TYPE_ECDSA_256 3 +#define LIBSSH2_HOSTKEY_TYPE_ECDSA_384 4 +#define LIBSSH2_HOSTKEY_TYPE_ECDSA_521 5 +#define LIBSSH2_HOSTKEY_TYPE_ED25519 6 /* Disconnect Codes (defined by SSH protocol) */ #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 @@ -453,7 +471,8 @@ typedef struct _LIBSSH2_POLLFD { #define LIBSSH2_ERROR_FILE -16 #define LIBSSH2_ERROR_METHOD_NONE -17 #define LIBSSH2_ERROR_AUTHENTICATION_FAILED -18 -#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED LIBSSH2_ERROR_AUTHENTICATION_FAILED +#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED \ + LIBSSH2_ERROR_AUTHENTICATION_FAILED #define LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED -19 #define LIBSSH2_ERROR_CHANNEL_OUTOFORDER -20 #define LIBSSH2_ERROR_CHANNEL_FAILURE -21 @@ -482,6 +501,8 @@ typedef struct _LIBSSH2_POLLFD { #define LIBSSH2_ERROR_ENCRYPT -44 #define LIBSSH2_ERROR_BAD_SOCKET -45 #define LIBSSH2_ERROR_KNOWN_HOSTS -46 +#define LIBSSH2_ERROR_CHANNEL_WINDOW_FULL -47 +#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48 /* this is a define to provide the old (<= 1.2.7) name */ #define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV @@ -531,7 +552,7 @@ LIBSSH2_API void libssh2_free(LIBSSH2_SESSION *session, void *ptr); */ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, int method_type, - const char*** algs); + const char ***algs); /* Session API */ LIBSSH2_API LIBSSH2_SESSION * @@ -579,7 +600,7 @@ LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, LIBSSH2_API int libssh2_session_last_errno(LIBSSH2_SESSION *session); LIBSSH2_API int libssh2_session_set_last_error(LIBSSH2_SESSION* session, int errcode, - const char* errmsg); + const char *errmsg); LIBSSH2_API int libssh2_session_block_directions(LIBSSH2_SESSION *session); LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, @@ -592,12 +613,14 @@ LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, unsigned int username_len); LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session); -LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len, - const char *password, - unsigned int password_len, - LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))); +LIBSSH2_API int +libssh2_userauth_password_ex(LIBSSH2_SESSION *session, + const char *username, + unsigned int username_len, + const char *password, + unsigned int password_len, + LIBSSH2_PASSWD_CHANGEREQ_FUNC + ((*passwd_change_cb))); #define libssh2_userauth_password(session, username, password) \ libssh2_userauth_password_ex((session), (username), \ @@ -624,7 +647,8 @@ libssh2_userauth_publickey(LIBSSH2_SESSION *session, const char *username, const unsigned char *pubkeydata, size_t pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), + LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC + ((*sign_callback)), void **abstract); LIBSSH2_API int @@ -716,7 +740,8 @@ libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host, LIBSSH2_API LIBSSH2_LISTENER * libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host, - int port, int *bound_port, int queue_maxsize); + int port, int *bound_port, + int queue_maxsize); #define libssh2_channel_forward_listen(session, port) \ libssh2_channel_forward_listen_ex((session), NULL, (port), NULL, 16) @@ -747,15 +772,17 @@ LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, libssh2_channel_request_pty_ex((channel), (term), \ (unsigned int)strlen(term), \ NULL, 0, \ - LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, \ - LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX) + LIBSSH2_TERM_WIDTH, \ + LIBSSH2_TERM_HEIGHT, \ + LIBSSH2_TERM_WIDTH_PX, \ + LIBSSH2_TERM_HEIGHT_PX) LIBSSH2_API int libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, int width, int height, int width_px, int height_px); #define libssh2_channel_request_pty_size(channel, width, height) \ - libssh2_channel_request_pty_size_ex( (channel), (width), (height), 0, 0) + libssh2_channel_request_pty_size_ex((channel), (width), (height), 0, 0) LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, @@ -817,8 +844,9 @@ LIBSSH2_API ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, #define libssh2_channel_write(channel, buf, buflen) \ libssh2_channel_write_ex((channel), 0, (buf), (buflen)) -#define libssh2_channel_write_stderr(channel, buf, buflen) \ - libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen)) +#define libssh2_channel_write_stderr(channel, buf, buflen) \ + libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, \ + (buf), (buflen)) LIBSSH2_API unsigned long libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, @@ -855,7 +883,7 @@ LIBSSH2_API int libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, libssh2_channel_handle_extended_data((channel), \ (ignore) ? \ LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE : \ - LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL ) + LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL) #define LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA -1 #define LIBSSH2_CHANNEL_FLUSH_ALL -2 @@ -959,13 +987,17 @@ libssh2_knownhost_init(LIBSSH2_SESSION *session); #define LIBSSH2_KNOWNHOST_KEYENC_RAW (1<<16) #define LIBSSH2_KNOWNHOST_KEYENC_BASE64 (2<<16) -/* type of key (2 bits) */ -#define LIBSSH2_KNOWNHOST_KEY_MASK (7<<18) -#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18 -#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18) -#define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18) -#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18) -#define LIBSSH2_KNOWNHOST_KEY_UNKNOWN (7<<18) +/* type of key (3 bits) */ +#define LIBSSH2_KNOWNHOST_KEY_MASK (15<<18) +#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18 +#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18) +#define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18) +#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18) +#define LIBSSH2_KNOWNHOST_KEY_ECDSA_256 (4<<18) +#define LIBSSH2_KNOWNHOST_KEY_ECDSA_384 (5<<18) +#define LIBSSH2_KNOWNHOST_KEY_ECDSA_521 (6<<18) +#define LIBSSH2_KNOWNHOST_KEY_ED25519 (7<<18) +#define LIBSSH2_KNOWNHOST_KEY_UNKNOWN (15<<18) LIBSSH2_API int libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, @@ -1233,6 +1265,24 @@ libssh2_agent_disconnect(LIBSSH2_AGENT *agent); LIBSSH2_API void libssh2_agent_free(LIBSSH2_AGENT *agent); +/* + * libssh2_agent_set_identity_path() + * + * Allows a custom agent identity socket path beyond SSH_AUTH_SOCK env + * + */ +LIBSSH2_API void +libssh2_agent_set_identity_path(LIBSSH2_AGENT *agent, + const char *path); + +/* + * libssh2_agent_get_identity_path() + * + * Returns the custom agent identity socket path if set + * + */ +LIBSSH2_API const char * +libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent); /* * libssh2_keepalive_config() @@ -1247,9 +1297,9 @@ libssh2_agent_free(LIBSSH2_AGENT *agent); * Note that non-blocking applications are responsible for sending the * keepalive messages using libssh2_keepalive_send(). */ -LIBSSH2_API void libssh2_keepalive_config (LIBSSH2_SESSION *session, - int want_reply, - unsigned interval); +LIBSSH2_API void libssh2_keepalive_config(LIBSSH2_SESSION *session, + int want_reply, + unsigned interval); /* * libssh2_keepalive_send() @@ -1259,8 +1309,8 @@ LIBSSH2_API void libssh2_keepalive_config (LIBSSH2_SESSION *session, * it again. Returns 0 on success, or LIBSSH2_ERROR_SOCKET_SEND on * I/O errors. */ -LIBSSH2_API int libssh2_keepalive_send (LIBSSH2_SESSION *session, - int *seconds_to_next); +LIBSSH2_API int libssh2_keepalive_send(LIBSSH2_SESSION *session, + int *seconds_to_next); /* NOTE NOTE NOTE libssh2_trace() has no function in builds that aren't built with debug @@ -1278,11 +1328,11 @@ LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask); #define LIBSSH2_TRACE_SOCKET (1<<9) typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION*, - void*, + void *, const char *, size_t); LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session, - void* context, + void *context, libssh2_trace_handler_func callback); #ifdef __cplusplus diff --git a/libssh2/include/libssh2_publickey.h b/libssh2/include/libssh2_publickey.h index 0979e23cb..5dbdcf925 100644 --- a/libssh2/include/libssh2_publickey.h +++ b/libssh2/include/libssh2_publickey.h @@ -81,16 +81,18 @@ extern "C" { #endif /* Publickey Subsystem */ -LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session); +LIBSSH2_API LIBSSH2_PUBLICKEY * +libssh2_publickey_init(LIBSSH2_SESSION *session); -LIBSSH2_API int libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, - const unsigned char *name, - unsigned long name_len, - const unsigned char *blob, - unsigned long blob_len, char overwrite, - unsigned long num_attrs, - const libssh2_publickey_attribute attrs[]); -#define libssh2_publickey_add(pkey, name, blob, blob_len, overwrite, \ +LIBSSH2_API int +libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, + const unsigned char *name, + unsigned long name_len, + const unsigned char *blob, + unsigned long blob_len, char overwrite, + unsigned long num_attrs, + const libssh2_publickey_attribute attrs[]); +#define libssh2_publickey_add(pkey, name, blob, blob_len, overwrite, \ num_attrs, attrs) \ libssh2_publickey_add_ex((pkey), (name), strlen(name), (blob), (blob_len), \ (overwrite), (num_attrs), (attrs)) @@ -107,8 +109,9 @@ LIBSSH2_API int libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, libssh2_publickey_list **pkey_list); -LIBSSH2_API void libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey, - libssh2_publickey_list *pkey_list); +LIBSSH2_API void +libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey, + libssh2_publickey_list *pkey_list); LIBSSH2_API int libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey); diff --git a/libssh2/include/libssh2_sftp.h b/libssh2/include/libssh2_sftp.h index 677faf2fd..4a750b3e3 100644 --- a/libssh2/include/libssh2_sftp.h +++ b/libssh2/include/libssh2_sftp.h @@ -79,6 +79,9 @@ typedef struct _LIBSSH2_SFTP_STATVFS LIBSSH2_SFTP_STATVFS; #define LIBSSH2_SFTP_READLINK 1 #define LIBSSH2_SFTP_REALPATH 2 +/* Flags for sftp_mkdir() */ +#define LIBSSH2_SFTP_DEFAULT_MODE -1 + /* SFTP attribute flag bits */ #define LIBSSH2_SFTP_ATTR_SIZE 0x00000001 #define LIBSSH2_SFTP_ATTR_UIDGID 0x00000002 @@ -221,12 +224,13 @@ LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp); LIBSSH2_API LIBSSH2_CHANNEL *libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp); /* File / Directory Ops */ -LIBSSH2_API LIBSSH2_SFTP_HANDLE *libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, - const char *filename, - unsigned int filename_len, - unsigned long flags, - long mode, int open_type); -#define libssh2_sftp_open(sftp, filename, flags, mode) \ +LIBSSH2_API LIBSSH2_SFTP_HANDLE * +libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, + const char *filename, + unsigned int filename_len, + unsigned long flags, + long mode, int open_type); +#define libssh2_sftp_open(sftp, filename, flags, mode) \ libssh2_sftp_open_ex((sftp), (filename), strlen(filename), (flags), \ (mode), LIBSSH2_SFTP_OPENFILE) #define libssh2_sftp_opendir(sftp, path) \ @@ -328,7 +332,8 @@ LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned int path_len, char *target, - unsigned int target_len, int link_type); + unsigned int target_len, + int link_type); #define libssh2_sftp_symlink(sftp, orig, linkpath) \ libssh2_sftp_symlink_ex((sftp), (orig), strlen(orig), (linkpath), \ strlen(linkpath), LIBSSH2_SFTP_SYMLINK) diff --git a/libssh2/install-sh b/libssh2/install-sh index 4d4a9519e..8175c640f 100755 --- a/libssh2/install-sh +++ b/libssh2/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2005-05-14.22 +scriptversion=2018-03-11.20; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -35,42 +35,57 @@ scriptversion=2005-05-14.22 # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it +# 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. +# from scratch. -# set DOITPROG to echo to test this script +tab=' ' +nl=' +' +IFS=" $tab$nl" -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" +# Set DOITPROG to "echo" to test this script. -# put in absolute paths if you don't have them in your path; or use env. vars. +doit=${DOITPROG-} +doit_exec=${doit:-exec} -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 -chmodcmd="$chmodprog 0755" -chowncmd= chgrpcmd= -stripcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog rmcmd="$rmprog -f" -mvcmd="$mvprog" +stripcmd= + src= dst= dir_arg= -dstarg= -no_target_directory= +dst_arg= -usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... @@ -80,108 +95,168 @@ In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --c (ignored) --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. --s $stripprog installed files. --t DIRECTORY install into DIRECTORY. --T report an error if DSTFILE is a directory. ---help display this help and exit. ---version display version info and exit. + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last 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. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG " -while test -n "$1"; do +while test $# -ne 0; do case $1 in - -c) shift - continue;; + -c) ;; - -d) dir_arg=true - shift - continue;; + -C) copy_on_change=true;; + + -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; + shift;; --help) echo "$usage"; exit $?;; - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift - shift - continue;; + shift;; - -s) stripcmd=$stripprog - shift - continue;; + -s) stripcmd=$stripprog;; - -t) dstarg=$2 - shift - shift - continue;; + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; - -T) no_target_directory=true - shift - continue;; + -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; - *) # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - test -n "$dir_arg$dstarg" && break - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dstarg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dstarg" - shift # fnord - fi - shift # arg - dstarg=$arg - done - break;; + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; esac + shift done -if test -z "$1"; then +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi - # It's OK to call `install-sh -d' without argument. + # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + for src do - # Protect names starting with `-'. + # Protect names problematic for 'test' and other utilities. case $src in - -*) src=./$src ;; + -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src - src= - - if test -d "$dst"; then - mkdircmd=: - chmodcmd= - else - mkdircmd=$mkdirprog - fi + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. @@ -190,82 +265,193 @@ do exit 1 fi - if test -z "$dstarg"; then + if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi + dst=$dst_arg - dst=$dstarg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst ;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. + # If destination is a directory, append the input filename. if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dstarg: Is a directory" >&2 - exit 1 + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi - dst=$dst/`basename "$src"` + dstdir=$dst + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? fi fi - # This sed command emulates the dirname command. - dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac - # Make sure that the destination directory exists. + obsolete_mkdir_used=false - # Skip lots of stat calls in the usual case. - if test ! -d "$dstdir"; then - defaultIFS=' - ' - IFS="${IFS-$defaultIFS}" + 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;; - oIFS=$IFS - # Some sh's can't handle IFS=/ for some reason. - IFS='%' - set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` - shift - IFS=$oIFS + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac - pathcomp= + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi - while test $# -ne 0 ; do - pathcomp=$pathcomp$1 + 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 + # 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 + + # 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. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or 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. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir shift - if test ! -d "$pathcomp"; then - $mkdirprog "$pathcomp" - # mkdir can fail with a `File exist' error in case several - # install-sh are creating the directory concurrently. This - # is OK. - test -d "$pathcomp" || exit + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (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 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi - pathcomp=$pathcomp/ - done + fi fi if test -n "$dir_arg"; then - $doit $mkdircmd "$dst" \ - && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } - + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else - dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - trap '(exit $?); exit' 1 2 13 15 # Copy the file name to the temp name. - $doit $cpprog "$src" "$dsttmp" && + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # @@ -273,51 +459,60 @@ do # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - # Now rename the file to the real destination. - { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ - || { - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - if test -f "$dstdir/$dstfile"; then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ - || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ - || { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit 1 - } - else - : - fi - } && + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - } - } - fi || { (exit 1); exit 1; } + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi done -# The final little trick to "correctly" pass the exit status to the exit trap. -{ - (exit 0); exit 0 -} - # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" # End: diff --git a/libssh2/os400/initscript.sh b/libssh2/os400/initscript.sh index 1d47a1dd8..a18e24cfe 100644 --- a/libssh2/os400/initscript.sh +++ b/libssh2/os400/initscript.sh @@ -49,7 +49,7 @@ setenv TGTCCSID '500' # Target CCSID of objects. setenv DEBUG '*ALL' # Debug level. setenv OPTIMIZE '10' # Optimisation level setenv OUTPUT '*NONE' # Compilation output option. -setenv TGTRLS 'V5R3M0' # Target OS release. +setenv TGTRLS 'V6R1M0' # Target OS release. setenv IFSDIR '/libssh2' # Installation IFS directory. # Define ZLIB availability and locations. @@ -180,7 +180,7 @@ make_module() CMD="CRTCMOD MODULE(${TARGETLIB}/${1}) SRCSTMF('__tmpsrcf.c')" # CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST *SHOWINC *SHOWSYS)" CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST)" - CMD="${CMD} LOCALETYPE(*LOCALE)" + CMD="${CMD} LOCALETYPE(*LOCALE) FLAG(10)" CMD="${CMD} INCDIR('${TOPDIR}/os400/include'" CMD="${CMD} '/QIBM/ProdData/qadrt/include' '${TOPDIR}/include'" CMD="${CMD} '${TOPDIR}/os400' '${SRCDIR}'" diff --git a/libssh2/src/CMakeLists.txt b/libssh2/src/CMakeLists.txt index 6401acff2..2eaf4cc2c 100644 --- a/libssh2/src/CMakeLists.txt +++ b/libssh2/src/CMakeLists.txt @@ -77,21 +77,21 @@ if(CRYPTO_BACKEND STREQUAL "OpenSSL" OR NOT CRYPTO_BACKEND) list(APPEND PC_LIBS -lcrypt32) find_file(DLL_LIBEAY32 - NAMES libeay32.dll crypto.dll + NAMES libeay32.dll crypto.dll libcrypto-1_1.dll libcrypto-1_1-x64.dll HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS} PATH_SUFFIXES bin) if (NOT DLL_LIBEAY32) message(WARNING - "Unable to find OpenSSL libeay32 DLL, executables may not run") + "Unable to find OpenSSL crypto (aka libeay32) DLL, executables may not run") endif() find_file(DLL_SSLEAY32 - NAMES ssleay32.dll ssl.dll + NAMES ssleay32.dll ssl.dll libssl-1_1.dll libssl-1_1-x64.dll HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS} PATH_SUFFIXES bin) if (NOT DLL_SSLEAY32) message(WARNING - "Unable to find OpenSSL ssleay32 DLL, executables may not run") + "Unable to find OpenSSL ssl (aka ssleay32) DLL, executables may not run") endif() if(DLL_LIBEAY32 AND DLL_SSLEAY32) @@ -176,6 +176,9 @@ include(GNUInstallDirs) set(SOURCES ${CRYPTO_SOURCES} agent.c + blf.h + bcrypt_pbkdf.c + blowfish.c channel.c channel.h comp.c @@ -217,7 +220,7 @@ set_target_properties(libssh2 PROPERTIES PREFIX "") target_compile_definitions(libssh2 PRIVATE ${PRIVATE_COMPILE_DEFINITIONS}) target_include_directories(libssh2 - PRIVATE ${PRIVATE_INCLUDE_DIRECTORIES} + PRIVATE "${PROJECT_SOURCE_DIR}/include/" ${PRIVATE_INCLUDE_DIRECTORIES} PUBLIC $ $/${CMAKE_INSTALL_INCLUDEDIR}>) @@ -312,6 +315,7 @@ if (NOT HAVE_STRTOLL) check_symbol_exists(_strtoi64 stdlib.h HAVE_STRTOI64) endif() check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF) +check_symbol_exists(memset_s string.h HAVE_MEMSET_S) if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR ${CMAKE_SYSTEM_NAME} STREQUAL "Interix") @@ -322,7 +326,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR # filesystem here" # # Mac OS X's poll has funny behaviors, like: - # not being able to do poll on no fildescriptors (10.3?) + # not being able to do poll on no filedescriptors (10.3?) # not being able to poll on some files (like anything in /dev) # not having reliable timeout support # inconsistent return of POLLHUP where other implementations give POLLIN @@ -333,7 +337,7 @@ endif() append_needed_socket_libraries(LIBRARIES) -# Non-blocking socket support tests. Must be after after library tests to +# Non-blocking socket support tests. Must be after library tests to # link correctly set(SAVE_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) set(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES}) diff --git a/libssh2/src/Makefile.am b/libssh2/src/Makefile.am index c14dc7cb3..31d58ed57 100644 --- a/libssh2/src/Makefile.am +++ b/libssh2/src/Makefile.am @@ -1,7 +1,7 @@ # $Id: Makefile.am,v 1.21 2009/05/07 17:21:56 bagder Exp $ AUTOMAKE_OPTIONS = foreign nostdinc -# Get the CRYPTO_CSOURCES and CRYPTO_HHEADERS defines +# Get the CRYPTO_CSOURCES, CRYPTO_HHEADERS and CRYPTO_LTLIBS defines if OPENSSL include ../Makefile.OpenSSL.inc endif @@ -11,9 +11,6 @@ endif if WINCNG include ../Makefile.WinCNG.inc endif -if OS400QC3 -include ../Makefile.os400qc3.inc -endif if MBEDTLS include ../Makefile.mbedTLS.inc endif @@ -65,4 +62,4 @@ VERSION=-version-info 1:1:0 libssh2_la_LDFLAGS = $(VERSION) -no-undefined \ -export-symbols-regex '^libssh2_.*' \ - $(LTLIBGCRYPT) $(LTLIBSSL) $(LTLIBZ) + $(CRYPTO_LTLIBS) $(LTLIBZ) diff --git a/libssh2/src/Makefile.in b/libssh2/src/Makefile.in index 44533bded..c00d9dbae 100644 --- a/libssh2/src/Makefile.in +++ b/libssh2/src/Makefile.in @@ -137,12 +137,12 @@ libssh2_la_LIBADD = am__libssh2_la_SOURCES_DIST = channel.c comp.c crypt.c hostkey.c kex.c \ mac.c misc.c packet.c publickey.c scp.c session.c sftp.c \ userauth.c transport.c version.c knownhost.c agent.c \ - libgcrypt.c mbedtls.c openssl.c os400qc3.c wincng.c pem.c \ - keepalive.c global.c libssh2_priv.h libgcrypt.h mbedtls.h \ - openssl.h os400qc3.h wincng.h transport.h channel.h comp.h \ - mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h -@LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_FALSE@@OS400QC3_FALSE@@WINCNG_TRUE@am__objects_1 = wincng.lo -@LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_FALSE@@OS400QC3_TRUE@am__objects_1 = os400qc3.lo + libgcrypt.c mbedtls.c openssl.c wincng.c pem.c keepalive.c \ + global.c blowfish.c bcrypt_pbkdf.c libssh2_priv.h libgcrypt.h \ + mbedtls.h openssl.h wincng.h transport.h channel.h comp.h \ + mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h \ + blf.h +@LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_FALSE@@WINCNG_TRUE@am__objects_1 = wincng.lo @LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_TRUE@am__objects_1 = \ @LIBGCRYPT_FALSE@@MBEDTLS_FALSE@@OPENSSL_TRUE@ openssl.lo @LIBGCRYPT_FALSE@@MBEDTLS_TRUE@am__objects_1 = mbedtls.lo @@ -150,7 +150,8 @@ am__libssh2_la_SOURCES_DIST = channel.c comp.c crypt.c hostkey.c kex.c \ am__objects_2 = channel.lo comp.lo crypt.lo hostkey.lo kex.lo mac.lo \ misc.lo packet.lo publickey.lo scp.lo session.lo sftp.lo \ userauth.lo transport.lo version.lo knownhost.lo agent.lo \ - $(am__objects_1) pem.lo keepalive.lo global.lo + $(am__objects_1) pem.lo keepalive.lo global.lo blowfish.lo \ + bcrypt_pbkdf.lo am__objects_3 = am__objects_4 = $(am__objects_3) am_libssh2_la_OBJECTS = $(am__objects_2) $(am__objects_4) @@ -177,14 +178,15 @@ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/agent.Plo ./$(DEPDIR)/channel.Plo \ - ./$(DEPDIR)/comp.Plo ./$(DEPDIR)/crypt.Plo \ - ./$(DEPDIR)/global.Plo ./$(DEPDIR)/hostkey.Plo \ - ./$(DEPDIR)/keepalive.Plo ./$(DEPDIR)/kex.Plo \ - ./$(DEPDIR)/knownhost.Plo ./$(DEPDIR)/libgcrypt.Plo \ - ./$(DEPDIR)/mac.Plo ./$(DEPDIR)/mbedtls.Plo \ - ./$(DEPDIR)/misc.Plo ./$(DEPDIR)/openssl.Plo \ - ./$(DEPDIR)/os400qc3.Plo ./$(DEPDIR)/packet.Plo \ +am__depfiles_remade = ./$(DEPDIR)/agent.Plo \ + ./$(DEPDIR)/bcrypt_pbkdf.Plo ./$(DEPDIR)/blowfish.Plo \ + ./$(DEPDIR)/channel.Plo ./$(DEPDIR)/comp.Plo \ + ./$(DEPDIR)/crypt.Plo ./$(DEPDIR)/global.Plo \ + ./$(DEPDIR)/hostkey.Plo ./$(DEPDIR)/keepalive.Plo \ + ./$(DEPDIR)/kex.Plo ./$(DEPDIR)/knownhost.Plo \ + ./$(DEPDIR)/libgcrypt.Plo ./$(DEPDIR)/mac.Plo \ + ./$(DEPDIR)/mbedtls.Plo ./$(DEPDIR)/misc.Plo \ + ./$(DEPDIR)/openssl.Plo ./$(DEPDIR)/packet.Plo \ ./$(DEPDIR)/pem.Plo ./$(DEPDIR)/publickey.Plo \ ./$(DEPDIR)/scp.Plo ./$(DEPDIR)/session.Plo \ ./$(DEPDIR)/sftp.Plo ./$(DEPDIR)/transport.Plo \ @@ -239,8 +241,7 @@ CTAGS = ctags am__DIST_COMMON = $(srcdir)/../Makefile.OpenSSL.inc \ $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.inc \ $(srcdir)/../Makefile.libgcrypt.inc \ - $(srcdir)/../Makefile.mbedTLS.inc \ - $(srcdir)/../Makefile.os400qc3.inc $(srcdir)/Makefile.in \ + $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/Makefile.in \ $(srcdir)/libssh2_config.h.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ @@ -274,7 +275,7 @@ GREP = @GREP@ HAVE_LIBBCRYPT = @HAVE_LIBBCRYPT@ HAVE_LIBCRYPT32 = @HAVE_LIBCRYPT32@ HAVE_LIBGCRYPT = @HAVE_LIBGCRYPT@ -HAVE_LIBMBEDTLS = @HAVE_LIBMBEDTLS@ +HAVE_LIBMBEDCRYPTO = @HAVE_LIBMBEDCRYPTO@ HAVE_LIBSSL = @HAVE_LIBSSL@ HAVE_LIBZ = @HAVE_LIBZ@ INSTALL = @INSTALL@ @@ -290,8 +291,8 @@ LIBCRYPT32 = @LIBCRYPT32@ LIBCRYPT32_PREFIX = @LIBCRYPT32_PREFIX@ LIBGCRYPT = @LIBGCRYPT@ LIBGCRYPT_PREFIX = @LIBGCRYPT_PREFIX@ -LIBMBEDTLS = @LIBMBEDTLS@ -LIBMBEDTLS_PREFIX = @LIBMBEDTLS_PREFIX@ +LIBMBEDCRYPTO = @LIBMBEDCRYPTO@ +LIBMBEDCRYPTO_PREFIX = @LIBMBEDCRYPTO_PREFIX@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSREQUIRED = @LIBSREQUIRED@ @@ -306,7 +307,7 @@ LN_S = @LN_S@ LTLIBBCRYPT = @LTLIBBCRYPT@ LTLIBCRYPT32 = @LTLIBCRYPT32@ LTLIBGCRYPT = @LTLIBGCRYPT@ -LTLIBMBEDTLS = @LTLIBMBEDTLS@ +LTLIBMBEDCRYPTO = @LTLIBMBEDCRYPTO@ LTLIBOBJS = @LTLIBOBJS@ LTLIBSSL = @LTLIBSSL@ LTLIBZ = @LTLIBZ@ @@ -395,22 +396,25 @@ AUTOMAKE_OPTIONS = foreign nostdinc @LIBGCRYPT_TRUE@CRYPTO_CSOURCES = libgcrypt.c @MBEDTLS_TRUE@CRYPTO_CSOURCES = mbedtls.c @OPENSSL_TRUE@CRYPTO_CSOURCES = openssl.c -@OS400QC3_TRUE@CRYPTO_CSOURCES = os400qc3.c @WINCNG_TRUE@CRYPTO_CSOURCES = wincng.c @LIBGCRYPT_TRUE@CRYPTO_HHEADERS = libgcrypt.h @MBEDTLS_TRUE@CRYPTO_HHEADERS = mbedtls.h @OPENSSL_TRUE@CRYPTO_HHEADERS = openssl.h -@OS400QC3_TRUE@CRYPTO_HHEADERS = os400qc3.h @WINCNG_TRUE@CRYPTO_HHEADERS = wincng.h +@LIBGCRYPT_TRUE@CRYPTO_LTLIBS = $(LTLIBGCRYPT) +@MBEDTLS_TRUE@CRYPTO_LTLIBS = $(LTLIBMBEDCRYPTO) +@OPENSSL_TRUE@CRYPTO_LTLIBS = $(LTLIBSSL) +@WINCNG_TRUE@CRYPTO_LTLIBS = $(LTLIBBCRYPT) $(LTLIBCRYPT32) CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \ packet.c publickey.c scp.c session.c sftp.c userauth.c transport.c \ - version.c knownhost.c agent.c $(CRYPTO_CSOURCES) pem.c keepalive.c global.c + version.c knownhost.c agent.c $(CRYPTO_CSOURCES) pem.c keepalive.c global.c \ + blowfish.c bcrypt_pbkdf.c HHEADERS = libssh2_priv.h $(CRYPTO_HHEADERS) transport.h channel.h comp.h \ - mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h + mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h -# Get the CRYPTO_CSOURCES and CRYPTO_HHEADERS defines +# Get the CRYPTO_CSOURCES, CRYPTO_HHEADERS and CRYPTO_LTLIBS defines # Makefile.inc provides the CSOURCES and HHEADERS defines libssh2_la_SOURCES = $(CSOURCES) $(HHEADERS) @@ -452,14 +456,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/src # libssh2_la_LDFLAGS = $(VERSION) -no-undefined \ -export-symbols-regex '^libssh2_.*' \ - $(LTLIBGCRYPT) $(LTLIBSSL) $(LTLIBZ) + $(CRYPTO_LTLIBS) $(LTLIBZ) all: libssh2_config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../Makefile.OpenSSL.inc $(srcdir)/../Makefile.libgcrypt.inc $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.os400qc3.inc $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/../Makefile.inc $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../Makefile.OpenSSL.inc $(srcdir)/../Makefile.libgcrypt.inc $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/../Makefile.inc $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -479,7 +483,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; -$(srcdir)/../Makefile.OpenSSL.inc $(srcdir)/../Makefile.libgcrypt.inc $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.os400qc3.inc $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/../Makefile.inc $(am__empty): +$(srcdir)/../Makefile.OpenSSL.inc $(srcdir)/../Makefile.libgcrypt.inc $(srcdir)/../Makefile.WinCNG.inc $(srcdir)/../Makefile.mbedTLS.inc $(srcdir)/../Makefile.inc $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh @@ -550,6 +554,8 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/agent.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bcrypt_pbkdf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blowfish.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypt.Plo@am__quote@ # am--include-marker @@ -563,7 +569,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbedtls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os400qc3.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pem.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/publickey.Plo@am__quote@ # am--include-marker @@ -737,6 +742,8 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ distclean: distclean-am -rm -f ./$(DEPDIR)/agent.Plo + -rm -f ./$(DEPDIR)/bcrypt_pbkdf.Plo + -rm -f ./$(DEPDIR)/blowfish.Plo -rm -f ./$(DEPDIR)/channel.Plo -rm -f ./$(DEPDIR)/comp.Plo -rm -f ./$(DEPDIR)/crypt.Plo @@ -750,7 +757,6 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/mbedtls.Plo -rm -f ./$(DEPDIR)/misc.Plo -rm -f ./$(DEPDIR)/openssl.Plo - -rm -f ./$(DEPDIR)/os400qc3.Plo -rm -f ./$(DEPDIR)/packet.Plo -rm -f ./$(DEPDIR)/pem.Plo -rm -f ./$(DEPDIR)/publickey.Plo @@ -807,6 +813,8 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/agent.Plo + -rm -f ./$(DEPDIR)/bcrypt_pbkdf.Plo + -rm -f ./$(DEPDIR)/blowfish.Plo -rm -f ./$(DEPDIR)/channel.Plo -rm -f ./$(DEPDIR)/comp.Plo -rm -f ./$(DEPDIR)/crypt.Plo @@ -820,7 +828,6 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mbedtls.Plo -rm -f ./$(DEPDIR)/misc.Plo -rm -f ./$(DEPDIR)/openssl.Plo - -rm -f ./$(DEPDIR)/os400qc3.Plo -rm -f ./$(DEPDIR)/packet.Plo -rm -f ./$(DEPDIR)/pem.Plo -rm -f ./$(DEPDIR)/publickey.Plo diff --git a/libssh2/src/agent.c b/libssh2/src/agent.c index c2ba422b6..0c8d88166 100644 --- a/libssh2/src/agent.c +++ b/libssh2/src/agent.c @@ -138,6 +138,8 @@ struct _LIBSSH2_AGENT struct agent_transaction_ctx transctx; struct agent_publickey *identity; struct list_head head; /* list of public keys */ + + char *identity_agent_path; /* Path to a custom identity agent socket */ }; #ifdef PF_UNIX @@ -147,22 +149,25 @@ agent_connect_unix(LIBSSH2_AGENT *agent) const char *path; struct sockaddr_un s_un; - path = getenv("SSH_AUTH_SOCK"); - if (!path) - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, - "no auth sock variable"); + path = agent->identity_agent_path; + if(!path) { + path = getenv("SSH_AUTH_SOCK"); + if(!path) + return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, + "no auth sock variable"); + } agent->fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (agent->fd < 0) + if(agent->fd < 0) return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_SOCKET, "failed creating socket"); s_un.sun_family = AF_UNIX; - strncpy (s_un.sun_path, path, sizeof s_un.sun_path); - s_un.sun_path[sizeof(s_un.sun_path)-1]=0; /* make sure there's a trailing - zero */ - if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) { - close (agent->fd); + strncpy(s_un.sun_path, path, sizeof s_un.sun_path); + s_un.sun_path[sizeof(s_un.sun_path)-1] = 0; /* make sure there's a trailing + zero */ + if(connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) { + close(agent->fd); return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "failed connecting with agent"); } @@ -177,34 +182,34 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) int rc; /* Send the length of the request */ - if (transctx->state == agent_NB_state_request_created) { + if(transctx->state == agent_NB_state_request_created) { _libssh2_htonu32(buf, transctx->request_len); rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0); - if (rc == -EAGAIN) + if(rc == -EAGAIN) return LIBSSH2_ERROR_EAGAIN; - else if (rc < 0) + else if(rc < 0) return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, "agent send failed"); transctx->state = agent_NB_state_request_length_sent; } /* Send the request body */ - if (transctx->state == agent_NB_state_request_length_sent) { + if(transctx->state == agent_NB_state_request_length_sent) { rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request, transctx->request_len, 0); - if (rc == -EAGAIN) + if(rc == -EAGAIN) return LIBSSH2_ERROR_EAGAIN; - else if (rc < 0) + else if(rc < 0) return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, "agent send failed"); transctx->state = agent_NB_state_request_sent; } /* Receive the length of a response */ - if (transctx->state == agent_NB_state_request_sent) { + if(transctx->state == agent_NB_state_request_sent) { rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0); - if (rc < 0) { - if (rc == -EAGAIN) + if(rc < 0) { + if(rc == -EAGAIN) return LIBSSH2_ERROR_EAGAIN; return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV, "agent recv failed"); @@ -212,18 +217,18 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) transctx->response_len = _libssh2_ntohu32(buf); transctx->response = LIBSSH2_ALLOC(agent->session, transctx->response_len); - if (!transctx->response) + if(!transctx->response) return LIBSSH2_ERROR_ALLOC; transctx->state = agent_NB_state_response_length_received; } /* Receive the response body */ - if (transctx->state == agent_NB_state_response_length_received) { + if(transctx->state == agent_NB_state_response_length_received) { rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response, transctx->response_len, 0); - if (rc < 0) { - if (rc == -EAGAIN) + if(rc < 0) { + if(rc == -EAGAIN) return LIBSSH2_ERROR_EAGAIN; return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, "agent recv failed"); @@ -270,7 +275,7 @@ agent_connect_pageant(LIBSSH2_AGENT *agent) { HWND hwnd; hwnd = FindWindow("Pageant", "Pageant"); - if (!hwnd) + if(!hwnd) return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "failed connecting agent"); agent->fd = 0; /* Mark as the connection has been established */ @@ -288,25 +293,26 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) int id; COPYDATASTRUCT cds; - if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) + if(!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL, "illegal input"); hwnd = FindWindow("Pageant", "Pageant"); - if (!hwnd) + if(!hwnd) return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "found no pageant"); - sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId()); + snprintf(mapname, sizeof(mapname), + "PageantRequest%08x%c", (unsigned)GetCurrentThreadId(), '\0'); filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, PAGEANT_MAX_MSGLEN, mapname); - if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) + if(filemap == NULL || filemap == INVALID_HANDLE_VALUE) return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "failed setting up pageant filemap"); p2 = p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0); - if (p == NULL || p2 == NULL) { + if(p == NULL || p2 == NULL) { CloseHandle(filemap); return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "failed to open pageant filemap for writing"); @@ -320,9 +326,9 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) cds.lpData = mapname; id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds); - if (id > 0) { + if(id > 0) { transctx->response_len = _libssh2_ntohu32(p); - if (transctx->response_len > PAGEANT_MAX_MSGLEN) { + if(transctx->response_len > PAGEANT_MAX_MSGLEN) { UnmapViewOfFile(p); CloseHandle(filemap); return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, @@ -330,7 +336,7 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) } transctx->response = LIBSSH2_ALLOC(agent->session, transctx->response_len); - if (!transctx->response) { + if(!transctx->response) { UnmapViewOfFile(p); CloseHandle(filemap); return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC, @@ -384,9 +390,9 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, int rc; /* Create a request to sign the data */ - if (transctx->state == agent_NB_state_init) { + if(transctx->state == agent_NB_state_init) { s = transctx->request = LIBSSH2_ALLOC(session, len); - if (!transctx->request) + if(!transctx->request) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "out of memory"); @@ -405,17 +411,17 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, } /* Make sure to be re-called as a result of EAGAIN. */ - if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST) + if(*transctx->request != SSH2_AGENTC_SIGN_REQUEST) return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, "illegal request"); - if (!agent->ops) + if(!agent->ops) /* if no agent has been connected, bail out */ return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, "agent not connected"); rc = agent->ops->transact(agent, transctx); - if (rc) { + if(rc) { goto error; } LIBSSH2_FREE(session, transctx->request); @@ -424,11 +430,11 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, len = transctx->response_len; s = transctx->response; len--; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } - if (*s != SSH2_AGENT_SIGN_RESPONSE) { + if(*s != SSH2_AGENT_SIGN_RESPONSE) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } @@ -436,7 +442,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, /* Skip the entire length of the signature */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } @@ -444,14 +450,14 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, /* Skip signing method */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } method_len = _libssh2_ntohu32(s); s += 4; len -= method_len; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } @@ -459,20 +465,20 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, /* Read the signature */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } *sig_len = _libssh2_ntohu32(s); s += 4; len -= *sig_len; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } *sig = LIBSSH2_ALLOC(session, *sig_len); - if (!*sig) { + if(!*sig) { rc = LIBSSH2_ERROR_ALLOC; goto error; } @@ -498,24 +504,24 @@ agent_list_identities(LIBSSH2_AGENT *agent) unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES; /* Create a request to list identities */ - if (transctx->state == agent_NB_state_init) { + if(transctx->state == agent_NB_state_init) { transctx->request = &c; transctx->request_len = 1; transctx->state = agent_NB_state_request_created; } /* Make sure to be re-called as a result of EAGAIN. */ - if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) + if(*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, "illegal agent request"); - if (!agent->ops) + if(!agent->ops) /* if no agent has been connected, bail out */ return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, "agent not connected"); rc = agent->ops->transact(agent, transctx); - if (rc) { + if(rc) { goto error; } transctx->request = NULL; @@ -523,11 +529,11 @@ agent_list_identities(LIBSSH2_AGENT *agent) len = transctx->response_len; s = transctx->response; len--; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } - if (*s != SSH2_AGENT_IDENTITIES_ANSWER) { + if(*s != SSH2_AGENT_IDENTITIES_ANSWER) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } @@ -535,25 +541,25 @@ agent_list_identities(LIBSSH2_AGENT *agent) /* Read the length of identities */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } num_identities = _libssh2_ntohu32(s); s += 4; - while (num_identities--) { + while(num_identities--) { struct agent_publickey *identity; ssize_t comment_len; /* Read the length of the blob */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } identity = LIBSSH2_ALLOC(agent->session, sizeof *identity); - if (!identity) { + if(!identity) { rc = LIBSSH2_ERROR_ALLOC; goto error; } @@ -562,7 +568,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) /* Read the blob */ len -= identity->external.blob_len; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; LIBSSH2_FREE(agent->session, identity); goto error; @@ -570,7 +576,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) identity->external.blob = LIBSSH2_ALLOC(agent->session, identity->external.blob_len); - if (!identity->external.blob) { + if(!identity->external.blob) { rc = LIBSSH2_ERROR_ALLOC; LIBSSH2_FREE(agent->session, identity); goto error; @@ -580,7 +586,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) /* Read the length of the comment */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; LIBSSH2_FREE(agent->session, identity->external.blob); LIBSSH2_FREE(agent->session, identity); @@ -591,7 +597,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) /* Read the comment */ len -= comment_len; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; LIBSSH2_FREE(agent->session, identity->external.blob); LIBSSH2_FREE(agent->session, identity); @@ -600,7 +606,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) identity->external.comment = LIBSSH2_ALLOC(agent->session, comment_len + 1); - if (!identity->external.comment) { + if(!identity->external.comment) { rc = LIBSSH2_ERROR_ALLOC; LIBSSH2_FREE(agent->session, identity->external.blob); LIBSSH2_FREE(agent->session, identity); @@ -621,11 +627,12 @@ agent_list_identities(LIBSSH2_AGENT *agent) } static void -agent_free_identities(LIBSSH2_AGENT *agent) { +agent_free_identities(LIBSSH2_AGENT *agent) +{ struct agent_publickey *node; struct agent_publickey *next; - for (node = _libssh2_list_first(&agent->head); node; node = next) { + for(node = _libssh2_list_first(&agent->head); node; node = next) { next = _libssh2_list_next(&node->node); LIBSSH2_FREE(agent->session, node->external.blob); LIBSSH2_FREE(agent->session, node->external.comment); @@ -664,13 +671,14 @@ libssh2_agent_init(LIBSSH2_SESSION *session) LIBSSH2_AGENT *agent; agent = LIBSSH2_CALLOC(session, sizeof *agent); - if (!agent) { + if(!agent) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate space for agent connection"); return NULL; } agent->fd = LIBSSH2_INVALID_SOCKET; agent->session = session; + agent->identity_agent_path = NULL; _libssh2_list_init(&agent->head); return agent; @@ -687,10 +695,10 @@ LIBSSH2_API int libssh2_agent_connect(LIBSSH2_AGENT *agent) { int i, rc = -1; - for (i = 0; supported_backends[i].name; i++) { + for(i = 0; supported_backends[i].name; i++) { agent->ops = supported_backends[i].ops; rc = (agent->ops->connect)(agent); - if (!rc) + if(!rc) return 0; } return rc; @@ -707,7 +715,7 @@ LIBSSH2_API int libssh2_agent_list_identities(LIBSSH2_AGENT *agent) { memset(&agent->transctx, 0, sizeof agent->transctx); - /* Abondon the last fetched identities */ + /* Abandon the last fetched identities */ agent_free_identities(agent); return agent_list_identities(agent); } @@ -730,7 +738,7 @@ libssh2_agent_get_identity(LIBSSH2_AGENT *agent, struct libssh2_agent_publickey *oprev) { struct agent_publickey *node; - if (oprev && oprev->node) { + if(oprev && oprev->node) { /* we have a starting point */ struct agent_publickey *prev = oprev->node; @@ -740,7 +748,7 @@ libssh2_agent_get_identity(LIBSSH2_AGENT *agent, else node = _libssh2_list_first(&agent->head); - if (!node) + if(!node) /* no (more) node */ return 1; @@ -764,7 +772,7 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent, void *abstract = agent; int rc; - if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) { + if(agent->session->userauth_pblc_state == libssh2_NB_state_idle) { memset(&agent->transctx, 0, sizeof agent->transctx); agent->identity = identity->node; } @@ -789,7 +797,7 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent, LIBSSH2_API int libssh2_agent_disconnect(LIBSSH2_AGENT *agent) { - if (agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET) + if(agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET) return agent->ops->disconnect(agent); return 0; } @@ -801,11 +809,52 @@ libssh2_agent_disconnect(LIBSSH2_AGENT *agent) * collection of public keys. */ LIBSSH2_API void -libssh2_agent_free(LIBSSH2_AGENT *agent) { +libssh2_agent_free(LIBSSH2_AGENT *agent) +{ /* Allow connection freeing when the socket has lost its connection */ - if (agent->fd != LIBSSH2_INVALID_SOCKET) { + if(agent->fd != LIBSSH2_INVALID_SOCKET) { libssh2_agent_disconnect(agent); } + + if(agent->identity_agent_path != NULL) + LIBSSH2_FREE(agent->session, agent->identity_agent_path); + agent_free_identities(agent); LIBSSH2_FREE(agent->session, agent); } + +/* + * libssh2_agent_set_identity_path() + * + * Allows a custom agent socket path beyond SSH_AUTH_SOCK env + * + */ +LIBSSH2_API void +libssh2_agent_set_identity_path(LIBSSH2_AGENT *agent, const char *path) +{ + if(agent->identity_agent_path) { + LIBSSH2_FREE(agent->session, agent->identity_agent_path); + agent->identity_agent_path = NULL; + } + + if(path) { + size_t path_len = strlen(path); + if(path_len < SIZE_MAX - 1) { + char *path_buf = LIBSSH2_ALLOC(agent->session, path_len + 1); + memcpy(path_buf, path, path_len); + path_buf[path_len] = '\0'; + agent->identity_agent_path = path_buf; + } + } +} + +/* + * libssh2_agent_get_identity_path() + * + * Returns the custom agent socket path if set + * + */ +LIBSSH2_API const char *libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent) +{ + return agent->identity_agent_path; +} diff --git a/libssh2/src/bcrypt_pbkdf.c b/libssh2/src/bcrypt_pbkdf.c new file mode 100644 index 000000000..e92969a00 --- /dev/null +++ b/libssh2/src/bcrypt_pbkdf.c @@ -0,0 +1,180 @@ +/* $OpenBSD: bcrypt_pbkdf.c,v 1.4 2013/07/29 00:55:53 tedu Exp $ */ +/* + * Copyright (c) 2013 Ted Unangst + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifndef HAVE_BCRYPT_PBKDF + +#include "libssh2_priv.h" +#include +#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include "blf.h" + +#define MINIMUM(a,b) (((a) < (b)) ? (a) : (b)) + +/* + * pkcs #5 pbkdf2 implementation using the "bcrypt" hash + * + * The bcrypt hash function is derived from the bcrypt password hashing + * function with the following modifications: + * 1. The input password and salt are preprocessed with SHA512. + * 2. The output length is expanded to 256 bits. + * 3. Subsequently the magic string to be encrypted is lengthened and modifed + * to "OxychromaticBlowfishSwatDynamite" + * 4. The hash function is defined to perform 64 rounds of initial state + * expansion. (More rounds are performed by iterating the hash.) + * + * Note that this implementation pulls the SHA512 operations into the caller + * as a performance optimization. + * + * One modification from official pbkdf2. Instead of outputting key material + * linearly, we mix it. pbkdf2 has a known weakness where if one uses it to + * generate (i.e.) 512 bits of key material for use as two 256 bit keys, an + * attacker can merely run once through the outer loop below, but the user + * always runs it twice. Shuffling output bytes requires computing the + * entirety of the key material to assemble any subkey. This is something a + * wise caller could do; we just do it for you. + */ + +#define BCRYPT_BLOCKS 8 +#define BCRYPT_HASHSIZE (BCRYPT_BLOCKS * 4) + +static void +bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out) +{ + blf_ctx state; + uint8_t ciphertext[BCRYPT_HASHSIZE] = + "OxychromaticBlowfishSwatDynamite"; + uint32_t cdata[BCRYPT_BLOCKS]; + int i; + uint16_t j; + size_t shalen = SHA512_DIGEST_LENGTH; + + /* key expansion */ + Blowfish_initstate(&state); + Blowfish_expandstate(&state, sha2salt, shalen, sha2pass, shalen); + for(i = 0; i < 64; i++) { + Blowfish_expand0state(&state, sha2salt, shalen); + Blowfish_expand0state(&state, sha2pass, shalen); + } + + /* encryption */ + j = 0; + for(i = 0; i < BCRYPT_BLOCKS; i++) + cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext), + &j); + for(i = 0; i < 64; i++) + blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t)); + + /* copy out */ + for(i = 0; i < BCRYPT_BLOCKS; i++) { + out[4 * i + 3] = (cdata[i] >> 24) & 0xff; + out[4 * i + 2] = (cdata[i] >> 16) & 0xff; + out[4 * i + 1] = (cdata[i] >> 8) & 0xff; + out[4 * i + 0] = cdata[i] & 0xff; + } + + /* zap */ + _libssh2_explicit_zero(ciphertext, sizeof(ciphertext)); + _libssh2_explicit_zero(cdata, sizeof(cdata)); + _libssh2_explicit_zero(&state, sizeof(state)); +} + +int +bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, + size_t saltlen, + uint8_t *key, size_t keylen, unsigned int rounds) +{ + uint8_t sha2pass[SHA512_DIGEST_LENGTH]; + uint8_t sha2salt[SHA512_DIGEST_LENGTH]; + uint8_t out[BCRYPT_HASHSIZE]; + uint8_t tmpout[BCRYPT_HASHSIZE]; + uint8_t *countsalt; + size_t i, j, amt, stride; + uint32_t count; + size_t origkeylen = keylen; + libssh2_sha512_ctx ctx; + + /* nothing crazy */ + if(rounds < 1) + return -1; + if(passlen == 0 || saltlen == 0 || keylen == 0 || + keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20) + return -1; + countsalt = calloc(1, saltlen + 4); + if(countsalt == NULL) + return -1; + stride = (keylen + sizeof(out) - 1) / sizeof(out); + amt = (keylen + stride - 1) / stride; + + memcpy(countsalt, salt, saltlen); + + /* collapse password */ + libssh2_sha512_init(&ctx); + libssh2_sha512_update(ctx, pass, passlen); + libssh2_sha512_final(ctx, sha2pass); + + /* generate key, sizeof(out) at a time */ + for(count = 1; keylen > 0; count++) { + countsalt[saltlen + 0] = (count >> 24) & 0xff; + countsalt[saltlen + 1] = (count >> 16) & 0xff; + countsalt[saltlen + 2] = (count >> 8) & 0xff; + countsalt[saltlen + 3] = count & 0xff; + + /* first round, salt is salt */ + libssh2_sha512_init(&ctx); + libssh2_sha512_update(ctx, countsalt, saltlen + 4); + libssh2_sha512_final(ctx, sha2salt); + + bcrypt_hash(sha2pass, sha2salt, tmpout); + memcpy(out, tmpout, sizeof(out)); + + for(i = 1; i < rounds; i++) { + /* subsequent rounds, salt is previous output */ + libssh2_sha512_init(&ctx); + libssh2_sha512_update(ctx, tmpout, sizeof(tmpout)); + libssh2_sha512_final(ctx, sha2salt); + + bcrypt_hash(sha2pass, sha2salt, tmpout); + for(j = 0; j < sizeof(out); j++) + out[j] ^= tmpout[j]; + } + + /* + * pbkdf2 deviation: ouput the key material non-linearly. + */ + amt = MINIMUM(amt, keylen); + for(i = 0; i < amt; i++) { + size_t dest = i * stride + (count - 1); + if(dest >= origkeylen) { + break; + } + key[dest] = out[i]; + } + keylen -= i; + } + + /* zap */ + _libssh2_explicit_zero(out, sizeof(out)); + free(countsalt); + + return 0; +} +#endif /* HAVE_BCRYPT_PBKDF */ diff --git a/libssh2/src/blf.h b/libssh2/src/blf.h new file mode 100644 index 000000000..1a85e6eef --- /dev/null +++ b/libssh2/src/blf.h @@ -0,0 +1,90 @@ +/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */ +/* + * Blowfish - a fast block cipher designed by Bruce Schneier + * + * Copyright 1997 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BLF_H_ +#define _BLF_H_ + +#if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) + +/* Schneier specifies a maximum key length of 56 bytes. + * This ensures that every key bit affects every cipher + * bit. However, the subkeys can hold up to 72 bytes. + * Warning: For normal blowfish encryption only 56 bytes + * of the key affect all cipherbits. + */ + +#define BLF_N 16 /* Number of Subkeys */ +#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ +#define BLF_MAXUTILIZED ((BLF_N + 2)*4) /* 576 bits */ + +/* Blowfish context */ +typedef struct BlowfishContext { + uint32_t S[4][256]; /* S-Boxes */ + uint32_t P[BLF_N + 2]; /* Subkeys */ +} blf_ctx; + +/* Raw access to customized Blowfish + * blf_key is just: + * Blowfish_initstate( state ) + * Blowfish_expand0state( state, key, keylen ) + */ + +void Blowfish_encipher(blf_ctx *, uint32_t *, uint32_t *); +void Blowfish_decipher(blf_ctx *, uint32_t *, uint32_t *); +void Blowfish_initstate(blf_ctx *); +void Blowfish_expand0state(blf_ctx *, const uint8_t *, uint16_t); +void Blowfish_expandstate +(blf_ctx *, const uint8_t *, uint16_t, const uint8_t *, uint16_t); + +/* Standard Blowfish */ + +void blf_key(blf_ctx *, const uint8_t *, uint16_t); +void blf_enc(blf_ctx *, uint32_t *, uint16_t); +void blf_dec(blf_ctx *, uint32_t *, uint16_t); + +void blf_ecb_encrypt(blf_ctx *, uint8_t *, uint32_t); +void blf_ecb_decrypt(blf_ctx *, uint8_t *, uint32_t); + +void blf_cbc_encrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t); +void blf_cbc_decrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t); + +/* Converts uint8_t to uint32_t */ +uint32_t Blowfish_stream2word(const uint8_t *, uint16_t, uint16_t *); + +/* bcrypt with pbkd */ +int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, + size_t saltlen, + uint8_t *key, size_t keylen, unsigned int rounds); + +#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */ +#endif /* _BLF_H */ diff --git a/libssh2/src/blowfish.c b/libssh2/src/blowfish.c new file mode 100644 index 000000000..4aefc66ac --- /dev/null +++ b/libssh2/src/blowfish.c @@ -0,0 +1,697 @@ +/* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */ +/* + * Blowfish block cipher for OpenBSD + * Copyright 1997 Niels Provos + * All rights reserved. + * + * Implementation advice by David Mazieres . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This code is derived from section 14.3 and the given source + * in section V of Applied Cryptography, second edition. + * Blowfish is an unpatented fast block cipher designed by + * Bruce Schneier. + */ + + +#if !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \ + !defined(HAVE_BLOWFISH_EXPAND0STATE) || \ + !defined(HAVE_BLF_ENC)) + +#if 0 +#include /* used for debugging */ +#include +#endif + +#include + +#include "libssh2.h" +#include "blf.h" + +#undef inline +#ifdef __GNUC__ +#define inline __inline +#else /* !__GNUC__ */ +#define inline +#endif /* !__GNUC__ */ + +/* Function for Feistel Networks */ + +#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \ + + (s)[0x100 + (((x)>>16)&0xFF)]) \ + ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \ + + (s)[0x300 + ( (x) &0xFF)]) + +#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n]) + +void +Blowfish_encipher(blf_ctx *c, uint32_t *xl, uint32_t *xr) +{ + uint32_t Xl; + uint32_t Xr; + uint32_t *s = c->S[0]; + uint32_t *p = c->P; + + Xl = *xl; + Xr = *xr; + + Xl ^= p[0]; + BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2); + BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4); + BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6); + BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8); + BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10); + BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12); + BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14); + BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16); + + *xl = Xr ^ p[17]; + *xr = Xl; +} + +void +Blowfish_decipher(blf_ctx *c, uint32_t *xl, uint32_t *xr) +{ + uint32_t Xl; + uint32_t Xr; + uint32_t *s = c->S[0]; + uint32_t *p = c->P; + + Xl = *xl; + Xr = *xr; + + Xl ^= p[17]; + BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15); + BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13); + BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11); + BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9); + BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7); + BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5); + BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3); + BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1); + + *xl = Xr ^ p[0]; + *xr = Xl; +} + +void +Blowfish_initstate(blf_ctx *c) +{ + /* P-box and S-box tables initialized with digits of Pi */ + + static const blf_ctx initstate = + { { + { + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a}, + { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7}, + { + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0}, + { + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6} + }, + { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b + } }; + + *c = initstate; +} + +uint32_t +Blowfish_stream2word(const uint8_t *data, uint16_t databytes, + uint16_t *current) +{ + uint8_t i; + uint16_t j; + uint32_t temp; + + temp = 0x00000000; + j = *current; + + for(i = 0; i < 4; i++, j++) { + if(j >= databytes) + j = 0; + temp = (temp << 8) | data[j]; + } + + *current = j; + return temp; +} + +void +Blowfish_expand0state(blf_ctx *c, const uint8_t *key, uint16_t keybytes) +{ + uint16_t i; + uint16_t j; + uint16_t k; + uint32_t temp; + uint32_t datal; + uint32_t datar; + + j = 0; + for(i = 0; i < BLF_N + 2; i++) { + /* Extract 4 int8 to 1 int32 from keystream */ + temp = Blowfish_stream2word(key, keybytes, &j); + c->P[i] = c->P[i] ^ temp; + } + + j = 0; + datal = 0x00000000; + datar = 0x00000000; + for(i = 0; i < BLF_N + 2; i += 2) { + Blowfish_encipher(c, &datal, &datar); + + c->P[i] = datal; + c->P[i + 1] = datar; + } + + for(i = 0; i < 4; i++) { + for(k = 0; k < 256; k += 2) { + Blowfish_encipher(c, &datal, &datar); + + c->S[i][k] = datal; + c->S[i][k + 1] = datar; + } + } +} + + +void +Blowfish_expandstate(blf_ctx *c, const uint8_t *data, uint16_t databytes, + const uint8_t *key, uint16_t keybytes) +{ + uint16_t i; + uint16_t j; + uint16_t k; + uint32_t temp; + uint32_t datal; + uint32_t datar; + + j = 0; + for(i = 0; i < BLF_N + 2; i++) { + /* Extract 4 int8 to 1 int32 from keystream */ + temp = Blowfish_stream2word(key, keybytes, &j); + c->P[i] = c->P[i] ^ temp; + } + + j = 0; + datal = 0x00000000; + datar = 0x00000000; + for(i = 0; i < BLF_N + 2; i += 2) { + datal ^= Blowfish_stream2word(data, databytes, &j); + datar ^= Blowfish_stream2word(data, databytes, &j); + Blowfish_encipher(c, &datal, &datar); + + c->P[i] = datal; + c->P[i + 1] = datar; + } + + for(i = 0; i < 4; i++) { + for(k = 0; k < 256; k += 2) { + datal ^= Blowfish_stream2word(data, databytes, &j); + datar ^= Blowfish_stream2word(data, databytes, &j); + Blowfish_encipher(c, &datal, &datar); + + c->S[i][k] = datal; + c->S[i][k + 1] = datar; + } + } + +} + +void +blf_key(blf_ctx *c, const uint8_t *k, uint16_t len) +{ + /* Initialize S-boxes and subkeys with Pi */ + Blowfish_initstate(c); + + /* Transform S-boxes and subkeys with key */ + Blowfish_expand0state(c, k, len); +} + +void +blf_enc(blf_ctx *c, uint32_t *data, uint16_t blocks) +{ + uint32_t *d; + uint16_t i; + + d = data; + for(i = 0; i < blocks; i++) { + Blowfish_encipher(c, d, d + 1); + d += 2; + } +} + +void +blf_dec(blf_ctx *c, uint32_t *data, uint16_t blocks) +{ + uint32_t *d; + uint16_t i; + + d = data; + for(i = 0; i < blocks; i++) { + Blowfish_decipher(c, d, d + 1); + d += 2; + } +} + +void +blf_ecb_encrypt(blf_ctx *c, uint8_t *data, uint32_t len) +{ + uint32_t l, r; + uint32_t i; + + for(i = 0; i < len; i += 8) { + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_encipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + data += 8; + } +} + +void +blf_ecb_decrypt(blf_ctx *c, uint8_t *data, uint32_t len) +{ + uint32_t l, r; + uint32_t i; + + for(i = 0; i < len; i += 8) { + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_decipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + data += 8; + } +} + +void +blf_cbc_encrypt(blf_ctx *c, uint8_t *iv, uint8_t *data, uint32_t len) +{ + uint32_t l, r; + uint32_t i, j; + + for(i = 0; i < len; i += 8) { + for(j = 0; j < 8; j++) + data[j] ^= iv[j]; + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_encipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + iv = data; + data += 8; + } +} + +void +blf_cbc_decrypt(blf_ctx *c, uint8_t *iva, uint8_t *data, uint32_t len) +{ + uint32_t l, r; + uint8_t *iv; + uint32_t i, j; + + iv = data + len - 16; + data = data + len - 8; + for(i = len - 8; i >= 8; i -= 8) { + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_decipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + for(j = 0; j < 8; j++) + data[j] ^= iv[j]; + iv -= 8; + data -= 8; + } + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_decipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + for(j = 0; j < 8; j++) + data[j] ^= iva[j]; +} + +#if 0 +void +report(uint32_t data[], uint16_t len) +{ + uint16_t i; + for(i = 0; i < len; i += 2) + printf("Block %0hd: %08lx %08lx.\n", + i / 2, data[i], data[i + 1]); +} +void +main(void) +{ + + blf_ctx c; + char key[] = "AAAAA"; + char key2[] = "abcdefghijklmnopqrstuvwxyz"; + + uint32_t data[10]; + uint32_t data2[] = + {0x424c4f57l, 0x46495348l}; + + uint16_t i; + + /* First test */ + for(i = 0; i < 10; i++) + data[i] = i; + + blf_key(&c, (uint8_t *) key, 5); + blf_enc(&c, data, 5); + blf_dec(&c, data, 1); + blf_dec(&c, data + 2, 4); + printf("Should read as 0 - 9.\n"); + report(data, 10); + + /* Second test */ + blf_key(&c, (uint8_t *) key2, strlen(key2)); + blf_enc(&c, data2, 1); + printf("\nShould read as: 0x324ed0fe 0xf413a203.\n"); + report(data2, 2); + blf_dec(&c, data2, 1); + report(data2, 2); +} +#endif + +#endif /* !defined(HAVE_BCRYPT_PBKDF) && \ + (!defined(HAVE_BLOWFISH_INITSTATE) || \ + !defined(HAVE_BLOWFISH_EXPAND0STATE) || \ + '!defined(HAVE_BLF_ENC)) */ diff --git a/libssh2/src/channel.c b/libssh2/src/channel.c index 39ff05bf1..7bbeeb88f 100644 --- a/libssh2/src/channel.c +++ b/libssh2/src/channel.c @@ -1,6 +1,6 @@ /* Copyright (c) 2004-2007 Sara Golemon * Copyright (c) 2005 Mikhail Gusarov - * Copyright (c) 2008-2014 by Daniel Stenberg + * Copyright (c) 2008-2019 by Daniel Stenberg * * All rights reserved. * @@ -66,8 +66,8 @@ _libssh2_channel_nextid(LIBSSH2_SESSION * session) channel = _libssh2_list_first(&session->channels); - while (channel) { - if (channel->local.id > id) { + while(channel) { + if(channel->local.id > id) { id = channel->local.id; } channel = _libssh2_list_next(&channel->node); @@ -100,7 +100,7 @@ _libssh2_channel_locate(LIBSSH2_SESSION *session, uint32_t channel_id) for(channel = _libssh2_list_first(&session->channels); channel; channel = _libssh2_list_next(&channel->node)) { - if (channel->local.id == channel_id) + if(channel->local.id == channel_id) return channel; } @@ -112,7 +112,7 @@ _libssh2_channel_locate(LIBSSH2_SESSION *session, uint32_t channel_id) for(channel = _libssh2_list_first(&l->queue); channel; channel = _libssh2_list_next(&channel->node)) { - if (channel->local.id == channel_id) + if(channel->local.id == channel_id) return channel; } } @@ -141,7 +141,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, unsigned char *s; int rc; - if (session->open_state == libssh2_NB_state_idle) { + if(session->open_state == libssh2_NB_state_idle) { session->open_channel = NULL; session->open_packet = NULL; session->open_data = NULL; @@ -159,7 +159,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, packet_size); session->open_channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL)); - if (!session->open_channel) { + if(!session->open_channel) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate space for channel data"); return NULL; @@ -167,7 +167,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, session->open_channel->channel_type_len = channel_type_len; session->open_channel->channel_type = LIBSSH2_ALLOC(session, channel_type_len); - if (!session->open_channel->channel_type) { + if(!session->open_channel->channel_type) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Failed allocating memory for channel type name"); LIBSSH2_FREE(session, session->open_channel); @@ -189,7 +189,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, s = session->open_packet = LIBSSH2_ALLOC(session, session->open_packet_len); - if (!session->open_packet) { + if(!session->open_packet) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate temporary space for packet"); goto channel_error; @@ -205,17 +205,17 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, session->open_state = libssh2_NB_state_created; } - if (session->open_state == libssh2_NB_state_created) { + if(session->open_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->open_packet, session->open_packet_len, message, message_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending channel-open request"); return NULL; } - else if (rc) { + else if(rc) { _libssh2_error(session, rc, "Unable to send channel-open request"); goto channel_error; @@ -224,17 +224,18 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, session->open_state = libssh2_NB_state_sent; } - if (session->open_state == libssh2_NB_state_sent) { + if(session->open_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->open_data, &session->open_data_len, 1, session->open_packet + 5 + channel_type_len, 4, &session->open_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); return NULL; - } else if (rc) { + } + else if(rc) { goto channel_error; } @@ -244,9 +245,9 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, goto channel_error; } - if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { - - if(session->open_data_len < 17) { + if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { + + if(session->open_data_len < 17) { _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unexpected packet size"); goto channel_error; @@ -278,12 +279,14 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, return session->open_channel; } - if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) { - unsigned int reason_code = _libssh2_ntohu32(session->open_data + 5); - switch (reason_code) { + if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) { + unsigned int reason_code = + _libssh2_ntohu32(session->open_data + 5); + switch(reason_code) { case SSH_OPEN_ADMINISTRATIVELY_PROHIBITED: _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Channel open failure (administratively prohibited)"); + "Channel open failure " + "(administratively prohibited)"); break; case SSH_OPEN_CONNECT_FAILED: _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, @@ -306,15 +309,15 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, channel_error: - if (session->open_data) { + if(session->open_data) { LIBSSH2_FREE(session, session->open_data); session->open_data = NULL; } - if (session->open_packet) { + if(session->open_packet) { LIBSSH2_FREE(session, session->open_packet); session->open_packet = NULL; } - if (session->open_channel) { + if(session->open_channel) { unsigned char channel_id[4]; LIBSSH2_FREE(session, session->open_channel->channel_type); @@ -322,7 +325,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, /* Clear out packets meant for this channel */ _libssh2_htonu32(channel_id, session->open_channel->local.id); - while ((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, + while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &session->open_data, &session->open_data_len, 1, channel_id, 4) >= 0) @@ -379,7 +382,7 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host, LIBSSH2_CHANNEL *channel; unsigned char *s; - if (session->direct_state == libssh2_NB_state_idle) { + if(session->direct_state == libssh2_NB_state_idle) { session->direct_host_len = strlen(host); session->direct_shost_len = strlen(shost); /* host_len(4) + port(4) + shost_len(4) + sport(4) */ @@ -387,14 +390,15 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host, session->direct_host_len + session->direct_shost_len + 16; _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Requesting direct-tcpip session to from %s:%d to %s:%d", + "Requesting direct-tcpip session from %s:%d to %s:%d", shost, sport, host, port); s = session->direct_message = LIBSSH2_ALLOC(session, session->direct_message_len); - if (!session->direct_message) { + if(!session->direct_message) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for direct-tcpip connection"); + "Unable to allocate memory for " + "direct-tcpip connection"); return NULL; } _libssh2_store_str(&s, host, session->direct_host_len); @@ -411,7 +415,7 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host, session->direct_message, session->direct_message_len); - if (!channel && + if(!channel && libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { /* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state to created to avoid re-creating the package on next invoke */ @@ -442,7 +446,8 @@ libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host, return NULL; BLOCK_ADJUST_ERRNO(ptr, session, - channel_direct_tcpip(session, host, port, shost, sport)); + channel_direct_tcpip(session, host, port, + shost, sport)); return ptr; } @@ -463,7 +468,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, if(!host) host = "0.0.0.0"; - if (session->fwdLstn_state == libssh2_NB_state_idle) { + if(session->fwdLstn_state == libssh2_NB_state_idle) { session->fwdLstn_host_len = strlen(host); /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */ @@ -480,7 +485,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, s = session->fwdLstn_packet = LIBSSH2_ALLOC(session, session->fwdLstn_packet_len); - if (!session->fwdLstn_packet) { + if(!session->fwdLstn_packet) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for setenv packet"); return NULL; @@ -496,18 +501,18 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, session->fwdLstn_state = libssh2_NB_state_created; } - if (session->fwdLstn_state == libssh2_NB_state_created) { + if(session->fwdLstn_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->fwdLstn_packet, session->fwdLstn_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending global-request packet for " "forward listen request"); return NULL; } - else if (rc) { + else if(rc) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send global-request packet for forward " "listen request"); @@ -522,34 +527,36 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, session->fwdLstn_state = libssh2_NB_state_sent; } - if (session->fwdLstn_state == libssh2_NB_state_sent) { + if(session->fwdLstn_state == libssh2_NB_state_sent) { unsigned char *data; size_t data_len; rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, 0, NULL, 0, &session->fwdLstn_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); return NULL; - } else if (rc || data_len < 1) { + } + else if(rc || (data_len < 1)) { _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown"); session->fwdLstn_state = libssh2_NB_state_idle; return NULL; } - if (data[0] == SSH_MSG_REQUEST_SUCCESS) { + if(data[0] == SSH_MSG_REQUEST_SUCCESS) { LIBSSH2_LISTENER *listener; listener = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_LISTENER)); - if (!listener) + if(!listener) _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for listener queue"); else { listener->host = LIBSSH2_ALLOC(session, session->fwdLstn_host_len + 1); - if (!listener->host) { + if(!listener->host) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for listener queue"); + "Unable to allocate memory " + "for listener queue"); LIBSSH2_FREE(session, listener); listener = NULL; } @@ -557,10 +564,11 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, listener->session = session; memcpy(listener->host, host, session->fwdLstn_host_len); listener->host[session->fwdLstn_host_len] = 0; - if (data_len >= 5 && !port) { + if(data_len >= 5 && !port) { listener->port = _libssh2_ntohu32(data + 1); _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Dynamic tcpip-forward port allocated: %d", + "Dynamic tcpip-forward port " + "allocated: %d", listener->port); } else @@ -572,7 +580,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, /* append this to the parent's list of listeners */ _libssh2_list_add(&session->listeners, &listener->node); - if (bound_port) { + if(bound_port) { *bound_port = listener->port; } } @@ -582,7 +590,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, session->fwdLstn_state = libssh2_NB_state_idle; return listener; } - else if (data[0] == SSH_MSG_REQUEST_FAILURE) { + else if(data[0] == SSH_MSG_REQUEST_FAILURE) { LIBSSH2_FREE(session, data); _libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED, "Unable to complete request for forward-listen"); @@ -637,13 +645,13 @@ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) int rc; int retcode = 0; - if (listener->chanFwdCncl_state == libssh2_NB_state_idle) { + if(listener->chanFwdCncl_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Cancelling tcpip-forward session for %s:%d", listener->host, listener->port); s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { + if(!packet) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for setenv packet"); return LIBSSH2_ERROR_ALLOC; @@ -658,19 +666,20 @@ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) _libssh2_store_u32(&s, listener->port); listener->chanFwdCncl_state = libssh2_NB_state_created; - } else { + } + else { packet = listener->chanFwdCncl_data; } - if (listener->chanFwdCncl_state == libssh2_NB_state_created) { + if(listener->chanFwdCncl_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending forward request"); listener->chanFwdCncl_data = packet; return rc; } - else if (rc) { + else if(rc) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send global-request packet for forward " "listen request"); @@ -686,11 +695,11 @@ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) } queued = _libssh2_list_first(&listener->queue); - while (queued) { + while(queued) { LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node); rc = _libssh2_channel_free(queued); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } queued = next; @@ -738,9 +747,9 @@ channel_forward_accept(LIBSSH2_LISTENER *listener) do { rc = _libssh2_transport_read(listener->session); - } while (rc > 0); + } while(rc > 0); - if (_libssh2_list_first(&listener->queue)) { + if(_libssh2_list_first(&listener->queue)) { LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue); /* detach channel from listener's queue */ @@ -754,7 +763,7 @@ channel_forward_accept(LIBSSH2_LISTENER *listener) return channel; } - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for packet"); } @@ -799,7 +808,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel, size_t data_len; int rc; - if (channel->setenv_state == libssh2_NB_state_idle) { + if(channel->setenv_state == libssh2_NB_state_idle) { /* 21 = packet_type(1) + channel_id(4) + request_len(4) + * request(3)"env" + want_reply(1) + varname_len(4) + value_len(4) */ channel->setenv_packet_len = varname_len + value_len + 21; @@ -815,7 +824,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel, s = channel->setenv_packet = LIBSSH2_ALLOC(session, channel->setenv_packet_len); - if (!channel->setenv_packet) { + if(!channel->setenv_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory " "for setenv packet"); @@ -831,16 +840,17 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel, channel->setenv_state = libssh2_NB_state_created; } - if (channel->setenv_state == libssh2_NB_state_created) { + if(channel->setenv_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, channel->setenv_packet, channel->setenv_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending setenv request"); return rc; - } else if (rc) { + } + else if(rc) { LIBSSH2_FREE(session, channel->setenv_packet); channel->setenv_packet = NULL; channel->setenv_state = libssh2_NB_state_idle; @@ -856,15 +866,15 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel, channel->setenv_state = libssh2_NB_state_sent; } - if (channel->setenv_state == libssh2_NB_state_sent) { + if(channel->setenv_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, 1, channel->setenv_local_channel, 4, &channel-> setenv_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - if (rc) { + if(rc) { channel->setenv_state = libssh2_NB_state_idle; return rc; } @@ -874,7 +884,7 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel, "Unexpected packet size"); } - if (data[0] == SSH_MSG_CHANNEL_SUCCESS) { + if(data[0] == SSH_MSG_CHANNEL_SUCCESS) { LIBSSH2_FREE(session, data); channel->setenv_state = libssh2_NB_state_idle; return 0; @@ -925,7 +935,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; int rc; - if (channel->reqPTY_state == libssh2_NB_state_idle) { + if(channel->reqPTY_state == libssh2_NB_state_idle) { /* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) + * want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) + * height_px(4) + modes_len(4) */ @@ -962,15 +972,16 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, channel->reqPTY_state = libssh2_NB_state_created; } - if (channel->reqPTY_state == libssh2_NB_state_created) { + if(channel->reqPTY_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, channel->reqPTY_packet, channel->reqPTY_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending pty request"); return rc; - } else if (rc) { + } + else if(rc) { channel->reqPTY_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send pty-request packet"); @@ -980,16 +991,17 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, channel->reqPTY_state = libssh2_NB_state_sent; } - if (channel->reqPTY_state == libssh2_NB_state_sent) { + if(channel->reqPTY_state == libssh2_NB_state_sent) { unsigned char *data; size_t data_len; unsigned char code; rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, 1, channel->reqPTY_local_channel, 4, &channel->reqPTY_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc || data_len < 1) { + } + else if(rc || data_len < 1) { channel->reqPTY_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Failed to require the PTY package"); @@ -1000,12 +1012,13 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, LIBSSH2_FREE(session, data); channel->reqPTY_state = libssh2_NB_state_idle; - if (code == SSH_MSG_CHANNEL_SUCCESS) + if(code == SSH_MSG_CHANNEL_SUCCESS) return 0; } return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for channel request-pty"); + "Unable to complete request for " + "channel request-pty"); } /* @@ -1039,7 +1052,7 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width, int rc; int retcode = LIBSSH2_ERROR_PROTO; - if (channel->reqPTY_state == libssh2_NB_state_idle) { + if(channel->reqPTY_state == libssh2_NB_state_idle) { channel->reqPTY_packet_len = 39; /* Zero the whole thing out */ @@ -1066,15 +1079,16 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width, channel->reqPTY_state = libssh2_NB_state_created; } - if (channel->reqPTY_state == libssh2_NB_state_created) { + if(channel->reqPTY_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, channel->reqPTY_packet, channel->reqPTY_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending window-change request"); return rc; - } else if (rc) { + } + else if(rc) { channel->reqPTY_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send window-change packet"); @@ -1124,7 +1138,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN; int rc; - if (channel->reqX11_state == libssh2_NB_state_idle) { + if(channel->reqX11_state == libssh2_NB_state_idle) { /* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) + * want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) + * screen_num(4) */ @@ -1144,7 +1158,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, s = channel->reqX11_packet = LIBSSH2_ALLOC(session, channel->reqX11_packet_len); - if (!channel->reqX11_packet) { + if(!channel->reqX11_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for pty-request"); } @@ -1156,23 +1170,24 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, *(s++) = 0x01; /* want_reply */ *(s++) = single_connection ? 0x01 : 0x00; - _libssh2_store_str(&s, auth_proto?auth_proto:"MIT-MAGIC-COOKIE-1", + _libssh2_store_str(&s, auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1", proto_len); _libssh2_store_u32(&s, cookie_len); - if (auth_cookie) { + if(auth_cookie) { memcpy(s, auth_cookie, cookie_len); - } else { + } + else { int i; /* note: the extra +1 below is necessary since the sprintf() loop will always write 3 bytes so the last one will write the trailing zero at the LIBSSH2_X11_RANDOM_COOKIE_LEN/2 border */ - unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) +1]; + unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1]; _libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) { - sprintf((char *)&s[i*2], "%02X", buffer[i]); + snprintf((char *)&s[i*2], 3, "%02X", buffer[i]); } } s += cookie_len; @@ -1181,16 +1196,16 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, channel->reqX11_state = libssh2_NB_state_created; } - if (channel->reqX11_state == libssh2_NB_state_created) { + if(channel->reqX11_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, channel->reqX11_packet, channel->reqX11_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending X11-req packet"); return rc; } - if (rc) { + if(rc) { LIBSSH2_FREE(session, channel->reqX11_packet); channel->reqX11_packet = NULL; channel->reqX11_state = libssh2_NB_state_idle; @@ -1205,7 +1220,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, channel->reqX11_state = libssh2_NB_state_sent; } - if (channel->reqX11_state == libssh2_NB_state_sent) { + if(channel->reqX11_state == libssh2_NB_state_sent) { size_t data_len; unsigned char *data; unsigned char code; @@ -1213,9 +1228,10 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, 1, channel->reqX11_local_channel, 4, &channel->reqX11_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc || data_len < 1) { + } + else if(rc || data_len < 1) { channel->reqX11_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "waiting for x11-req response packet"); @@ -1225,7 +1241,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, LIBSSH2_FREE(session, data); channel->reqX11_state = libssh2_NB_state_idle; - if (code == SSH_MSG_CHANNEL_SUCCESS) + if(code == SSH_MSG_CHANNEL_SUCCESS) return 0; } @@ -1270,12 +1286,12 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; int rc; - if (channel->process_state == libssh2_NB_state_end) { + if(channel->process_state == libssh2_NB_state_end) { return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, "Channel can not be reused"); } - if (channel->process_state == libssh2_NB_state_idle) { + if(channel->process_state == libssh2_NB_state_idle) { /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */ channel->process_packet_len = request_len + 10; @@ -1283,16 +1299,16 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, memset(&channel->process_packet_requirev_state, 0, sizeof(channel->process_packet_requirev_state)); - if (message) + if(message) channel->process_packet_len += + 4; _libssh2_debug(session, LIBSSH2_TRACE_CONN, "starting request(%s) on channel %lu/%lu, message=%s", request, channel->local.id, channel->remote.id, - message?message:""); + message ? message : ""); s = channel->process_packet = LIBSSH2_ALLOC(session, channel->process_packet_len); - if (!channel->process_packet) + if(!channel->process_packet) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory " "for channel-process request"); @@ -1302,23 +1318,23 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, _libssh2_store_str(&s, request, request_len); *(s++) = 0x01; - if (message) + if(message) _libssh2_store_u32(&s, message_len); channel->process_state = libssh2_NB_state_created; } - if (channel->process_state == libssh2_NB_state_created) { + if(channel->process_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, channel->process_packet, channel->process_packet_len, (unsigned char *)message, message_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending channel request"); return rc; } - else if (rc) { + else if(rc) { LIBSSH2_FREE(session, channel->process_packet); channel->process_packet = NULL; channel->process_state = libssh2_NB_state_end; @@ -1333,16 +1349,17 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, channel->process_state = libssh2_NB_state_sent; } - if (channel->process_state == libssh2_NB_state_sent) { + if(channel->process_state == libssh2_NB_state_sent) { unsigned char *data; size_t data_len; unsigned char code; rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, 1, channel->process_local_channel, 4, &channel->process_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc || data_len < 1) { + } + else if(rc || data_len < 1) { channel->process_state = libssh2_NB_state_end; return _libssh2_error(session, rc, "Failed waiting for channel success"); @@ -1352,7 +1369,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, LIBSSH2_FREE(session, data); channel->process_state = libssh2_NB_state_end; - if (code == SSH_MSG_CHANNEL_SUCCESS) + if(code == SSH_MSG_CHANNEL_SUCCESS) return 0; } @@ -1405,30 +1422,54 @@ libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking) int _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid) { - if (channel->flush_state == libssh2_NB_state_idle) { + if(channel->flush_state == libssh2_NB_state_idle) { LIBSSH2_PACKET *packet = _libssh2_list_first(&channel->session->packets); channel->flush_refund_bytes = 0; channel->flush_flush_bytes = 0; - while (packet) { + while(packet) { + unsigned char packet_type; LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node); - unsigned char packet_type = packet->data[0]; - if (((packet_type == SSH_MSG_CHANNEL_DATA) - || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) - && (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) { + if(packet->data_len < 1) { + packet = next; + _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR, + "Unexpected packet length"); + continue; + } + + packet_type = packet->data[0]; + + if(((packet_type == SSH_MSG_CHANNEL_DATA) + || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) + && ((packet->data_len >= 5) + && (_libssh2_ntohu32(packet->data + 1) + == channel->local.id))) { /* It's our channel at least */ - long packet_stream_id = - (packet_type == SSH_MSG_CHANNEL_DATA) ? 0 : - _libssh2_ntohu32(packet->data + 5); - if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL) + int packet_stream_id; + + if(packet_type == SSH_MSG_CHANNEL_DATA) { + packet_stream_id = 0; + } + else if(packet->data_len >= 9) { + packet_stream_id = _libssh2_ntohu32(packet->data + 5); + } + else { + channel->flush_state = libssh2_NB_state_idle; + return _libssh2_error(channel->session, + LIBSSH2_ERROR_PROTO, + "Unexpected packet length"); + } + + if((streamid == LIBSSH2_CHANNEL_FLUSH_ALL) || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA) && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA) || (streamid == packet_stream_id))) || ((packet_type == SSH_MSG_CHANNEL_DATA) && (streamid == 0))) { - int bytes_to_flush = packet->data_len - packet->data_head; + size_t bytes_to_flush = packet->data_len - + packet->data_head; _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, "Flushing %d bytes of data from stream " @@ -1456,13 +1497,12 @@ _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid) channel->read_avail -= channel->flush_flush_bytes; channel->remote.window_size -= channel->flush_flush_bytes; - if (channel->flush_refund_bytes) { - int rc; - - rc = _libssh2_channel_receive_window_adjust(channel, - channel->flush_refund_bytes, - 1, NULL); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(channel->flush_refund_bytes) { + int rc = + _libssh2_channel_receive_window_adjust(channel, + channel->flush_refund_bytes, + 1, NULL); + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; } @@ -1528,41 +1568,42 @@ libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel, { size_t namelen = 0; - if (channel) { + if(channel) { LIBSSH2_SESSION *session = channel->session; - if (channel->exit_signal) { + if(channel->exit_signal) { namelen = strlen(channel->exit_signal); - if (exitsignal) { - *exitsignal = LIBSSH2_ALLOC(session, namelen + 1); - if (!*exitsignal) { + if(exitsignal) { + *exitsignal = LIBSSH2_ALLOC(session, namelen + 1); + if(!*exitsignal) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for signal name"); } memcpy(*exitsignal, channel->exit_signal, namelen); (*exitsignal)[namelen] = '\0'; } - if (exitsignal_len) + if(exitsignal_len) *exitsignal_len = namelen; - } else { - if (exitsignal) + } + else { + if(exitsignal) *exitsignal = NULL; - if (exitsignal_len) + if(exitsignal_len) *exitsignal_len = 0; } /* TODO: set error message and language tag */ - if (errmsg) + if(errmsg) *errmsg = NULL; - if (errmsg_len) + if(errmsg_len) *errmsg_len = 0; - if (langtag) + if(langtag) *langtag = NULL; - if (langtag_len) + if(langtag_len) *langtag_len = 0; } @@ -1589,8 +1630,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, if(store) *store = channel->remote.window_size; - if (channel->adjust_state == libssh2_NB_state_idle) { - if (!force + if(channel->adjust_state == libssh2_NB_state_idle) { + if(!force && (adjustment + channel->adjust_queue < LIBSSH2_CHANNEL_MINADJUST)) { _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, @@ -1601,7 +1642,7 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, return 0; } - if (!adjustment && !channel->adjust_queue) { + if(!adjustment && !channel->adjust_queue) { return 0; } @@ -1622,12 +1663,12 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(channel->session, rc, "Would block sending window adjust"); return rc; } - else if (rc) { + else if(rc) { channel->adjust_queue = adjustment; return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment " @@ -1672,7 +1713,7 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, /* stupid - but this is how it was made to work before and this is just kept for backwards compatibility */ - return rc?(unsigned long)rc:window; + return rc ? (unsigned long)rc : window; } /* @@ -1706,7 +1747,7 @@ libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel, int _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode) { - if (channel->extData2_state == libssh2_NB_state_idle) { + if(channel->extData2_state == libssh2_NB_state_idle) { _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, "Setting channel %lu/%lu handle_extended_data" " mode to %d", @@ -1716,8 +1757,8 @@ _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode) channel->extData2_state = libssh2_NB_state_created; } - if (channel->extData2_state == libssh2_NB_state_idle) { - if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) { + if(channel->extData2_state == libssh2_NB_state_idle) { + if(ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) { int rc = _libssh2_channel_flush(channel, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA); @@ -1784,8 +1825,8 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, { LIBSSH2_SESSION *session = channel->session; int rc; - int bytes_read = 0; - int bytes_want; + size_t bytes_read = 0; + size_t bytes_want; int unlink_packet; LIBSSH2_PACKET *read_packet; LIBSSH2_PACKET *read_next; @@ -1797,11 +1838,13 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, stream_id); /* expand the receiving window first if it has become too narrow */ - if( (channel->read_state == libssh2_NB_state_jump1) || - (channel->remote.window_size < channel->remote.window_size_initial / 4 * 3 + buflen) ) { + if((channel->read_state == libssh2_NB_state_jump1) || + (channel->remote.window_size < + channel->remote.window_size_initial / 4 * 3 + buflen) ) { - uint32_t adjustment = channel->remote.window_size_initial + buflen - channel->remote.window_size; - if (adjustment < LIBSSH2_CHANNEL_MINADJUST) + uint32_t adjustment = channel->remote.window_size_initial + buflen - + channel->remote.window_size; + if(adjustment < LIBSSH2_CHANNEL_MINADJUST) adjustment = LIBSSH2_CHANNEL_MINADJUST; /* the actual window adjusting may not finish so we need to deal with @@ -1809,7 +1852,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, channel->read_state = libssh2_NB_state_jump1; rc = _libssh2_channel_receive_window_adjust(channel, adjustment, 0, NULL); - if (rc) + if(rc) return rc; channel->read_state = libssh2_NB_state_idle; @@ -1819,13 +1862,13 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, produces faster transfers. */ do { rc = _libssh2_transport_read(session); - } while (rc > 0); + } while(rc > 0); - if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) + if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) return _libssh2_error(session, rc, "transport read"); read_packet = _libssh2_list_first(&session->packets); - while (read_packet && (bytes_read < (int) buflen)) { + while(read_packet && (bytes_read < buflen)) { /* previously this loop condition also checked for !channel->remote.close but we cannot let it do this: @@ -1839,6 +1882,13 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, /* In case packet gets destroyed during this iteration */ read_next = _libssh2_list_next(&readpkt->node); + if(readpkt->data_len < 5) { + read_packet = read_next; + _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR, + "Unexpected packet length"); + continue; + } + channel->read_local_id = _libssh2_ntohu32(readpkt->data + 1); @@ -1849,9 +1899,10 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, * or the standard stream with extended_data_merge * enabled and data was available */ - if ((stream_id + if((stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (channel->local.id == channel->read_local_id) + && (readpkt->data_len >= 9) && (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5))) || (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA) && (channel->local.id == channel->read_local_id)) @@ -1865,7 +1916,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, bytes_want = buflen - bytes_read; unlink_packet = FALSE; - if (bytes_want >= (int) (readpkt->data_len - readpkt->data_head)) { + if(bytes_want >= (readpkt->data_len - readpkt->data_head)) { /* we want more than this node keeps, so adjust the number and delete this node after the copy */ bytes_want = readpkt->data_len - readpkt->data_head; @@ -1887,7 +1938,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, bytes_read += bytes_want; /* if drained, remove from list */ - if (unlink_packet) { + if(unlink_packet) { /* detach readpkt from session->packets list */ _libssh2_list_remove(&readpkt->node); @@ -1900,7 +1951,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, read_packet = read_next; } - if (!bytes_read) { + if(!bytes_read) { /* If the channel is already at EOF or even closed, we need to signal that back. We may have gotten that info while draining the incoming transport layer until EAGAIN so we must not be fooled by that @@ -1968,13 +2019,24 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id) { LIBSSH2_SESSION *session = channel->session; LIBSSH2_PACKET *read_packet; + LIBSSH2_PACKET *next_packet; uint32_t read_local_id; read_packet = _libssh2_list_first(&session->packets); - if (read_packet == NULL) + if(read_packet == NULL) return 0; - while (read_packet) { + while(read_packet) { + + next_packet = _libssh2_list_next(&read_packet->node); + + if(read_packet->data_len < 5) { + read_packet = next_packet; + _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR, + "Unexpected packet length"); + continue; + } + read_local_id = _libssh2_ntohu32(read_packet->data + 1); /* @@ -1984,9 +2046,10 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id) * or the standard stream with extended_data_merge * enabled and data was available */ - if ((stream_id + if((stream_id && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (channel->local.id == read_local_id) + && (read_packet->data_len >= 9) && (stream_id == (int) _libssh2_ntohu32(read_packet->data + 5))) || (!stream_id @@ -1997,11 +2060,11 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id) && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (channel->local.id == read_local_id) && (channel->remote.extended_data_ignore_mode - == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) - { + == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) { return (read_packet->data_len - read_packet->data_head); } - read_packet = _libssh2_list_next(&read_packet->node); + + read_packet = next_packet; } return 0; @@ -2035,7 +2098,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, if(buflen > 32700) buflen = 32700; - if (channel->write_state == libssh2_NB_state_idle) { + if(channel->write_state == libssh2_NB_state_idle) { unsigned char *s = channel->write_packet; _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, @@ -2043,11 +2106,11 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, (int) buflen, channel->local.id, channel->remote.id, stream_id); - if (channel->local.close) + if(channel->local.close) return _libssh2_error(channel->session, LIBSSH2_ERROR_CHANNEL_CLOSED, "We've already closed this channel"); - else if (channel->local.eof) + else if(channel->local.eof) return _libssh2_error(channel->session, LIBSSH2_ERROR_CHANNEL_EOF_SENT, "EOF has already been received, " @@ -2057,7 +2120,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, * pending window adjust packets */ do rc = _libssh2_transport_read(session); - while (rc > 0); + while(rc > 0); if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) { return _libssh2_error(channel->session, rc, @@ -2073,7 +2136,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, */ session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND; - return (rc==LIBSSH2_ERROR_EAGAIN?rc:0); + return (rc == LIBSSH2_ERROR_EAGAIN?rc:0); } channel->write_bufwrite = buflen; @@ -2081,12 +2144,12 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, *(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA; _libssh2_store_u32(&s, channel->remote.id); - if (stream_id) + if(stream_id) _libssh2_store_u32(&s, stream_id); /* Don't exceed the remote end's limits */ /* REMEMBER local means local as the SOURCE of the data */ - if (channel->write_bufwrite > channel->local.window_size) { + if(channel->write_bufwrite > channel->local.window_size) { _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Splitting write block due to %lu byte " "window_size on %lu/%lu/%d", @@ -2094,7 +2157,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, channel->remote.id, stream_id); channel->write_bufwrite = channel->local.window_size; } - if (channel->write_bufwrite > channel->local.packet_size) { + if(channel->write_bufwrite > channel->local.packet_size) { _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Splitting write block due to %lu byte " "packet_size on %lu/%lu/%d", @@ -2115,15 +2178,15 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, channel->write_state = libssh2_NB_state_created; } - if (channel->write_state == libssh2_NB_state_created) { + if(channel->write_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, channel->write_packet, channel->write_packet_len, buf, channel->write_bufwrite); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, rc, "Unable to send channel data"); } - else if (rc) { + else if(rc) { channel->write_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send channel data"); @@ -2182,17 +2245,18 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel) unsigned char packet[5]; /* packet_type(1) + channelno(4) */ int rc; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Sending EOF on channel %lu/%lu", + _libssh2_debug(session, LIBSSH2_TRACE_CONN, + "Sending EOF on channel %lu/%lu", channel->local.id, channel->remote.id); packet[0] = SSH_MSG_CHANNEL_EOF; _libssh2_htonu32(packet + 1, channel->remote.id); rc = _libssh2_transport_send(session, packet, 5, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending EOF"); return rc; } - else if (rc) { + else if(rc) { return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send EOF on channel"); } @@ -2228,6 +2292,7 @@ libssh2_channel_eof(LIBSSH2_CHANNEL * channel) { LIBSSH2_SESSION *session; LIBSSH2_PACKET *packet; + LIBSSH2_PACKET *next_packet; if(!channel) return LIBSSH2_ERROR_BAD_USE; @@ -2235,14 +2300,25 @@ libssh2_channel_eof(LIBSSH2_CHANNEL * channel) session = channel->session; packet = _libssh2_list_first(&session->packets); - while (packet) { - if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) - || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) - && (channel->local.id == _libssh2_ntohu32(packet->data + 1))) { + while(packet) { + + next_packet = _libssh2_list_next(&packet->node); + + if(packet->data_len < 1) { + packet = next_packet; + _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR, + "Unexpected packet length"); + continue; + } + + if(((packet->data[0] == SSH_MSG_CHANNEL_DATA) + || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) + && ((packet->data_len >= 5) + && (channel->local.id == _libssh2_ntohu32(packet->data + 1)))) { /* There's data waiting to be read yet, mask the EOF status */ return 0; } - packet = _libssh2_list_next(&packet->node); + packet = next_packet; } return channel->remote.eof; @@ -2258,9 +2334,9 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel) LIBSSH2_SESSION *session = channel->session; int rc; - if (channel->wait_eof_state == libssh2_NB_state_idle) { + if(channel->wait_eof_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Awaiting close of channel %lu/%lu", channel->local.id, + "Awaiting EOF for channel %lu/%lu", channel->local.id, channel->remote.id); channel->wait_eof_state = libssh2_NB_state_created; @@ -2271,19 +2347,26 @@ static int channel_wait_eof(LIBSSH2_CHANNEL *channel) * Either the EOF will be set or network timeout will occur. */ do { - if (channel->remote.eof) { + if(channel->remote.eof) { break; } + + if((channel->remote.window_size == channel->read_avail) && + session->api_block_mode) + return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_FULL, + "Receiving channel window " + "has been exhausted"); + rc = _libssh2_transport_read(session); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc < 0) { + else if(rc < 0) { channel->wait_eof_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "_libssh2_transport_read() bailed out!"); } - } while (1); + } while(1); channel->wait_eof_state = libssh2_NB_state_idle; @@ -2312,16 +2395,17 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel) LIBSSH2_SESSION *session = channel->session; int rc = 0; - if (channel->local.close) { + if(channel->local.close) { /* Already closed, act like we sent another close, * even though we didn't... shhhhhh */ channel->close_state = libssh2_NB_state_idle; return 0; } - if (!channel->local.eof) { - if ((rc = channel_send_eof(channel))) { - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(!channel->local.eof) { + rc = channel_send_eof(channel); + if(rc) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } _libssh2_error(session, rc, @@ -2332,7 +2416,7 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel) /* ignore if we have received a remote eof or not, as it is now too late for us to wait for it. Continue closing! */ - if (channel->close_state == libssh2_NB_state_idle) { + if(channel->close_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu", channel->local.id, channel->remote.id); @@ -2342,41 +2426,43 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel) channel->close_state = libssh2_NB_state_created; } - if (channel->close_state == libssh2_NB_state_created) { + if(channel->close_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, channel->close_packet, 5, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending close-channel"); return rc; - } else if (rc) { + } + else if(rc) { _libssh2_error(session, rc, "Unable to send close-channel request, " "but closing anyway"); /* skip waiting for the response and fall through to LIBSSH2_CHANNEL_CLOSE below */ - } else + } + else channel->close_state = libssh2_NB_state_sent; } - if (channel->close_state == libssh2_NB_state_sent) { + if(channel->close_state == libssh2_NB_state_sent) { /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */ - while (!channel->remote.close && !rc && + while(!channel->remote.close && !rc && (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED)) rc = _libssh2_transport_read(session); } if(rc != LIBSSH2_ERROR_EAGAIN) { - /* set the local close state first when we're perfectly confirmed to not - do any more EAGAINs */ + /* set the local close state first when we're perfectly confirmed to + not do any more EAGAINs */ channel->local.close = 1; /* We call the callback last in this function to make it keep the local data as long as EAGAIN is returned. */ - if (channel->close_cb) { + if(channel->close_cb) { LIBSSH2_CHANNEL_CLOSE(session, channel); } @@ -2384,7 +2470,7 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel) } /* return 0 or an error */ - return rc>=0?0:rc; + return rc >= 0 ? 0 : rc; } /* @@ -2414,13 +2500,13 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel) LIBSSH2_SESSION *session = channel->session; int rc; - if (!libssh2_channel_eof(channel)) { + if(!channel->remote.eof) { return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "libssh2_channel_wait_closed() invoked when " "channel is not in EOF state"); } - if (channel->wait_closed_state == libssh2_NB_state_idle) { + if(channel->wait_closed_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Awaiting close of channel %lu/%lu", channel->local.id, channel->remote.id); @@ -2432,13 +2518,13 @@ static int channel_wait_closed(LIBSSH2_CHANNEL *channel) * While channel is not closed, read more packets from the network. * Either the channel will be closed or network timeout will occur. */ - if (!channel->remote.close) { + if(!channel->remote.close) { do { rc = _libssh2_transport_read(session); - if (channel->remote.close) + if(channel->remote.close) /* it is now closed, move on! */ break; - } while (rc > 0); + } while(rc > 0); if(rc < 0) return rc; } @@ -2483,7 +2569,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) assert(session); - if (channel->free_state == libssh2_NB_state_idle) { + if(channel->free_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Freeing channel %lu/%lu resources", channel->local.id, channel->remote.id); @@ -2492,7 +2578,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) } /* Allow channel freeing even when the socket has lost its connection */ - if (!channel->local.close + if(!channel->local.close && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) { rc = _libssh2_channel_close(channel); @@ -2505,7 +2591,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) channel->free_state = libssh2_NB_state_idle; - if (channel->exit_signal) { + if(channel->exit_signal) { LIBSSH2_FREE(session, channel->exit_signal); } @@ -2517,7 +2603,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) /* Clear out packets meant for this channel */ _libssh2_htonu32(channel_id, channel->local.id); - while ((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data, + while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data, &data_len, 1, channel_id, 4) >= 0) || (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data, @@ -2526,7 +2612,7 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) } /* free "channel_type" */ - if (channel->channel_type) { + if(channel->channel_type) { LIBSSH2_FREE(session, channel->channel_type); } @@ -2536,13 +2622,13 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) /* * Make sure all memory used in the state variables are free */ - if (channel->setenv_packet) { + if(channel->setenv_packet) { LIBSSH2_FREE(session, channel->setenv_packet); } - if (channel->reqX11_packet) { + if(channel->reqX11_packet) { LIBSSH2_FREE(session, channel->reqX11_packet); } - if (channel->process_packet) { + if(channel->process_packet) { LIBSSH2_FREE(session, channel->process_packet); } @@ -2587,25 +2673,38 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, if(!channel) return 0; /* no channel, no window! */ - if (window_size_initial) { + if(window_size_initial) { *window_size_initial = channel->remote.window_size_initial; } - if (read_avail) { + if(read_avail) { size_t bytes_queued = 0; + LIBSSH2_PACKET *next_packet; LIBSSH2_PACKET *packet = _libssh2_list_first(&channel->session->packets); - while (packet) { - unsigned char packet_type = packet->data[0]; + while(packet) { + unsigned char packet_type; + next_packet = _libssh2_list_next(&packet->node); - if (((packet_type == SSH_MSG_CHANNEL_DATA) - || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) - && (_libssh2_ntohu32(packet->data + 1) == channel->local.id)) { + if(packet->data_len < 1) { + packet = next_packet; + _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR, + "Unexpected packet length"); + continue; + } + + packet_type = packet->data[0]; + + if(((packet_type == SSH_MSG_CHANNEL_DATA) + || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) + && ((packet->data_len >= 5) + && (_libssh2_ntohu32(packet->data + 1) == + channel->local.id))) { bytes_queued += packet->data_len - packet->data_head; } - packet = _libssh2_list_next(&packet->node); + packet = next_packet; } *read_avail = bytes_queued; @@ -2629,7 +2728,7 @@ libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, if(!channel) return 0; /* no channel, no window! */ - if (window_size_initial) { + if(window_size_initial) { /* For locally initiated channels this is very often 0, so it's not * *that* useful as information goes */ *window_size_initial = channel->local.window_size_initial; diff --git a/libssh2/src/comp.c b/libssh2/src/comp.c index 629319590..fec82a74b 100644 --- a/libssh2/src/comp.c +++ b/libssh2/src/comp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2004-2007, Sara Golemon +/* Copyright (c) 2004-2007, 2019, Sara Golemon * Copyright (c) 2010-2014, Daniel Stenberg * All rights reserved. * @@ -142,7 +142,7 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compr, int status; strm = LIBSSH2_CALLOC(session, sizeof(z_stream)); - if (!strm) { + if(!strm) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "zlib compression/decompression"); @@ -151,15 +151,16 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compr, strm->opaque = (voidpf) session; strm->zalloc = (alloc_func) comp_method_zlib_alloc; strm->zfree = (free_func) comp_method_zlib_free; - if (compr) { + if(compr) { /* deflate */ status = deflateInit(strm, Z_DEFAULT_COMPRESSION); - } else { + } + else { /* inflate */ status = inflateInit(strm); } - if (status != Z_OK) { + if(status != Z_OK) { LIBSSH2_FREE(session, strm); _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "unhandled zlib error %d", status); @@ -197,13 +198,14 @@ comp_method_zlib_comp(LIBSSH2_SESSION *session, status = deflate(strm, Z_PARTIAL_FLUSH); - if ((status == Z_OK) && (strm->avail_out > 0)) { + if((status == Z_OK) && (strm->avail_out > 0)) { *dest_len = out_maxlen - strm->avail_out; return 0; } _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib compression error %d, avail_out", status, strm->avail_out); + "unhandled zlib compression error %d, avail_out", + status, strm->avail_out); return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compression failure"); } @@ -225,22 +227,22 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session, reallocs */ char *out; size_t out_maxlen = src_len; - - if (src_len <= SIZE_MAX / 4) + + if(src_len <= SIZE_MAX / 4) out_maxlen = src_len * 4; else out_maxlen = payload_limit; /* If strm is null, then we have not yet been initialized. */ - if (strm == NULL) + if(strm == NULL) return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS, "decompression uninitialized");; /* In practice they never come smaller than this */ - if (out_maxlen < 25) + if(out_maxlen < 25) out_maxlen = 25; - if (out_maxlen > (int) payload_limit) + if(out_maxlen > payload_limit) out_maxlen = payload_limit; strm->next_in = (unsigned char *) src; @@ -248,26 +250,29 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session, strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen); out = (char *) strm->next_out; strm->avail_out = out_maxlen; - if (!strm->next_out) + if(!strm->next_out) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate decompression buffer"); /* Loop until it's all inflated or hit error */ - for (;;) { + for(;;) { int status; size_t out_ofs; char *newout; status = inflate(strm, Z_PARTIAL_FLUSH); - if (status == Z_OK) { - if (strm->avail_out > 0) - /* status is OK and the output buffer has not been exhausted so we're done */ + if(status == Z_OK) { + if(strm->avail_out > 0) + /* status is OK and the output buffer has not been exhausted + so we're done */ break; - } else if (status == Z_BUF_ERROR) { + } + else if(status == Z_BUF_ERROR) { /* the input data has been exhausted so we are done */ break; - } else { + } + else { /* error state */ LIBSSH2_FREE(session, out); _libssh2_debug(session, LIBSSH2_TRACE_TRANS, @@ -276,7 +281,7 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session, "decompression failure"); } - if (out_maxlen > (int) payload_limit || out_maxlen > SIZE_MAX / 2) { + if(out_maxlen > payload_limit || out_maxlen > SIZE_MAX / 2) { LIBSSH2_FREE(session, out); return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase"); @@ -286,7 +291,7 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session, out_ofs = out_maxlen - strm->avail_out; out_maxlen *= 2; newout = LIBSSH2_REALLOC(session, out, out_maxlen); - if (!newout) { + if(!newout) { LIBSSH2_FREE(session, out); return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to expand decompression buffer"); @@ -311,8 +316,8 @@ comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract) { z_stream *strm = *abstract; - if (strm) { - if (compr) + if(strm) { + if(compr) deflateEnd(strm); else inflateEnd(strm); diff --git a/libssh2/src/crypt.c b/libssh2/src/crypt.c index 931ae8b80..8d493b484 100644 --- a/libssh2/src/crypt.c +++ b/libssh2/src/crypt.c @@ -53,10 +53,11 @@ crypt_none_crypt(LIBSSH2_SESSION * session, unsigned char *buf, static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = { "none", - 8, /* blocksize (SSH2 defines minimum blocksize as 8) */ - 0, /* iv_len */ - 0, /* secret_len */ - 0, /* flags */ + "DEK-Info: NONE", + 8, /* blocksize (SSH2 defines minimum blocksize as 8) */ + 0, /* iv_len */ + 0, /* secret_len */ + 0, /* flags */ NULL, crypt_none_crypt, NULL @@ -79,12 +80,12 @@ crypt_init(LIBSSH2_SESSION * session, { struct crypt_ctx *ctx = LIBSSH2_ALLOC(session, sizeof(struct crypt_ctx)); - if (!ctx) + if(!ctx) return LIBSSH2_ERROR_ALLOC; ctx->encrypt = encrypt; ctx->algo = method->algo; - if (_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) { + if(_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) { LIBSSH2_FREE(session, ctx); return -1; } @@ -108,7 +109,7 @@ static int crypt_dtor(LIBSSH2_SESSION * session, void **abstract) { struct crypt_ctx **cctx = (struct crypt_ctx **) abstract; - if (cctx && *cctx) { + if(cctx && *cctx) { _libssh2_cipher_dtor(&(*cctx)->h); LIBSSH2_FREE(session, *cctx); *abstract = NULL; @@ -119,6 +120,7 @@ crypt_dtor(LIBSSH2_SESSION * session, void **abstract) #if LIBSSH2_AES_CTR static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = { "aes128-ctr", + "", 16, /* blocksize */ 16, /* initial value length */ 16, /* secret length -- 16*8 == 128bit */ @@ -131,6 +133,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = { static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = { "aes192-ctr", + "", 16, /* blocksize */ 16, /* initial value length */ 24, /* secret length -- 24*8 == 192bit */ @@ -143,6 +146,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = { static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = { "aes256-ctr", + "", 16, /* blocksize */ 16, /* initial value length */ 32, /* secret length -- 32*8 == 256bit */ @@ -157,6 +161,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = { #if LIBSSH2_AES static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = { "aes128-cbc", + "DEK-Info: AES-128-CBC", 16, /* blocksize */ 16, /* initial value length */ 16, /* secret length -- 16*8 == 128bit */ @@ -169,6 +174,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = { static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = { "aes192-cbc", + "DEK-Info: AES-192-CBC", 16, /* blocksize */ 16, /* initial value length */ 24, /* secret length -- 24*8 == 192bit */ @@ -181,6 +187,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = { static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = { "aes256-cbc", + "DEK-Info: AES-256-CBC", 16, /* blocksize */ 16, /* initial value length */ 32, /* secret length -- 32*8 == 256bit */ @@ -195,6 +202,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = { static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_rijndael_cbc_lysator_liu_se = { "rijndael-cbc@lysator.liu.se", + "DEK-Info: AES-256-CBC", 16, /* blocksize */ 16, /* initial value length */ 32, /* secret length -- 32*8 == 256bit */ @@ -209,6 +217,7 @@ static const LIBSSH2_CRYPT_METHOD #if LIBSSH2_BLOWFISH static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = { "blowfish-cbc", + "", 8, /* blocksize */ 8, /* initial value length */ 16, /* secret length */ @@ -223,6 +232,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = { #if LIBSSH2_RC4 static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = { "arcfour", + "DEK-Info: RC4", 8, /* blocksize */ 8, /* initial value length */ 16, /* secret length */ @@ -242,13 +252,13 @@ crypt_init_arcfour128(LIBSSH2_SESSION * session, { int rc; - rc = crypt_init (session, method, iv, free_iv, secret, free_secret, - encrypt, abstract); - if (rc == 0) { + rc = crypt_init(session, method, iv, free_iv, secret, free_secret, + encrypt, abstract); + if(rc == 0) { struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract; unsigned char block[8]; size_t discard = 1536; - for (; discard; discard -= 8) + for(; discard; discard -= 8) _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block, method->blocksize); } @@ -258,6 +268,7 @@ crypt_init_arcfour128(LIBSSH2_SESSION * session, static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = { "arcfour128", + "", 8, /* blocksize */ 8, /* initial value length */ 16, /* secret length */ @@ -272,6 +283,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = { #if LIBSSH2_CAST static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = { "cast128-cbc", + "", 8, /* blocksize */ 8, /* initial value length */ 16, /* secret length */ @@ -286,6 +298,7 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = { #if LIBSSH2_3DES static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = { "3des-cbc", + "DEK-Info: DES-EDE3-CBC", 8, /* blocksize */ 8, /* initial value length */ 24, /* secret length */ diff --git a/libssh2/src/crypto.h b/libssh2/src/crypto.h index aa997a307..8b1e00402 100644 --- a/libssh2/src/crypto.h +++ b/libssh2/src/crypto.h @@ -1,6 +1,6 @@ /* Copyright (C) 2009, 2010 Simon Josefsson * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2010 Daniel Stenberg + * Copyright (C) 2010-2019 Daniel Stenberg * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided @@ -58,6 +58,11 @@ #include "mbedtls.h" #endif +#define LIBSSH2_ED25519_KEY_LEN 32 +#define LIBSSH2_ED25519_PRIVATE_KEY_LEN 64 +#define LIBSSH2_ED25519_SIG_LEN 64 + +#if LIBSSH2_RSA int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, const unsigned char *edata, unsigned long elen, @@ -90,8 +95,10 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, size_t *signature_len); int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa, LIBSSH2_SESSION * session, - const char *filedata, size_t filedata_len, + const char *filedata, + size_t filedata_len, unsigned const char *passphrase); +#endif #if LIBSSH2_DSA int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa, @@ -116,10 +123,102 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, unsigned long hash_len, unsigned char *sig); int _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa, LIBSSH2_SESSION * session, - const char *filedata, size_t filedata_len, + const char *filedata, + size_t filedata_len, unsigned const char *passphrase); #endif +#if LIBSSH2_ECDSA +int +_libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ecdsactx, + const unsigned char *k, + size_t k_len, + libssh2_curve_type type); +int +_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx, + LIBSSH2_SESSION * session, + const char *filename, + unsigned const char *passphrase); + +int +_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, + const unsigned char *r, size_t r_len, + const unsigned char *s, size_t s_len, + const unsigned char *m, size_t m_len); + +int +_libssh2_ecdsa_create_key(LIBSSH2_SESSION *session, + _libssh2_ec_key **out_private_key, + unsigned char **out_public_key_octal, + size_t *out_public_key_octal_len, + libssh2_curve_type curve_type); + +int +_libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key, + const unsigned char *server_public_key, + size_t server_public_key_len); + +int +_libssh2_ecdsa_sign(LIBSSH2_SESSION *session, libssh2_ecdsa_ctx *ec_ctx, + const unsigned char *hash, unsigned long hash_len, + unsigned char **signature, size_t *signature_len); + +int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, + LIBSSH2_SESSION * session, + const char *filedata, + size_t filedata_len, + unsigned const char *passphrase); + +libssh2_curve_type +_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key); + +int +_libssh2_ecdsa_curve_type_from_name(const char *name, + libssh2_curve_type *out_type); + +#endif /* LIBSSH2_ECDSA */ + +#if LIBSSH2_ED25519 + +int +_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_ed25519_ctx **ctx, + uint8_t **out_public_key, uint8_t **out_private_key); + +int +_libssh2_curve25519_gen_k(_libssh2_bn **k, + uint8_t private_key[LIBSSH2_ED25519_KEY_LEN], + uint8_t server_public_key[LIBSSH2_ED25519_KEY_LEN]); + +int +_libssh2_ed25519_verify(libssh2_ed25519_ctx *ctx, const uint8_t *s, + size_t s_len, const uint8_t *m, size_t m_len); + +int +_libssh2_ed25519_new_private(libssh2_ed25519_ctx **ed_ctx, + LIBSSH2_SESSION *session, + const char *filename, const uint8_t *passphrase); + +int +_libssh2_ed25519_new_public(libssh2_ed25519_ctx **ed_ctx, + LIBSSH2_SESSION *session, + const unsigned char *raw_pub_key, + const uint8_t key_len); + +int +_libssh2_ed25519_sign(libssh2_ed25519_ctx *ctx, LIBSSH2_SESSION *session, + uint8_t **out_sig, size_t *out_sig_len, + const uint8_t *message, size_t message_len); + +int +_libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx **ed_ctx, + LIBSSH2_SESSION *session, + const char *filedata, + size_t filedata_len, + unsigned const char *passphrase); + +#endif /* LIBSSH2_ED25519 */ + + int _libssh2_cipher_init(_libssh2_cipher_ctx * h, _libssh2_cipher_type(algo), unsigned char *iv, @@ -136,6 +235,7 @@ int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, size_t *pubkeydata_len, const char *privatekey, const char *passphrase); + int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, unsigned char **method, size_t *method_len, @@ -145,6 +245,4 @@ int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, size_t privatekeydata_len, const char *passphrase); -void _libssh2_init_aes_ctr(void); - #endif diff --git a/libssh2/src/global.c b/libssh2/src/global.c index dc45e7003..f88eb33da 100644 --- a/libssh2/src/global.c +++ b/libssh2/src/global.c @@ -44,9 +44,8 @@ static int _libssh2_init_flags = 0; LIBSSH2_API int libssh2_init(int flags) { - if (_libssh2_initialized == 0 && !(flags & LIBSSH2_INIT_NO_CRYPTO)) { + if(_libssh2_initialized == 0 && !(flags & LIBSSH2_INIT_NO_CRYPTO)) { libssh2_crypto_init(); - _libssh2_init_aes_ctr(); } _libssh2_initialized++; @@ -58,12 +57,12 @@ libssh2_init(int flags) LIBSSH2_API void libssh2_exit(void) { - if (_libssh2_initialized == 0) + if(_libssh2_initialized == 0) return; _libssh2_initialized--; - if (!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) { + if(!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) { libssh2_crypto_exit(); } @@ -73,6 +72,6 @@ libssh2_exit(void) void _libssh2_init_if_needed(void) { - if (_libssh2_initialized == 0) + if(_libssh2_initialized == 0) (void)libssh2_init (0); } diff --git a/libssh2/src/hostkey.c b/libssh2/src/hostkey.c index 2a0a8f943..a8bd42b7a 100644 --- a/libssh2/src/hostkey.c +++ b/libssh2/src/hostkey.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Sara Golemon - * Copyright (c) 2009-2014 by Daniel Stenberg + * Copyright (c) 2009-2019 by Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -64,38 +64,36 @@ hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session, void **abstract) { libssh2_rsa_ctx *rsactx; - const unsigned char *s, *e, *n; - unsigned long len, e_len, n_len; - int ret; + unsigned char *e, *n; + size_t e_len, n_len; + struct string_buf buf; - (void) hostkey_data_len; - - if (*abstract) { + if(*abstract) { hostkey_method_ssh_rsa_dtor(session, abstract); *abstract = NULL; } - s = hostkey_data; - len = _libssh2_ntohu32(s); - s += 4; - - if (len != 7 || strncmp((char *) s, "ssh-rsa", 7) != 0) { + if(hostkey_data_len < 19) { + _libssh2_debug(session, LIBSSH2_TRACE_ERROR, + "host key length too short"); return -1; } - s += 7; - e_len = _libssh2_ntohu32(s); - s += 4; + buf.data = (unsigned char *)hostkey_data; + buf.dataptr = buf.data; + buf.len = hostkey_data_len; - e = s; - s += e_len; - n_len = _libssh2_ntohu32(s); - s += 4; - n = s; + if(_libssh2_match_string(&buf, "ssh-rsa")) + return -1; - ret = _libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0); - if (ret) { + if(_libssh2_get_string(&buf, &e, &e_len)) + return -1; + + if(_libssh2_get_string(&buf, &n, &n_len)) + return -1; + + if(_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0)) { return -1; } @@ -118,13 +116,13 @@ hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session, libssh2_rsa_ctx *rsactx; int ret; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_rsa_dtor(session, abstract); *abstract = NULL; } ret = _libssh2_rsa_new_private(&rsactx, session, privkeyfile, passphrase); - if (ret) { + if(ret) { return -1; } @@ -148,7 +146,7 @@ hostkey_method_ssh_rsa_initPEMFromMemory(LIBSSH2_SESSION * session, libssh2_rsa_ctx *rsactx; int ret; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_rsa_dtor(session, abstract); *abstract = NULL; } @@ -156,7 +154,7 @@ hostkey_method_ssh_rsa_initPEMFromMemory(LIBSSH2_SESSION * session, ret = _libssh2_rsa_new_private_frommemory(&rsactx, session, privkeyfiledata, privkeyfiledata_len, passphrase); - if (ret) { + if(ret) { return -1; } @@ -181,6 +179,9 @@ hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session, (void) session; /* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */ + if(sig_len < 15) + return -1; + sig += 15; sig_len -= 15; return _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len); @@ -218,7 +219,7 @@ hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session, ret = _libssh2_rsa_sha1_sign(session, rsactx, hash, SHA_DIGEST_LENGTH, signature, signature_len); - if (ret) { + if(ret) { return -1; } @@ -281,45 +282,42 @@ hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session, void **abstract) { libssh2_dsa_ctx *dsactx; - const unsigned char *p, *q, *g, *y, *s; - unsigned long p_len, q_len, g_len, y_len, len; - int ret; + unsigned char *p, *q, *g, *y; + size_t p_len, q_len, g_len, y_len; + struct string_buf buf; - (void) hostkey_data_len; - - if (*abstract) { + if(*abstract) { hostkey_method_ssh_dss_dtor(session, abstract); *abstract = NULL; } - s = hostkey_data; - len = _libssh2_ntohu32(s); - s += 4; - if (len != 7 || strncmp((char *) s, "ssh-dss", 7) != 0) { + if(hostkey_data_len < 27) { + _libssh2_debug(session, LIBSSH2_TRACE_ERROR, + "host key length too short"); return -1; } - s += 7; - p_len = _libssh2_ntohu32(s); - s += 4; - p = s; - s += p_len; - q_len = _libssh2_ntohu32(s); - s += 4; - q = s; - s += q_len; - g_len = _libssh2_ntohu32(s); - s += 4; - g = s; - s += g_len; - y_len = _libssh2_ntohu32(s); - s += 4; - y = s; - /* s += y_len; */ + buf.data = (unsigned char *)hostkey_data; + buf.dataptr = buf.data; + buf.len = hostkey_data_len; - ret = _libssh2_dsa_new(&dsactx, p, p_len, q, q_len, - g, g_len, y, y_len, NULL, 0); - if (ret) { + if(_libssh2_match_string(&buf, "ssh-dss")) + return -1; + + if(_libssh2_get_string(&buf, &p, &p_len)) + return -1; + + if(_libssh2_get_string(&buf, &q, &q_len)) + return -1; + + if(_libssh2_get_string(&buf, &g, &g_len)) + return -1; + + if(_libssh2_get_string(&buf, &y, &y_len)) + return -1; + + if(_libssh2_dsa_new(&dsactx, p, p_len, q, q_len, + g, g_len, y, y_len, NULL, 0)) { return -1; } @@ -342,13 +340,13 @@ hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session, libssh2_dsa_ctx *dsactx; int ret; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_dss_dtor(session, abstract); *abstract = NULL; } ret = _libssh2_dsa_new_private(&dsactx, session, privkeyfile, passphrase); - if (ret) { + if(ret) { return -1; } @@ -372,7 +370,7 @@ hostkey_method_ssh_dss_initPEMFromMemory(LIBSSH2_SESSION * session, libssh2_dsa_ctx *dsactx; int ret; - if (*abstract) { + if(*abstract) { hostkey_method_ssh_dss_dtor(session, abstract); *abstract = NULL; } @@ -380,7 +378,7 @@ hostkey_method_ssh_dss_initPEMFromMemory(LIBSSH2_SESSION * session, ret = _libssh2_dsa_new_private_frommemory(&dsactx, session, privkeyfiledata, privkeyfiledata_len, passphrase); - if (ret) { + if(ret) { return -1; } @@ -404,12 +402,14 @@ hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session, libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract); /* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */ - sig += 15; - sig_len -= 15; - if (sig_len != 40) { + if(sig_len != 55) { return _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Invalid DSS signature length"); } + + sig += 15; + sig_len -= 15; + return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len); } @@ -432,7 +432,7 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, int i; *signature = LIBSSH2_CALLOC(session, 2 * SHA_DIGEST_LENGTH); - if (!*signature) { + if(!*signature) { return -1; } @@ -444,7 +444,7 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, } libssh2_sha1_final(ctx, hash); - if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) { + if(_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) { LIBSSH2_FREE(session, *signature); return -1; } @@ -483,7 +483,526 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_dss = { }; #endif /* LIBSSH2_DSA */ +#if LIBSSH2_ECDSA + +/* *********** + * ecdsa-sha2-nistp256/384/521 * + *********** */ + +static int +hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session, + void **abstract); + +/* + * hostkey_method_ssh_ecdsa_init + * + * Initialize the server hostkey working area with e/n pair + */ +static int +hostkey_method_ssh_ecdsa_init(LIBSSH2_SESSION * session, + const unsigned char *hostkey_data, + size_t hostkey_data_len, + void **abstract) +{ + libssh2_ecdsa_ctx *ecdsactx = NULL; + unsigned char *type_str, *domain, *public_key; + size_t key_len, len; + libssh2_curve_type type; + struct string_buf buf; + + if(abstract != NULL && *abstract) { + hostkey_method_ssh_ecdsa_dtor(session, abstract); + *abstract = NULL; + } + + if(hostkey_data_len < 39) { + _libssh2_debug(session, LIBSSH2_TRACE_ERROR, + "host key length too short"); + return -1; + } + + buf.data = (unsigned char *)hostkey_data; + buf.dataptr = buf.data; + buf.len = hostkey_data_len; + + if(_libssh2_get_string(&buf, &type_str, &len) || len != 19) + return -1; + + if(strncmp((char *) type_str, "ecdsa-sha2-nistp256", 19) == 0) { + type = LIBSSH2_EC_CURVE_NISTP256; + } + else if(strncmp((char *) type_str, "ecdsa-sha2-nistp384", 19) == 0) { + type = LIBSSH2_EC_CURVE_NISTP384; + } + else if(strncmp((char *) type_str, "ecdsa-sha2-nistp521", 19) == 0) { + type = LIBSSH2_EC_CURVE_NISTP521; + } + else { + return -1; + } + + if(_libssh2_get_string(&buf, &domain, &len) || len != 8) + return -1; + + if(type == LIBSSH2_EC_CURVE_NISTP256 && + strncmp((char *)domain, "nistp256", 8) != 0) { + return -1; + } + else if(type == LIBSSH2_EC_CURVE_NISTP384 && + strncmp((char *)domain, "nistp384", 8) != 0) { + return -1; + } + else if(type == LIBSSH2_EC_CURVE_NISTP521 && + strncmp((char *)domain, "nistp521", 8) != 0) { + return -1; + } + + /* public key */ + if(_libssh2_get_string(&buf, &public_key, &key_len)) + return -1; + + if(_libssh2_ecdsa_curve_name_with_octal_new(&ecdsactx, public_key, + key_len, type)) + return -1; + + if(abstract != NULL) + *abstract = ecdsactx; + + return 0; +} + +/* + * hostkey_method_ssh_ecdsa_initPEM + * + * Load a Private Key from a PEM file + */ +static int +hostkey_method_ssh_ecdsa_initPEM(LIBSSH2_SESSION * session, + const char *privkeyfile, + unsigned const char *passphrase, + void **abstract) +{ + libssh2_ecdsa_ctx *ec_ctx = NULL; + int ret; + + if(abstract != NULL && *abstract) { + hostkey_method_ssh_ecdsa_dtor(session, abstract); + *abstract = NULL; + } + + ret = _libssh2_ecdsa_new_private(&ec_ctx, session, + privkeyfile, passphrase); + + if(abstract != NULL) + *abstract = ec_ctx; + + return ret; +} + +/* + * hostkey_method_ssh_ecdsa_initPEMFromMemory + * + * Load a Private Key from memory + */ +static int +hostkey_method_ssh_ecdsa_initPEMFromMemory(LIBSSH2_SESSION * session, + const char *privkeyfiledata, + size_t privkeyfiledata_len, + unsigned const char *passphrase, + void **abstract) +{ + libssh2_ecdsa_ctx *ec_ctx = NULL; + int ret; + + if(abstract != NULL && *abstract) { + hostkey_method_ssh_ecdsa_dtor(session, abstract); + *abstract = NULL; + } + + ret = _libssh2_ecdsa_new_private_frommemory(&ec_ctx, session, + privkeyfiledata, + privkeyfiledata_len, + passphrase); + if(ret) { + return -1; + } + + if(abstract != NULL) + *abstract = ec_ctx; + + return 0; +} + +/* + * hostkey_method_ecdsa_sig_verify + * + * Verify signature created by remote + */ +static int +hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session, + const unsigned char *sig, + size_t sig_len, + const unsigned char *m, + size_t m_len, void **abstract) +{ + unsigned char *r, *s, *name; + size_t r_len, s_len, name_len; + unsigned int len; + struct string_buf buf; + libssh2_ecdsa_ctx *ctx = (libssh2_ecdsa_ctx *) (*abstract); + + (void) session; + + if(sig_len < 35) + return -1; + + /* keyname_len(4) + keyname(19){"ecdsa-sha2-nistp256"} + + signature_len(4) */ + buf.data = (unsigned char *)sig; + buf.dataptr = buf.data; + buf.len = sig_len; + + if(_libssh2_get_string(&buf, &name, &name_len) || name_len != 19) + return -1; + + if(_libssh2_get_u32(&buf, &len) != 0 || len < 8) + return -1; + + if(_libssh2_get_string(&buf, &r, &r_len)) + return -1; + + if(_libssh2_get_string(&buf, &s, &s_len)) + return -1; + + return _libssh2_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len); +} + + +#define LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(digest_type) \ + { \ + unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ + libssh2_sha##digest_type##_ctx ctx; \ + int i; \ + libssh2_sha##digest_type##_init(&ctx); \ + for(i = 0; i < veccount; i++) { \ + libssh2_sha##digest_type##_update(ctx, datavec[i].iov_base, \ + datavec[i].iov_len); \ + } \ + libssh2_sha##digest_type##_final(ctx, hash); \ + ret = _libssh2_ecdsa_sign(session, ec_ctx, hash, \ + SHA##digest_type##_DIGEST_LENGTH, \ + signature, signature_len); \ + } + + +/* + * hostkey_method_ecdsa_signv + * + * Construct a signature from an array of vectors + */ +static int +hostkey_method_ssh_ecdsa_signv(LIBSSH2_SESSION * session, + unsigned char **signature, + size_t *signature_len, + int veccount, + const struct iovec datavec[], + void **abstract) +{ + libssh2_ecdsa_ctx *ec_ctx = (libssh2_ecdsa_ctx *) (*abstract); + libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_ctx); + int ret = 0; + + if(type == LIBSSH2_EC_CURVE_NISTP256) { + LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(256); + } + else if(type == LIBSSH2_EC_CURVE_NISTP384) { + LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(384); + } + else if(type == LIBSSH2_EC_CURVE_NISTP521) { + LIBSSH2_HOSTKEY_METHOD_EC_SIGNV_HASH(512); + } + else { + return -1; + } + + return ret; +} + +/* + * hostkey_method_ssh_ecdsa_dtor + * + * Shutdown the hostkey by freeing EC_KEY context + */ +static int +hostkey_method_ssh_ecdsa_dtor(LIBSSH2_SESSION * session, void **abstract) +{ + libssh2_ecdsa_ctx *keyctx = (libssh2_ecdsa_ctx *) (*abstract); + (void) session; + + if(keyctx != NULL) + _libssh2_ecdsa_free(keyctx); + + *abstract = NULL; + + return 0; +} + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp256 = { + "ecdsa-sha2-nistp256", + SHA256_DIGEST_LENGTH, + hostkey_method_ssh_ecdsa_init, + hostkey_method_ssh_ecdsa_initPEM, + hostkey_method_ssh_ecdsa_initPEMFromMemory, + hostkey_method_ssh_ecdsa_sig_verify, + hostkey_method_ssh_ecdsa_signv, + NULL, /* encrypt */ + hostkey_method_ssh_ecdsa_dtor, +}; + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp384 = { + "ecdsa-sha2-nistp384", + SHA384_DIGEST_LENGTH, + hostkey_method_ssh_ecdsa_init, + hostkey_method_ssh_ecdsa_initPEM, + hostkey_method_ssh_ecdsa_initPEMFromMemory, + hostkey_method_ssh_ecdsa_sig_verify, + hostkey_method_ssh_ecdsa_signv, + NULL, /* encrypt */ + hostkey_method_ssh_ecdsa_dtor, +}; + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521 = { + "ecdsa-sha2-nistp521", + SHA512_DIGEST_LENGTH, + hostkey_method_ssh_ecdsa_init, + hostkey_method_ssh_ecdsa_initPEM, + hostkey_method_ssh_ecdsa_initPEMFromMemory, + hostkey_method_ssh_ecdsa_sig_verify, + hostkey_method_ssh_ecdsa_signv, + NULL, /* encrypt */ + hostkey_method_ssh_ecdsa_dtor, +}; + +#endif /* LIBSSH2_ECDSA */ + +#if LIBSSH2_ED25519 + +/* *********** + * ed25519 * + *********** */ + +static int hostkey_method_ssh_ed25519_dtor(LIBSSH2_SESSION * session, + void **abstract); + +/* + * hostkey_method_ssh_ed25519_init + * + * Initialize the server hostkey working area with e/n pair + */ +static int +hostkey_method_ssh_ed25519_init(LIBSSH2_SESSION * session, + const unsigned char *hostkey_data, + size_t hostkey_data_len, + void **abstract) +{ + const unsigned char *s; + unsigned long len, key_len; + libssh2_ed25519_ctx *ctx = NULL; + + if(*abstract) { + hostkey_method_ssh_ed25519_dtor(session, abstract); + *abstract = NULL; + } + + if(hostkey_data_len < 19) { + _libssh2_debug(session, LIBSSH2_TRACE_ERROR, + "host key length too short"); + return -1; + } + + s = hostkey_data; + len = _libssh2_ntohu32(s); + s += 4; + + if(len != 11 || strncmp((char *) s, "ssh-ed25519", 11) != 0) { + return -1; + } + + s += 11; + + /* public key */ + key_len = _libssh2_ntohu32(s); + s += 4; + + if(_libssh2_ed25519_new_public(&ctx, session, s, key_len) != 0) { + return -1; + } + + *abstract = ctx; + + return 0; +} + +/* + * hostkey_method_ssh_ed25519_initPEM + * + * Load a Private Key from a PEM file + */ +static int +hostkey_method_ssh_ed25519_initPEM(LIBSSH2_SESSION * session, + const char *privkeyfile, + unsigned const char *passphrase, + void **abstract) +{ + libssh2_ed25519_ctx *ec_ctx = NULL; + int ret; + + if(*abstract) { + hostkey_method_ssh_ed25519_dtor(session, abstract); + *abstract = NULL; + } + + ret = _libssh2_ed25519_new_private(&ec_ctx, session, + privkeyfile, passphrase); + if(ret) { + return -1; + } + + *abstract = ec_ctx; + + return ret; +} + +/* + * hostkey_method_ssh_ed25519_initPEMFromMemory + * + * Load a Private Key from memory + */ +static int +hostkey_method_ssh_ed25519_initPEMFromMemory(LIBSSH2_SESSION * session, + const char *privkeyfiledata, + size_t privkeyfiledata_len, + unsigned const char *passphrase, + void **abstract) +{ + libssh2_ed25519_ctx *ed_ctx = NULL; + int ret; + + if(abstract != NULL && *abstract) { + hostkey_method_ssh_ed25519_dtor(session, abstract); + *abstract = NULL; + } + + ret = _libssh2_ed25519_new_private_frommemory(&ed_ctx, session, + privkeyfiledata, + privkeyfiledata_len, + passphrase); + if(ret) { + return -1; + } + + if(abstract != NULL) + *abstract = ed_ctx; + + return 0; +} + +/* + * hostkey_method_ssh_ed25519_sig_verify + * + * Verify signature created by remote + */ +static int +hostkey_method_ssh_ed25519_sig_verify(LIBSSH2_SESSION * session, + const unsigned char *sig, + size_t sig_len, + const unsigned char *m, + size_t m_len, void **abstract) +{ + libssh2_ed25519_ctx *ctx = (libssh2_ed25519_ctx *) (*abstract); + (void) session; + + if(sig_len < 19) + return -1; + + /* Skip past keyname_len(4) + keyname(11){"ssh-ed25519"} + + signature_len(4) */ + sig += 19; + sig_len -= 19; + + if(sig_len != LIBSSH2_ED25519_SIG_LEN) + return -1; + + return _libssh2_ed25519_verify(ctx, sig, sig_len, m, m_len); +} + +/* + * hostkey_method_ssh_ed25519_signv + * + * Construct a signature from an array of vectors + */ +static int +hostkey_method_ssh_ed25519_signv(LIBSSH2_SESSION * session, + unsigned char **signature, + size_t *signature_len, + int veccount, + const struct iovec datavec[], + void **abstract) +{ + libssh2_ed25519_ctx *ctx = (libssh2_ed25519_ctx *) (*abstract); + + if(veccount != 1) { + return -1; + } + + return _libssh2_ed25519_sign(ctx, session, signature, signature_len, + datavec[0].iov_base, datavec[0].iov_len); +} + + +/* + * hostkey_method_ssh_ed25519_dtor + * + * Shutdown the hostkey by freeing key context + */ +static int +hostkey_method_ssh_ed25519_dtor(LIBSSH2_SESSION * session, void **abstract) +{ + libssh2_ed25519_ctx *keyctx = (libssh2_ed25519_ctx*) (*abstract); + (void) session; + + if(keyctx) + _libssh2_ed25519_free(keyctx); + + *abstract = NULL; + + return 0; +} + +static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_ed25519 = { + "ssh-ed25519", + SHA256_DIGEST_LENGTH, + hostkey_method_ssh_ed25519_init, + hostkey_method_ssh_ed25519_initPEM, + hostkey_method_ssh_ed25519_initPEMFromMemory, + hostkey_method_ssh_ed25519_sig_verify, + hostkey_method_ssh_ed25519_signv, + NULL, /* encrypt */ + hostkey_method_ssh_ed25519_dtor, +}; + +#endif /*LIBSSH2_ED25519*/ + + static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = { +#if LIBSSH2_ECDSA + &hostkey_method_ecdsa_ssh_nistp256, + &hostkey_method_ecdsa_ssh_nistp384, + &hostkey_method_ecdsa_ssh_nistp521, +#endif +#if LIBSSH2_ED25519 + &hostkey_method_ssh_ed25519, +#endif #if LIBSSH2_RSA &hostkey_method_ssh_rsa, #endif /* LIBSSH2_RSA */ @@ -505,12 +1024,12 @@ libssh2_hostkey_methods(void) * Returns hash signature * Returned buffer should NOT be freed * Length of buffer is determined by hash type - * i.e. MD5 == 16, SHA1 == 20 + * i.e. MD5 == 16, SHA1 == 20, SHA256 == 32 */ LIBSSH2_API const char * libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) { - switch (hash_type) { + switch(hash_type) { #if LIBSSH2_MD5 case LIBSSH2_HOSTKEY_HASH_MD5: return (session->server_hostkey_md5_valid) @@ -523,6 +1042,11 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) ? (char *) session->server_hostkey_sha1 : NULL; break; + case LIBSSH2_HOSTKEY_HASH_SHA256: + return (session->server_hostkey_sha256_valid) + ? (char *) session->server_hostkey_sha256 + : NULL; + break; default: return NULL; } @@ -530,22 +1054,55 @@ libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type) static int hostkey_type(const unsigned char *hostkey, size_t len) { - const unsigned char rsa[] = { + static const unsigned char rsa[] = { 0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a' }; - const unsigned char dss[] = { + static const unsigned char dss[] = { 0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's' }; + static const unsigned char ecdsa_256[] = { + 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', + 'n', 'i', 's', 't', 'p', '2', '5', '6' + }; + static const unsigned char ecdsa_384[] = { + 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', + 'n', 'i', 's', 't', 'p', '3', '8', '4' + }; + static const unsigned char ecdsa_521[] = { + 0, 0, 0, 0x13, 'e', 'c', 'd', 's', 'a', '-', 's', 'h', 'a', '2', '-', + 'n', 'i', 's', 't', 'p', '5', '2', '1' + }; + static const unsigned char ed25519[] = { + 0, 0, 0, 0x0b, 's', 's', 'h', '-', 'e', 'd', '2', '5', '5', '1', '9' + }; - if (len < 11) + if(len < 11) return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; - if (!memcmp(rsa, hostkey, 11)) + if(!memcmp(rsa, hostkey, 11)) return LIBSSH2_HOSTKEY_TYPE_RSA; - if (!memcmp(dss, hostkey, 11)) + if(!memcmp(dss, hostkey, 11)) return LIBSSH2_HOSTKEY_TYPE_DSS; + if(len < 15) + return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; + + if(!memcmp(ed25519, hostkey, 15)) + return LIBSSH2_HOSTKEY_TYPE_ED25519; + + if(len < 23) + return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; + + if(!memcmp(ecdsa_256, hostkey, 23)) + return LIBSSH2_HOSTKEY_TYPE_ECDSA_256; + + if(!memcmp(ecdsa_384, hostkey, 23)) + return LIBSSH2_HOSTKEY_TYPE_ECDSA_384; + + if(!memcmp(ecdsa_521, hostkey, 23)) + return LIBSSH2_HOSTKEY_TYPE_ECDSA_521; + return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; } @@ -561,7 +1118,7 @@ libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type) if(session->server_hostkey_len) { if(len) *len = session->server_hostkey_len; - if (type) + if(type) *type = hostkey_type(session->server_hostkey, session->server_hostkey_len); return (char *) session->server_hostkey; @@ -570,4 +1127,3 @@ libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type) *len = 0; return NULL; } - diff --git a/libssh2/src/keepalive.c b/libssh2/src/keepalive.c index fd749dd29..2151b1710 100644 --- a/libssh2/src/keepalive.c +++ b/libssh2/src/keepalive.c @@ -46,7 +46,7 @@ libssh2_keepalive_config (LIBSSH2_SESSION *session, int want_reply, unsigned interval) { - if (interval == 1) + if(interval == 1) session->keepalive_interval = 2; else session->keepalive_interval = interval; @@ -59,20 +59,20 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session, { time_t now; - if (!session->keepalive_interval) { - if (seconds_to_next) + if(!session->keepalive_interval) { + if(seconds_to_next) *seconds_to_next = 0; return 0; } - now = time (NULL); + now = time(NULL); - if (session->keepalive_last_sent + session->keepalive_interval <= now) { + if(session->keepalive_last_sent + session->keepalive_interval <= now) { /* Format is "SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */ unsigned char keepalive_data[] = "\x50\x00\x00\x00\x15keepalive@libssh2.orgW"; - size_t len = sizeof (keepalive_data) - 1; + size_t len = sizeof(keepalive_data) - 1; int rc; keepalive_data[len - 1] = @@ -81,16 +81,17 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session, rc = _libssh2_transport_send(session, keepalive_data, len, NULL, 0); /* Silently ignore PACKET_EAGAIN here: if the write buffer is already full, sending another keepalive is not useful. */ - if (rc && rc != LIBSSH2_ERROR_EAGAIN) { + if(rc && rc != LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send keepalive message"); return rc; } session->keepalive_last_sent = now; - if (seconds_to_next) + if(seconds_to_next) *seconds_to_next = session->keepalive_interval; - } else if (seconds_to_next) { + } + else if(seconds_to_next) { *seconds_to_next = (int) (session->keepalive_last_sent - now) + session->keepalive_interval; } diff --git a/libssh2/src/kex.c b/libssh2/src/kex.c index 3634cb5a9..cb1663937 100644 --- a/libssh2/src/kex.c +++ b/libssh2/src/kex.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010, Daniel Stenberg + * Copyright (c) 2010-2019, Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -43,24 +43,26 @@ #include "mac.h" /* TODO: Switch this to an inline and handle alloc() failures */ -/* Helper macro called from kex_method_diffie_hellman_group1_sha1_key_exchange */ +/* Helper macro called from + kex_method_diffie_hellman_group1_sha1_key_exchange */ #define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \ { \ libssh2_sha1_ctx hash; \ unsigned long len = 0; \ - if (!(value)) { \ + if(!(value)) { \ value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \ } \ - if (value) \ - while (len < (unsigned long)reqlen) { \ + if(value) \ + while(len < (unsigned long)reqlen) { \ libssh2_sha1_init(&hash); \ libssh2_sha1_update(hash, exchange_state->k_value, \ exchange_state->k_value_len); \ libssh2_sha1_update(hash, exchange_state->h_sig_comp, \ SHA_DIGEST_LENGTH); \ - if (len > 0) { \ + if(len > 0) { \ libssh2_sha1_update(hash, value, len); \ - } else { \ + } \ + else { \ libssh2_sha1_update(hash, (version), 1); \ libssh2_sha1_update(hash, session->session_id, \ session->session_id_len); \ @@ -68,35 +70,53 @@ libssh2_sha1_final(hash, (value) + len); \ len += SHA_DIGEST_LENGTH; \ } \ - } + } \ -/* Helper macro called from kex_method_diffie_hellman_group1_sha256_key_exchange */ -#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(value, reqlen, version) \ - { \ - libssh2_sha256_ctx hash; \ - unsigned long len = 0; \ - if (!(value)) { \ - value = LIBSSH2_ALLOC(session, reqlen + SHA256_DIGEST_LENGTH); \ - } \ - if (value) \ - while (len < (unsigned long)reqlen) { \ - libssh2_sha256_init(&hash); \ - libssh2_sha256_update(hash, exchange_state->k_value, \ - exchange_state->k_value_len); \ - libssh2_sha256_update(hash, exchange_state->h_sig_comp, \ - SHA256_DIGEST_LENGTH); \ - if (len > 0) { \ - libssh2_sha256_update(hash, value, len); \ - } else { \ - libssh2_sha256_update(hash, (version), 1); \ - libssh2_sha256_update(hash, session->session_id, \ - session->session_id_len); \ - } \ - libssh2_sha256_final(hash, (value) + len); \ - len += SHA256_DIGEST_LENGTH; \ - } \ - } +#define LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(value, reqlen, version) \ + { \ + if(type == LIBSSH2_EC_CURVE_NISTP256) { \ + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, value, reqlen, version); \ + } \ + else if(type == LIBSSH2_EC_CURVE_NISTP384) { \ + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(384, value, reqlen, version); \ + } \ + else if(type == LIBSSH2_EC_CURVE_NISTP521) { \ + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, value, reqlen, version); \ + } \ + } \ + + +#define LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(digest_type, value, \ + reqlen, version) \ +{ \ + libssh2_sha##digest_type##_ctx hash; \ + unsigned long len = 0; \ + if(!(value)) { \ + value = LIBSSH2_ALLOC(session, \ + reqlen + SHA##digest_type##_DIGEST_LENGTH); \ + } \ + if(value) \ + while(len < (unsigned long)reqlen) { \ + libssh2_sha##digest_type##_init(&hash); \ + libssh2_sha##digest_type##_update(hash, \ + exchange_state->k_value, \ + exchange_state->k_value_len); \ + libssh2_sha##digest_type##_update(hash, \ + exchange_state->h_sig_comp, \ + SHA##digest_type##_DIGEST_LENGTH); \ + if(len > 0) { \ + libssh2_sha##digest_type##_update(hash, value, len); \ + } \ + else { \ + libssh2_sha##digest_type##_update(hash, (version), 1); \ + libssh2_sha##digest_type##_update(hash, session->session_id, \ + session->session_id_len); \ + } \ + libssh2_sha##digest_type##_final(hash, (value) + len); \ + len += SHA##digest_type##_DIGEST_LENGTH; \ + } \ +} /* @@ -118,37 +138,40 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, int rc; libssh2_sha1_ctx exchange_hash_ctx; - if (exchange_state->state == libssh2_NB_state_idle) { + if(exchange_state->state == libssh2_NB_state_idle) { /* Setup initial values */ exchange_state->e_packet = NULL; exchange_state->s_packet = NULL; exchange_state->k_value = NULL; exchange_state->ctx = _libssh2_bn_ctx_new(); - exchange_state->x = _libssh2_bn_init(); /* Random from client */ + libssh2_dh_init(&exchange_state->x); exchange_state->e = _libssh2_bn_init(); /* g^x mod p */ - exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from server) mod p */ - exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */ + exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from + server) mod p */ + exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod + p */ /* Zero the whole thing out */ memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t)); /* Generate x and e */ - _libssh2_bn_rand(exchange_state->x, group_order * 8 - 1, 0, -1); - _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p, - exchange_state->ctx); + rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p, + group_order, exchange_state->ctx); + if(rc) + goto clean_exit; /* Send KEX init */ /* packet_type(1) + String Length(4) + leading 0(1) */ exchange_state->e_packet_len = _libssh2_bn_bytes(exchange_state->e) + 6; - if (_libssh2_bn_bits(exchange_state->e) % 8) { + if(_libssh2_bn_bits(exchange_state->e) % 8) { /* Leading 00 not needed */ exchange_state->e_packet_len--; } exchange_state->e_packet = LIBSSH2_ALLOC(session, exchange_state->e_packet_len); - if (!exchange_state->e_packet) { + if(!exchange_state->e_packet) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Out of memory error"); goto clean_exit; @@ -156,10 +179,11 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, exchange_state->e_packet[0] = packet_type_init; _libssh2_htonu32(exchange_state->e_packet + 1, exchange_state->e_packet_len - 5); - if (_libssh2_bn_bits(exchange_state->e) % 8) { + if(_libssh2_bn_bits(exchange_state->e) % 8) { _libssh2_bn_to_bin(exchange_state->e, exchange_state->e_packet + 5); - } else { + } + else { exchange_state->e_packet[5] = 0; _libssh2_bn_to_bin(exchange_state->e, exchange_state->e_packet + 6); @@ -170,13 +194,14 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, exchange_state->state = libssh2_NB_state_created; } - if (exchange_state->state == libssh2_NB_state_created) { + if(exchange_state->state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, exchange_state->e_packet, exchange_state->e_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { ret = _libssh2_error(session, rc, "Unable to send KEX init message"); goto clean_exit; @@ -184,20 +209,22 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, exchange_state->state = libssh2_NB_state_sent; } - if (exchange_state->state == libssh2_NB_state_sent) { - if (session->burn_optimistic_kexinit) { + if(exchange_state->state == libssh2_NB_state_sent) { + if(session->burn_optimistic_kexinit) { /* The first KEX packet to come along will be the guess initially * sent by the server. That guess turned out to be wrong so we * need to silently ignore it */ int burn_type; _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Waiting for badly guessed KEX packet (to be ignored)"); + "Waiting for badly guessed KEX packet " + "(to be ignored)"); burn_type = _libssh2_packet_burn(session, &exchange_state->burn_state); - if (burn_type == LIBSSH2_ERROR_EAGAIN) { + if(burn_type == LIBSSH2_ERROR_EAGAIN) { return burn_type; - } else if (burn_type <= 0) { + } + else if(burn_type <= 0) { /* Failed to receive a packet */ ret = burn_type; goto clean_exit; @@ -212,16 +239,19 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, exchange_state->state = libssh2_NB_state_sent1; } - if (exchange_state->state == libssh2_NB_state_sent1) { + if(exchange_state->state == libssh2_NB_state_sent1) { /* Wait for KEX reply */ + struct string_buf buf; + size_t host_key_len; + rc = _libssh2_packet_require(session, packet_type_reply, &exchange_state->s_packet, &exchange_state->s_packet_len, 0, NULL, 0, &exchange_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - if (rc) { + if(rc) { ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Timed out waiting for KEX reply"); goto clean_exit; @@ -234,37 +264,28 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, goto clean_exit; } - exchange_state->s = exchange_state->s_packet + 1; + buf.data = exchange_state->s_packet; + buf.len = exchange_state->s_packet_len; + buf.dataptr = buf.data; + buf.dataptr++; /* advance past type */ - session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - - if(session->server_hostkey_len > exchange_state->s_packet_len - 5) { - ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, - "Host key length out of bounds"); - goto clean_exit; - } - - if (session->server_hostkey) + if(session->server_hostkey) LIBSSH2_FREE(session, session->server_hostkey); - session->server_hostkey = - LIBSSH2_ALLOC(session, session->server_hostkey_len); - if (!session->server_hostkey) { + if(_libssh2_copy_string(session, &buf, &(session->server_hostkey), + &host_key_len)) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for a copy " - "of the host key"); + "Could not copy host key"); goto clean_exit; } - memcpy(session->server_hostkey, exchange_state->s, - session->server_hostkey_len); - exchange_state->s += session->server_hostkey_len; + + session->server_hostkey_len = (uint32_t)host_key_len; #if LIBSSH2_MD5 { libssh2_md5_ctx fingerprint_ctx; - if (libssh2_md5_init(&fingerprint_ctx)) { + if(libssh2_md5_init(&fingerprint_ctx)) { libssh2_md5_update(fingerprint_ctx, session->server_hostkey, session->server_hostkey_len); libssh2_md5_final(fingerprint_ctx, @@ -292,7 +313,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, { libssh2_sha1_ctx fingerprint_ctx; - if (libssh2_sha1_init(&fingerprint_ctx)) { + if(libssh2_sha1_init(&fingerprint_ctx)) { libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, session->server_hostkey_len); libssh2_sha1_final(fingerprint_ctx, @@ -317,7 +338,38 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, } #endif /* LIBSSH2DEBUG */ - if (session->hostkey->init(session, session->server_hostkey, + { + libssh2_sha256_ctx fingerprint_ctx; + + if(libssh2_sha256_init(&fingerprint_ctx)) { + libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len); + libssh2_sha256_final(fingerprint_ctx, + session->server_hostkey_sha256); + session->server_hostkey_sha256_valid = TRUE; + } + else { + session->server_hostkey_sha256_valid = FALSE; + } + } +#ifdef LIBSSH2DEBUG + { + char *base64Fingerprint = NULL; + _libssh2_base64_encode(session, + (const char *) + session->server_hostkey_sha256, + SHA256_DIGEST_LENGTH, &base64Fingerprint); + if(base64Fingerprint != NULL) { + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server's SHA256 Fingerprint: %s", + base64Fingerprint); + LIBSSH2_FREE(session, base64Fingerprint); + } + } +#endif /* LIBSSH2DEBUG */ + + + if(session->hostkey->init(session, session->server_hostkey, session->server_hostkey_len, &session->server_hostkey_abstract)) { ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, @@ -325,58 +377,67 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, goto clean_exit; } - exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->f_value = exchange_state->s; - exchange_state->s += exchange_state->f_value_len; + if(_libssh2_get_string(&buf, &(exchange_state->f_value), + &(exchange_state->f_value_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to get f value"); + goto clean_exit; + } + _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len, exchange_state->f_value); - exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->h_sig = exchange_state->s; + if(_libssh2_get_string(&buf, &(exchange_state->h_sig), + &(exchange_state->h_sig_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to get h sig"); + goto clean_exit; + } /* Compute the shared secret */ - _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f, - exchange_state->x, p, exchange_state->ctx); + libssh2_dh_secret(&exchange_state->x, exchange_state->k, + exchange_state->f, p, exchange_state->ctx); exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5; - if (_libssh2_bn_bits(exchange_state->k) % 8) { + if(_libssh2_bn_bits(exchange_state->k) % 8) { /* don't need leading 00 */ exchange_state->k_value_len--; } exchange_state->k_value = LIBSSH2_ALLOC(session, exchange_state->k_value_len); - if (!exchange_state->k_value) { + if(!exchange_state->k_value) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate buffer for K"); goto clean_exit; } _libssh2_htonu32(exchange_state->k_value, exchange_state->k_value_len - 4); - if (_libssh2_bn_bits(exchange_state->k) % 8) { + if(_libssh2_bn_bits(exchange_state->k) % 8) { _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); - } else { + } + else { exchange_state->k_value[4] = 0; _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); } - exchange_state->exchange_hash = (void*)&exchange_hash_ctx; + exchange_state->exchange_hash = (void *)&exchange_hash_ctx; libssh2_sha1_init(&exchange_hash_ctx); - if (session->local.banner) { + if(session->local.banner) { _libssh2_htonu32(exchange_state->h_sig_comp, strlen((char *) session->local.banner) - 2); libssh2_sha1_update(exchange_hash_ctx, exchange_state->h_sig_comp, 4); libssh2_sha1_update(exchange_hash_ctx, - (char *) session->local.banner, + session->local.banner, strlen((char *) session->local.banner) - 2); - } else { + } + else { _libssh2_htonu32(exchange_state->h_sig_comp, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); libssh2_sha1_update(exchange_hash_ctx, exchange_state->h_sig_comp, 4); libssh2_sha1_update(exchange_hash_ctx, + (const unsigned char *) LIBSSH2_SSH_DEFAULT_BANNER, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); } @@ -413,7 +474,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, session->server_hostkey, session->server_hostkey_len); - if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) { + if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) { /* diffie-hellman-group-exchange hashes additional fields */ #ifdef LIBSSH2_DH_GEX_NEW _libssh2_htonu32(exchange_state->h_sig_comp, @@ -432,7 +493,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, #endif } - if (midhash) { + if(midhash) { libssh2_sha1_update(exchange_hash_ctx, midhash, midhash_len); } @@ -456,7 +517,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, libssh2_sha1_final(exchange_hash_ctx, exchange_state->h_sig_comp); - if (session->hostkey-> + if(session->hostkey-> sig_verify(session, exchange_state->h_sig, exchange_state->h_sig_len, exchange_state->h_sig_comp, 20, &session->server_hostkey_abstract)) { @@ -471,26 +532,29 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, exchange_state->state = libssh2_NB_state_sent2; } - if (exchange_state->state == libssh2_NB_state_sent2) { + if(exchange_state->state == libssh2_NB_state_sent2) { rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message"); + } + else if(rc) { + ret = _libssh2_error(session, rc, + "Unable to send NEWKEYS message"); goto clean_exit; } exchange_state->state = libssh2_NB_state_sent3; } - if (exchange_state->state == libssh2_NB_state_sent3) { + if(exchange_state->state == libssh2_NB_state_sent3) { rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS, &exchange_state->tmp, &exchange_state->tmp_len, 0, NULL, 0, &exchange_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS"); goto clean_exit; } @@ -503,46 +567,52 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, for this packet type anyway */ LIBSSH2_FREE(session, exchange_state->tmp); - if (!session->session_id) { + if(!session->session_id) { session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH); - if (!session->session_id) { + if(!session->session_id) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate buffer for SHA digest"); + "Unable to allocate buffer for " + "SHA digest"); goto clean_exit; } memcpy(session->session_id, exchange_state->h_sig_comp, SHA_DIGEST_LENGTH); session->session_id_len = SHA_DIGEST_LENGTH; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated"); + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "session_id calculated"); } /* Cleanup any existing cipher */ - if (session->local.crypt->dtor) { + if(session->local.crypt->dtor) { session->local.crypt->dtor(session, &session->local.crypt_abstract); } /* Calculate IV/Secret/Key for each direction */ - if (session->local.crypt->init) { + if(session->local.crypt->init) { unsigned char *iv = NULL, *secret = NULL; int free_iv = 0, free_secret = 0; LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv, session->local.crypt-> - iv_len, "A"); - if (!iv) { + iv_len, + (const unsigned char *) + "A"); + if(!iv) { ret = -1; goto clean_exit; } LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, session->local.crypt-> - secret_len, "C"); - if (!secret) { + secret_len, + (const unsigned char *) + "C"); + if(!secret) { LIBSSH2_FREE(session, iv); ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } - if (session->local.crypt-> + if(session->local.crypt-> init(session, session->local.crypt, iv, &free_iv, secret, &free_secret, 1, &session->local.crypt_abstract)) { LIBSSH2_FREE(session, iv); @@ -551,45 +621,50 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, goto clean_exit; } - if (free_iv) { - memset(iv, 0, session->local.crypt->iv_len); + if(free_iv) { + _libssh2_explicit_zero(iv, session->local.crypt->iv_len); LIBSSH2_FREE(session, iv); } - if (free_secret) { - memset(secret, 0, session->local.crypt->secret_len); + if(free_secret) { + _libssh2_explicit_zero(secret, + session->local.crypt->secret_len); LIBSSH2_FREE(session, secret); } } _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Client to Server IV and Key calculated"); - if (session->remote.crypt->dtor) { + if(session->remote.crypt->dtor) { /* Cleanup any existing cipher */ session->remote.crypt->dtor(session, &session->remote.crypt_abstract); } - if (session->remote.crypt->init) { + if(session->remote.crypt->init) { unsigned char *iv = NULL, *secret = NULL; int free_iv = 0, free_secret = 0; LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv, session->remote.crypt-> - iv_len, "B"); - if (!iv) { + iv_len, + (const unsigned char *) + "B"); + if(!iv) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, session->remote.crypt-> - secret_len, "D"); - if (!secret) { + secret_len, + (const unsigned char *) + "D"); + if(!secret) { LIBSSH2_FREE(session, iv); ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } - if (session->remote.crypt-> + if(session->remote.crypt-> init(session, session->remote.crypt, iv, &free_iv, secret, &free_secret, 0, &session->remote.crypt_abstract)) { LIBSSH2_FREE(session, iv); @@ -598,65 +673,70 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, goto clean_exit; } - if (free_iv) { - memset(iv, 0, session->remote.crypt->iv_len); + if(free_iv) { + _libssh2_explicit_zero(iv, session->remote.crypt->iv_len); LIBSSH2_FREE(session, iv); } - if (free_secret) { - memset(secret, 0, session->remote.crypt->secret_len); + if(free_secret) { + _libssh2_explicit_zero(secret, + session->remote.crypt->secret_len); LIBSSH2_FREE(session, secret); } } _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Server to Client IV and Key calculated"); - if (session->local.mac->dtor) { + if(session->local.mac->dtor) { session->local.mac->dtor(session, &session->local.mac_abstract); } - if (session->local.mac->init) { + if(session->local.mac->init) { unsigned char *key = NULL; int free_key = 0; LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->local.mac-> - key_len, "E"); - if (!key) { + key_len, + (const unsigned char *) + "E"); + if(!key) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } session->local.mac->init(session, key, &free_key, &session->local.mac_abstract); - if (free_key) { - memset(key, 0, session->local.mac->key_len); + if(free_key) { + _libssh2_explicit_zero(key, session->local.mac->key_len); LIBSSH2_FREE(session, key); } } _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Client to Server HMAC Key calculated"); - if (session->remote.mac->dtor) { + if(session->remote.mac->dtor) { session->remote.mac->dtor(session, &session->remote.mac_abstract); } - if (session->remote.mac->init) { + if(session->remote.mac->init) { unsigned char *key = NULL; int free_key = 0; LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->remote.mac-> - key_len, "F"); - if (!key) { + key_len, + (const unsigned char *) + "F"); + if(!key) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } session->remote.mac->init(session, key, &free_key, &session->remote.mac_abstract); - if (free_key) { - memset(key, 0, session->remote.mac->key_len); + if(free_key) { + _libssh2_explicit_zero(key, session->remote.mac->key_len); LIBSSH2_FREE(session, key); } } @@ -666,13 +746,13 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, /* Initialize compression for each direction */ /* Cleanup any existing compression */ - if (session->local.comp && session->local.comp->dtor) { + if(session->local.comp && session->local.comp->dtor) { session->local.comp->dtor(session, 1, &session->local.comp_abstract); } - if (session->local.comp && session->local.comp->init) { - if (session->local.comp->init(session, 1, + if(session->local.comp && session->local.comp->init) { + if(session->local.comp->init(session, 1, &session->local.comp_abstract)) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; @@ -681,13 +761,13 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Client to Server compression initialized"); - if (session->remote.comp && session->remote.comp->dtor) { + if(session->remote.comp && session->remote.comp->dtor) { session->remote.comp->dtor(session, 0, &session->remote.comp_abstract); } - if (session->remote.comp && session->remote.comp->init) { - if (session->remote.comp->init(session, 0, + if(session->remote.comp && session->remote.comp->init) { + if(session->remote.comp->init(session, 0, &session->remote.comp_abstract)) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; @@ -699,8 +779,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, } clean_exit: - _libssh2_bn_free(exchange_state->x); - exchange_state->x = NULL; + libssh2_dh_dtor(&exchange_state->x); _libssh2_bn_free(exchange_state->e); exchange_state->e = NULL; _libssh2_bn_free(exchange_state->f); @@ -710,17 +789,17 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, _libssh2_bn_ctx_free(exchange_state->ctx); exchange_state->ctx = NULL; - if (exchange_state->e_packet) { + if(exchange_state->e_packet) { LIBSSH2_FREE(session, exchange_state->e_packet); exchange_state->e_packet = NULL; } - if (exchange_state->s_packet) { + if(exchange_state->s_packet) { LIBSSH2_FREE(session, exchange_state->s_packet); exchange_state->s_packet = NULL; } - if (exchange_state->k_value) { + if(exchange_state->k_value) { LIBSSH2_FREE(session, exchange_state->k_value); exchange_state->k_value = NULL; } @@ -750,37 +829,40 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, int rc; libssh2_sha256_ctx exchange_hash_ctx; - if (exchange_state->state == libssh2_NB_state_idle) { + if(exchange_state->state == libssh2_NB_state_idle) { /* Setup initial values */ exchange_state->e_packet = NULL; exchange_state->s_packet = NULL; exchange_state->k_value = NULL; exchange_state->ctx = _libssh2_bn_ctx_new(); - exchange_state->x = _libssh2_bn_init(); /* Random from client */ + libssh2_dh_init(&exchange_state->x); exchange_state->e = _libssh2_bn_init(); /* g^x mod p */ - exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from server) mod p */ - exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */ + exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from + server) mod p */ + exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod + p */ /* Zero the whole thing out */ memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t)); /* Generate x and e */ - _libssh2_bn_rand(exchange_state->x, group_order * 8 - 1, 0, -1); - _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p, - exchange_state->ctx); + rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p, + group_order, exchange_state->ctx); + if(rc) + goto clean_exit; /* Send KEX init */ /* packet_type(1) + String Length(4) + leading 0(1) */ exchange_state->e_packet_len = _libssh2_bn_bytes(exchange_state->e) + 6; - if (_libssh2_bn_bits(exchange_state->e) % 8) { + if(_libssh2_bn_bits(exchange_state->e) % 8) { /* Leading 00 not needed */ exchange_state->e_packet_len--; } exchange_state->e_packet = LIBSSH2_ALLOC(session, exchange_state->e_packet_len); - if (!exchange_state->e_packet) { + if(!exchange_state->e_packet) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Out of memory error"); goto clean_exit; @@ -788,10 +870,11 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, exchange_state->e_packet[0] = packet_type_init; _libssh2_htonu32(exchange_state->e_packet + 1, exchange_state->e_packet_len - 5); - if (_libssh2_bn_bits(exchange_state->e) % 8) { + if(_libssh2_bn_bits(exchange_state->e) % 8) { _libssh2_bn_to_bin(exchange_state->e, exchange_state->e_packet + 5); - } else { + } + else { exchange_state->e_packet[5] = 0; _libssh2_bn_to_bin(exchange_state->e, exchange_state->e_packet + 6); @@ -802,13 +885,14 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, exchange_state->state = libssh2_NB_state_created; } - if (exchange_state->state == libssh2_NB_state_created) { + if(exchange_state->state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, exchange_state->e_packet, exchange_state->e_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { ret = _libssh2_error(session, rc, "Unable to send KEX init message"); goto clean_exit; @@ -816,20 +900,22 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, exchange_state->state = libssh2_NB_state_sent; } - if (exchange_state->state == libssh2_NB_state_sent) { - if (session->burn_optimistic_kexinit) { + if(exchange_state->state == libssh2_NB_state_sent) { + if(session->burn_optimistic_kexinit) { /* The first KEX packet to come along will be the guess initially * sent by the server. That guess turned out to be wrong so we * need to silently ignore it */ int burn_type; _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Waiting for badly guessed KEX packet (to be ignored)"); + "Waiting for badly guessed KEX packet " + "(to be ignored)"); burn_type = _libssh2_packet_burn(session, &exchange_state->burn_state); - if (burn_type == LIBSSH2_ERROR_EAGAIN) { + if(burn_type == LIBSSH2_ERROR_EAGAIN) { return burn_type; - } else if (burn_type <= 0) { + } + else if(burn_type <= 0) { /* Failed to receive a packet */ ret = burn_type; goto clean_exit; @@ -844,16 +930,19 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, exchange_state->state = libssh2_NB_state_sent1; } - if (exchange_state->state == libssh2_NB_state_sent1) { + if(exchange_state->state == libssh2_NB_state_sent1) { /* Wait for KEX reply */ + struct string_buf buf; + size_t host_key_len; + rc = _libssh2_packet_require(session, packet_type_reply, &exchange_state->s_packet, &exchange_state->s_packet_len, 0, NULL, 0, &exchange_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - if (rc) { + if(rc) { ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Timed out waiting for KEX reply"); goto clean_exit; @@ -865,38 +954,29 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, "Unexpected packet length"); goto clean_exit; } - - exchange_state->s = exchange_state->s_packet + 1; - session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; + buf.data = exchange_state->s_packet; + buf.len = exchange_state->s_packet_len; + buf.dataptr = buf.data; + buf.dataptr++; /* advance past type */ - if(session->server_hostkey_len > exchange_state->s_packet_len - 5) { - ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, - "Host key length out of bounds"); - goto clean_exit; - } - - if (session->server_hostkey) + if(session->server_hostkey) LIBSSH2_FREE(session, session->server_hostkey); - session->server_hostkey = - LIBSSH2_ALLOC(session, session->server_hostkey_len); - if (!session->server_hostkey) { + if(_libssh2_copy_string(session, &buf, &(session->server_hostkey), + &host_key_len)) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for a copy " - "of the host key"); + "Could not copy host key"); goto clean_exit; } - memcpy(session->server_hostkey, exchange_state->s, - session->server_hostkey_len); - exchange_state->s += session->server_hostkey_len; + + session->server_hostkey_len = (uint32_t)host_key_len; #if LIBSSH2_MD5 { libssh2_md5_ctx fingerprint_ctx; - if (libssh2_md5_init(&fingerprint_ctx)) { + if(libssh2_md5_init(&fingerprint_ctx)) { libssh2_md5_update(fingerprint_ctx, session->server_hostkey, session->server_hostkey_len); libssh2_md5_final(fingerprint_ctx, @@ -924,7 +1004,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, { libssh2_sha1_ctx fingerprint_ctx; - if (libssh2_sha1_init(&fingerprint_ctx)) { + if(libssh2_sha1_init(&fingerprint_ctx)) { libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, session->server_hostkey_len); libssh2_sha1_final(fingerprint_ctx, @@ -949,7 +1029,37 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, } #endif /* LIBSSH2DEBUG */ - if (session->hostkey->init(session, session->server_hostkey, + { + libssh2_sha256_ctx fingerprint_ctx; + + if(libssh2_sha256_init(&fingerprint_ctx)) { + libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len); + libssh2_sha256_final(fingerprint_ctx, + session->server_hostkey_sha256); + session->server_hostkey_sha256_valid = TRUE; + } + else { + session->server_hostkey_sha256_valid = FALSE; + } + } +#ifdef LIBSSH2DEBUG + { + char *base64Fingerprint = NULL; + _libssh2_base64_encode(session, + (const char *) + session->server_hostkey_sha256, + SHA256_DIGEST_LENGTH, &base64Fingerprint); + if(base64Fingerprint != NULL) { + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server's SHA256 Fingerprint: %s", + base64Fingerprint); + LIBSSH2_FREE(session, base64Fingerprint); + } + } +#endif /* LIBSSH2DEBUG */ + + if(session->hostkey->init(session, session->server_hostkey, session->server_hostkey_len, &session->server_hostkey_abstract)) { ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, @@ -957,58 +1067,67 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, goto clean_exit; } - exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->f_value = exchange_state->s; - exchange_state->s += exchange_state->f_value_len; + if(_libssh2_get_string(&buf, &(exchange_state->f_value), + &(exchange_state->f_value_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to get f value"); + goto clean_exit; + } + _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len, exchange_state->f_value); - exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->h_sig = exchange_state->s; + if(_libssh2_get_string(&buf, &(exchange_state->h_sig), + &(exchange_state->h_sig_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to get h sig"); + goto clean_exit; + } /* Compute the shared secret */ - _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f, - exchange_state->x, p, exchange_state->ctx); + libssh2_dh_secret(&exchange_state->x, exchange_state->k, + exchange_state->f, p, exchange_state->ctx); exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5; - if (_libssh2_bn_bits(exchange_state->k) % 8) { + if(_libssh2_bn_bits(exchange_state->k) % 8) { /* don't need leading 00 */ exchange_state->k_value_len--; } exchange_state->k_value = LIBSSH2_ALLOC(session, exchange_state->k_value_len); - if (!exchange_state->k_value) { + if(!exchange_state->k_value) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate buffer for K"); goto clean_exit; } _libssh2_htonu32(exchange_state->k_value, exchange_state->k_value_len - 4); - if (_libssh2_bn_bits(exchange_state->k) % 8) { + if(_libssh2_bn_bits(exchange_state->k) % 8) { _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); - } else { + } + else { exchange_state->k_value[4] = 0; _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); } - exchange_state->exchange_hash = (void*)&exchange_hash_ctx; + exchange_state->exchange_hash = (void *)&exchange_hash_ctx; libssh2_sha256_init(&exchange_hash_ctx); - if (session->local.banner) { + if(session->local.banner) { _libssh2_htonu32(exchange_state->h_sig_comp, strlen((char *) session->local.banner) - 2); libssh2_sha256_update(exchange_hash_ctx, exchange_state->h_sig_comp, 4); libssh2_sha256_update(exchange_hash_ctx, - (char *) session->local.banner, + session->local.banner, strlen((char *) session->local.banner) - 2); - } else { + } + else { _libssh2_htonu32(exchange_state->h_sig_comp, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); libssh2_sha256_update(exchange_hash_ctx, exchange_state->h_sig_comp, 4); libssh2_sha256_update(exchange_hash_ctx, + (const unsigned char *) LIBSSH2_SSH_DEFAULT_BANNER, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); } @@ -1045,7 +1164,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, session->server_hostkey, session->server_hostkey_len); - if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) { + if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) { /* diffie-hellman-group-exchange hashes additional fields */ #ifdef LIBSSH2_DH_GEX_NEW _libssh2_htonu32(exchange_state->h_sig_comp, @@ -1064,7 +1183,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, #endif } - if (midhash) { + if(midhash) { libssh2_sha256_update(exchange_hash_ctx, midhash, midhash_len); } @@ -1088,10 +1207,11 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, libssh2_sha256_final(exchange_hash_ctx, exchange_state->h_sig_comp); - if (session->hostkey-> - sig_verify(session, exchange_state->h_sig, - exchange_state->h_sig_len, exchange_state->h_sig_comp, - SHA256_DIGEST_LENGTH, &session->server_hostkey_abstract)) { + if(session->hostkey-> + sig_verify(session, exchange_state->h_sig, + exchange_state->h_sig_len, exchange_state->h_sig_comp, + SHA256_DIGEST_LENGTH, + &session->server_hostkey_abstract)) { ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN, "Unable to verify hostkey signature"); goto clean_exit; @@ -1105,26 +1225,29 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, exchange_state->state = libssh2_NB_state_sent2; } - if (exchange_state->state == libssh2_NB_state_sent2) { + if(exchange_state->state == libssh2_NB_state_sent2) { rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message"); + } + else if(rc) { + ret = _libssh2_error(session, rc, + "Unable to send NEWKEYS message"); goto clean_exit; } exchange_state->state = libssh2_NB_state_sent3; } - if (exchange_state->state == libssh2_NB_state_sent3) { + if(exchange_state->state == libssh2_NB_state_sent3) { rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS, &exchange_state->tmp, &exchange_state->tmp_len, 0, NULL, 0, &exchange_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS"); goto clean_exit; } @@ -1137,46 +1260,50 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, for this packet type anyway */ LIBSSH2_FREE(session, exchange_state->tmp); - if (!session->session_id) { + if(!session->session_id) { session->session_id = LIBSSH2_ALLOC(session, SHA256_DIGEST_LENGTH); - if (!session->session_id) { + if(!session->session_id) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate buffer for SHA digest"); + "Unable to allocate buffer for " + "SHA digest"); goto clean_exit; } memcpy(session->session_id, exchange_state->h_sig_comp, SHA256_DIGEST_LENGTH); session->session_id_len = SHA256_DIGEST_LENGTH; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "session_id calculated"); + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "session_id calculated"); } /* Cleanup any existing cipher */ - if (session->local.crypt->dtor) { + if(session->local.crypt->dtor) { session->local.crypt->dtor(session, &session->local.crypt_abstract); } /* Calculate IV/Secret/Key for each direction */ - if (session->local.crypt->init) { + if(session->local.crypt->init) { unsigned char *iv = NULL, *secret = NULL; int free_iv = 0, free_secret = 0; - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(iv, - session->local.crypt-> - iv_len, "A"); - if (!iv) { + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv, + session->local.crypt-> + iv_len, + (const unsigned char *)"A"); + if(!iv) { ret = -1; goto clean_exit; } - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(secret, - session->local.crypt-> - secret_len, "C"); - if (!secret) { + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret, + session->local.crypt-> + secret_len, + (const unsigned char *)"C"); + if(!secret) { LIBSSH2_FREE(session, iv); ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } - if (session->local.crypt-> + if(session->local.crypt-> init(session, session->local.crypt, iv, &free_iv, secret, &free_secret, 1, &session->local.crypt_abstract)) { LIBSSH2_FREE(session, iv); @@ -1185,45 +1312,48 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, goto clean_exit; } - if (free_iv) { - memset(iv, 0, session->local.crypt->iv_len); + if(free_iv) { + _libssh2_explicit_zero(iv, session->local.crypt->iv_len); LIBSSH2_FREE(session, iv); } - if (free_secret) { - memset(secret, 0, session->local.crypt->secret_len); + if(free_secret) { + _libssh2_explicit_zero(secret, + session->local.crypt->secret_len); LIBSSH2_FREE(session, secret); } } _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Client to Server IV and Key calculated"); - if (session->remote.crypt->dtor) { + if(session->remote.crypt->dtor) { /* Cleanup any existing cipher */ session->remote.crypt->dtor(session, &session->remote.crypt_abstract); } - if (session->remote.crypt->init) { + if(session->remote.crypt->init) { unsigned char *iv = NULL, *secret = NULL; int free_iv = 0, free_secret = 0; - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(iv, - session->remote.crypt-> - iv_len, "B"); - if (!iv) { + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv, + session->remote.crypt-> + iv_len, + (const unsigned char *)"B"); + if(!iv) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(secret, - session->remote.crypt-> - secret_len, "D"); - if (!secret) { + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret, + session->remote.crypt-> + secret_len, + (const unsigned char *)"D"); + if(!secret) { LIBSSH2_FREE(session, iv); ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } - if (session->remote.crypt-> + if(session->remote.crypt-> init(session, session->remote.crypt, iv, &free_iv, secret, &free_secret, 0, &session->remote.crypt_abstract)) { LIBSSH2_FREE(session, iv); @@ -1232,65 +1362,68 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, goto clean_exit; } - if (free_iv) { - memset(iv, 0, session->remote.crypt->iv_len); + if(free_iv) { + _libssh2_explicit_zero(iv, session->remote.crypt->iv_len); LIBSSH2_FREE(session, iv); } - if (free_secret) { - memset(secret, 0, session->remote.crypt->secret_len); + if(free_secret) { + _libssh2_explicit_zero(secret, + session->remote.crypt->secret_len); LIBSSH2_FREE(session, secret); } } _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Server to Client IV and Key calculated"); - if (session->local.mac->dtor) { + if(session->local.mac->dtor) { session->local.mac->dtor(session, &session->local.mac_abstract); } - if (session->local.mac->init) { + if(session->local.mac->init) { unsigned char *key = NULL; int free_key = 0; - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(key, - session->local.mac-> - key_len, "E"); - if (!key) { + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key, + session->local.mac-> + key_len, + (const unsigned char *)"E"); + if(!key) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } session->local.mac->init(session, key, &free_key, &session->local.mac_abstract); - if (free_key) { - memset(key, 0, session->local.mac->key_len); + if(free_key) { + _libssh2_explicit_zero(key, session->local.mac->key_len); LIBSSH2_FREE(session, key); } } _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Client to Server HMAC Key calculated"); - if (session->remote.mac->dtor) { + if(session->remote.mac->dtor) { session->remote.mac->dtor(session, &session->remote.mac_abstract); } - if (session->remote.mac->init) { + if(session->remote.mac->init) { unsigned char *key = NULL; int free_key = 0; - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA256_HASH(key, - session->remote.mac-> - key_len, "F"); - if (!key) { + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key, + session->remote.mac-> + key_len, + (const unsigned char *)"F"); + if(!key) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; } session->remote.mac->init(session, key, &free_key, &session->remote.mac_abstract); - if (free_key) { - memset(key, 0, session->remote.mac->key_len); + if(free_key) { + _libssh2_explicit_zero(key, session->remote.mac->key_len); LIBSSH2_FREE(session, key); } } @@ -1300,13 +1433,13 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, /* Initialize compression for each direction */ /* Cleanup any existing compression */ - if (session->local.comp && session->local.comp->dtor) { + if(session->local.comp && session->local.comp->dtor) { session->local.comp->dtor(session, 1, &session->local.comp_abstract); } - if (session->local.comp && session->local.comp->init) { - if (session->local.comp->init(session, 1, + if(session->local.comp && session->local.comp->init) { + if(session->local.comp->init(session, 1, &session->local.comp_abstract)) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; @@ -1315,13 +1448,13 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Client to Server compression initialized"); - if (session->remote.comp && session->remote.comp->dtor) { + if(session->remote.comp && session->remote.comp->dtor) { session->remote.comp->dtor(session, 0, &session->remote.comp_abstract); } - if (session->remote.comp && session->remote.comp->init) { - if (session->remote.comp->init(session, 0, + if(session->remote.comp && session->remote.comp->init) { + if(session->remote.comp->init(session, 0, &session->remote.comp_abstract)) { ret = LIBSSH2_ERROR_KEX_FAILURE; goto clean_exit; @@ -1333,8 +1466,7 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, } clean_exit: - _libssh2_bn_free(exchange_state->x); - exchange_state->x = NULL; + libssh2_dh_dtor(&exchange_state->x); _libssh2_bn_free(exchange_state->e); exchange_state->e = NULL; _libssh2_bn_free(exchange_state->f); @@ -1344,17 +1476,17 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, _libssh2_bn_ctx_free(exchange_state->ctx); exchange_state->ctx = NULL; - if (exchange_state->e_packet) { + if(exchange_state->e_packet) { LIBSSH2_FREE(session, exchange_state->e_packet); exchange_state->e_packet = NULL; } - if (exchange_state->s_packet) { + if(exchange_state->s_packet) { LIBSSH2_FREE(session, exchange_state->s_packet); exchange_state->s_packet = NULL; } - if (exchange_state->k_value) { + if(exchange_state->k_value) { LIBSSH2_FREE(session, exchange_state->k_value); exchange_state->k_value = NULL; } @@ -1395,9 +1527,10 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session, int ret; - if (key_state->state == libssh2_NB_state_idle) { + if(key_state->state == libssh2_NB_state_idle) { /* g == 2 */ - key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value (p_value) */ + key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value + (p_value) */ key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */ /* Initialize P and G */ @@ -1412,7 +1545,7 @@ kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session, ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, NULL, 0, &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { + if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } @@ -1471,8 +1604,9 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session, }; int ret; - if (key_state->state == libssh2_NB_state_idle) { - key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value (p_value) */ + if(key_state->state == libssh2_NB_state_idle) { + key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value + (p_value) */ key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */ /* g == 2 */ @@ -1488,7 +1622,7 @@ kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session, ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, NULL, 0, &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { + if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } @@ -1511,11 +1645,10 @@ static int kex_method_diffie_hellman_group_exchange_sha1_key_exchange (LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) { - unsigned long p_len, g_len; int ret = 0; int rc; - if (key_state->state == libssh2_NB_state_idle) { + if(key_state->state == libssh2_NB_state_idle) { key_state->p = _libssh2_bn_init_from_bin(); key_state->g = _libssh2_bn_init_from_bin(); /* Ask for a P and G pair */ @@ -1526,24 +1659,27 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange _libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP); key_state->request_len = 13; _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Initiating Diffie-Hellman Group-Exchange (New Method)"); + "Initiating Diffie-Hellman Group-Exchange " + "(New Method)"); #else key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD; _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP); key_state->request_len = 5; _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Initiating Diffie-Hellman Group-Exchange (Old Method)"); + "Initiating Diffie-Hellman Group-Exchange " + "(Old Method)"); #endif key_state->state = libssh2_NB_state_created; } - if (key_state->state == libssh2_NB_state_created) { + if(key_state->state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, key_state->request, key_state->request_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { ret = _libssh2_error(session, rc, "Unable to send Group Exchange Request"); goto dh_gex_clean_exit; @@ -1552,13 +1688,14 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange key_state->state = libssh2_NB_state_sent; } - if (key_state->state == libssh2_NB_state_sent) { + if(key_state->state == libssh2_NB_state_sent) { rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP, &key_state->data, &key_state->data_len, 0, NULL, 0, &key_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { ret = _libssh2_error(session, rc, "Timeout waiting for GEX_GROUP reply"); goto dh_gex_clean_exit; @@ -1567,16 +1704,37 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange key_state->state = libssh2_NB_state_sent1; } - if (key_state->state == libssh2_NB_state_sent1) { - unsigned char *s = key_state->data + 1; - p_len = _libssh2_ntohu32(s); - s += 4; - _libssh2_bn_from_bin(key_state->p, p_len, s); - s += p_len; + if(key_state->state == libssh2_NB_state_sent1) { + size_t p_len, g_len; + unsigned char *p, *g; + struct string_buf buf; - g_len = _libssh2_ntohu32(s); - s += 4; - _libssh2_bn_from_bin(key_state->g, g_len, s); + if(key_state->data_len < 9) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected key length"); + goto dh_gex_clean_exit; + } + + buf.data = key_state->data; + buf.dataptr = buf.data; + buf.len = key_state->data_len; + + buf.dataptr++; /* increment to big num */ + + if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected value"); + goto dh_gex_clean_exit; + } + + if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected value"); + goto dh_gex_clean_exit; + } + + _libssh2_bn_from_bin(key_state->p, p_len, p); + _libssh2_bn_from_bin(key_state->g, g_len, g); ret = diffie_hellman_sha1(session, key_state->g, key_state->p, p_len, SSH_MSG_KEX_DH_GEX_INIT, @@ -1584,7 +1742,7 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange key_state->data + 1, key_state->data_len - 1, &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { + if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } @@ -1611,11 +1769,10 @@ static int kex_method_diffie_hellman_group_exchange_sha256_key_exchange (LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) { - unsigned long p_len, g_len; int ret = 0; int rc; - if (key_state->state == libssh2_NB_state_idle) { + if(key_state->state == libssh2_NB_state_idle) { key_state->p = _libssh2_bn_init(); key_state->g = _libssh2_bn_init(); /* Ask for a P and G pair */ @@ -1626,39 +1783,44 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange _libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP); key_state->request_len = 13; _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Initiating Diffie-Hellman Group-Exchange (New Method SHA256)"); + "Initiating Diffie-Hellman Group-Exchange " + "(New Method SHA256)"); #else key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD; _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP); key_state->request_len = 5; _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Initiating Diffie-Hellman Group-Exchange (Old Method SHA256)"); + "Initiating Diffie-Hellman Group-Exchange " + "(Old Method SHA256)"); #endif key_state->state = libssh2_NB_state_created; } - if (key_state->state == libssh2_NB_state_created) { + if(key_state->state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, key_state->request, key_state->request_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { ret = _libssh2_error(session, rc, - "Unable to send Group Exchange Request SHA256"); + "Unable to send " + "Group Exchange Request SHA256"); goto dh_gex_clean_exit; } key_state->state = libssh2_NB_state_sent; } - if (key_state->state == libssh2_NB_state_sent) { + if(key_state->state == libssh2_NB_state_sent) { rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP, &key_state->data, &key_state->data_len, 0, NULL, 0, &key_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { ret = _libssh2_error(session, rc, "Timeout waiting for GEX_GROUP reply SHA256"); goto dh_gex_clean_exit; @@ -1667,16 +1829,37 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange key_state->state = libssh2_NB_state_sent1; } - if (key_state->state == libssh2_NB_state_sent1) { - unsigned char *s = key_state->data + 1; - p_len = _libssh2_ntohu32(s); - s += 4; - _libssh2_bn_from_bin(key_state->p, p_len, s); - s += p_len; + if(key_state->state == libssh2_NB_state_sent1) { + unsigned char *p, *g; + size_t p_len, g_len; + struct string_buf buf; - g_len = _libssh2_ntohu32(s); - s += 4; - _libssh2_bn_from_bin(key_state->g, g_len, s); + if(key_state->data_len < 9) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected key length"); + goto dh_gex_clean_exit; + } + + buf.data = key_state->data; + buf.dataptr = buf.data; + buf.len = key_state->data_len; + + buf.dataptr++; /* increment to big num */ + + if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected value"); + goto dh_gex_clean_exit; + } + + if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected value"); + goto dh_gex_clean_exit; + } + + _libssh2_bn_from_bin(key_state->p, p_len, p); + _libssh2_bn_from_bin(key_state->g, g_len, g); ret = diffie_hellman_sha256(session, key_state->g, key_state->p, p_len, SSH_MSG_KEX_DH_GEX_INIT, @@ -1684,7 +1867,7 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange key_state->data + 1, key_state->data_len - 1, &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { + if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } @@ -1702,6 +1885,1369 @@ kex_method_diffie_hellman_group_exchange_sha256_key_exchange } +#if LIBSSH2_ECDSA + +/* kex_session_ecdh_curve_type + * returns the EC curve type by name used in key exchange + */ + +static int +kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type) +{ + int ret = 0; + libssh2_curve_type type; + + if(name == NULL) + return -1; + + if(strcmp(name, "ecdh-sha2-nistp256") == 0) + type = LIBSSH2_EC_CURVE_NISTP256; + else if(strcmp(name, "ecdh-sha2-nistp384") == 0) + type = LIBSSH2_EC_CURVE_NISTP384; + else if(strcmp(name, "ecdh-sha2-nistp521") == 0) + type = LIBSSH2_EC_CURVE_NISTP521; + else { + ret = -1; + } + + if(ret == 0 && out_type) { + *out_type = type; + } + + return ret; +} + + +/* LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY + * + * Macro that create and verifies EC SHA hash with a given digest bytes + * + * Payload format: + * + * string V_C, client's identification string (CR and LF excluded) + * string V_S, server's identification string (CR and LF excluded) + * string I_C, payload of the client's SSH_MSG_KEXINIT + * string I_S, payload of the server's SSH_MSG_KEXINIT + * string K_S, server's public host key + * string Q_C, client's ephemeral public key octet string + * string Q_S, server's ephemeral public key octet string + * mpint K, shared secret + * + */ + +#define LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(digest_type) \ +{ \ + libssh2_sha##digest_type##_ctx ctx; \ + exchange_state->exchange_hash = (void *)&ctx; \ + libssh2_sha##digest_type##_init(&ctx); \ + if(session->local.banner) { \ + _libssh2_htonu32(exchange_state->h_sig_comp, \ + strlen((char *) session->local.banner) - 2); \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + libssh2_sha##digest_type##_update(ctx, \ + (char *) session->local.banner, \ + strlen((char *) \ + session->local.banner) \ + - 2); \ + } \ + else { \ + _libssh2_htonu32(exchange_state->h_sig_comp, \ + sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1); \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + libssh2_sha##digest_type##_update(ctx, \ + LIBSSH2_SSH_DEFAULT_BANNER, \ + sizeof(LIBSSH2_SSH_DEFAULT_BANNER) \ + - 1); \ + } \ + \ + _libssh2_htonu32(exchange_state->h_sig_comp, \ + strlen((char *) session->remote.banner)); \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + libssh2_sha##digest_type##_update(ctx, \ + session->remote.banner, \ + strlen((char *) \ + session->remote.banner)); \ + \ + _libssh2_htonu32(exchange_state->h_sig_comp, \ + session->local.kexinit_len); \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + libssh2_sha##digest_type##_update(ctx, \ + session->local.kexinit, \ + session->local.kexinit_len); \ + \ + _libssh2_htonu32(exchange_state->h_sig_comp, \ + session->remote.kexinit_len); \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + libssh2_sha##digest_type##_update(ctx, \ + session->remote.kexinit, \ + session->remote.kexinit_len); \ + \ + _libssh2_htonu32(exchange_state->h_sig_comp, \ + session->server_hostkey_len); \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + libssh2_sha##digest_type##_update(ctx, \ + session->server_hostkey, \ + session->server_hostkey_len); \ + \ + _libssh2_htonu32(exchange_state->h_sig_comp, \ + public_key_len); \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + libssh2_sha##digest_type##_update(ctx, \ + public_key, \ + public_key_len); \ + \ + _libssh2_htonu32(exchange_state->h_sig_comp, \ + server_public_key_len); \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->h_sig_comp, 4); \ + libssh2_sha##digest_type##_update(ctx, \ + server_public_key, \ + server_public_key_len); \ + \ + libssh2_sha##digest_type##_update(ctx, \ + exchange_state->k_value, \ + exchange_state->k_value_len); \ + \ + libssh2_sha##digest_type##_final(ctx, exchange_state->h_sig_comp); \ + \ + if(session->hostkey-> \ + sig_verify(session, exchange_state->h_sig, \ + exchange_state->h_sig_len, exchange_state->h_sig_comp, \ + SHA##digest_type##_DIGEST_LENGTH, \ + &session->server_hostkey_abstract)) { \ + rc = -1; \ + } \ +} \ + + +/* ecdh_sha2_nistp + * Elliptic Curve Diffie Hellman Key Exchange + */ + +static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type, + unsigned char *data, size_t data_len, + unsigned char *public_key, + size_t public_key_len, _libssh2_ec_key *private_key, + kmdhgGPshakex_state_t *exchange_state) +{ + int ret = 0; + int rc; + + if(data_len < 5) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Host key data is too short"); + return ret; + } + + if(exchange_state->state == libssh2_NB_state_idle) { + + /* Setup initial values */ + exchange_state->k = _libssh2_bn_init(); + + exchange_state->state = libssh2_NB_state_created; + } + + if(exchange_state->state == libssh2_NB_state_created) { + /* parse INIT reply data */ + + /* host key K_S */ + unsigned char *s = data + 1; /* Advance past packet type */ + unsigned char *server_public_key; + size_t server_public_key_len; + size_t host_sig_len; + + session->server_hostkey_len = + _libssh2_ntohu32((const unsigned char *)s); + s += 4; + + session->server_hostkey = LIBSSH2_ALLOC(session, + session->server_hostkey_len); + if(!session->server_hostkey) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for a copy " + "of the host key"); + goto clean_exit; + } + + memcpy(session->server_hostkey, s, session->server_hostkey_len); + s += session->server_hostkey_len; + +#if LIBSSH2_MD5 + { + libssh2_md5_ctx fingerprint_ctx; + + if(libssh2_md5_init(&fingerprint_ctx)) { + libssh2_md5_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len); + libssh2_md5_final(fingerprint_ctx, + session->server_hostkey_md5); + session->server_hostkey_md5_valid = TRUE; + } + else { + session->server_hostkey_md5_valid = FALSE; + } + } +#ifdef LIBSSH2DEBUG + { + char fingerprint[50], *fprint = fingerprint; + int i; + for(i = 0; i < 16; i++, fprint += 3) { + snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]); + } + *(--fprint) = '\0'; + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server's MD5 Fingerprint: %s", fingerprint); + } +#endif /* LIBSSH2DEBUG */ +#endif /* ! LIBSSH2_MD5 */ + + { + libssh2_sha1_ctx fingerprint_ctx; + + if(libssh2_sha1_init(&fingerprint_ctx)) { + libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len); + libssh2_sha1_final(fingerprint_ctx, + session->server_hostkey_sha1); + session->server_hostkey_sha1_valid = TRUE; + } + else { + session->server_hostkey_sha1_valid = FALSE; + } + } +#ifdef LIBSSH2DEBUG + { + char fingerprint[64], *fprint = fingerprint; + int i; + + for(i = 0; i < 20; i++, fprint += 3) { + snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]); + } + *(--fprint) = '\0'; + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server's SHA1 Fingerprint: %s", fingerprint); + } +#endif /* LIBSSH2DEBUG */ + + /* SHA256 */ + { + libssh2_sha256_ctx fingerprint_ctx; + + if(libssh2_sha256_init(&fingerprint_ctx)) { + libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len); + libssh2_sha256_final(fingerprint_ctx, + session->server_hostkey_sha256); + session->server_hostkey_sha256_valid = TRUE; + } + else { + session->server_hostkey_sha256_valid = FALSE; + } + } +#ifdef LIBSSH2DEBUG + { + char *base64Fingerprint = NULL; + _libssh2_base64_encode(session, + (const char *) + session->server_hostkey_sha256, + SHA256_DIGEST_LENGTH, &base64Fingerprint); + if(base64Fingerprint != NULL) { + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server's SHA256 Fingerprint: %s", + base64Fingerprint); + LIBSSH2_FREE(session, base64Fingerprint); + } + } +#endif /* LIBSSH2DEBUG */ + + if(session->hostkey->init(session, session->server_hostkey, + session->server_hostkey_len, + &session->server_hostkey_abstract)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to initialize hostkey importer"); + goto clean_exit; + } + + /* server public key Q_S */ + server_public_key_len = _libssh2_ntohu32((const unsigned char *)s); + s += 4; + + server_public_key = s; + s += server_public_key_len; + + /* server signature */ + host_sig_len = _libssh2_ntohu32((const unsigned char *)s); + s += 4; + + exchange_state->h_sig = s; + exchange_state->h_sig_len = host_sig_len; + s += host_sig_len; + + /* Compute the shared secret K */ + rc = _libssh2_ecdh_gen_k(&exchange_state->k, private_key, + server_public_key, server_public_key_len); + if(rc != 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, + "Unable to create ECDH shared secret"); + goto clean_exit; + } + + exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5; + if(_libssh2_bn_bits(exchange_state->k) % 8) { + /* don't need leading 00 */ + exchange_state->k_value_len--; + } + exchange_state->k_value = + LIBSSH2_ALLOC(session, exchange_state->k_value_len); + if(!exchange_state->k_value) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate buffer for K"); + goto clean_exit; + } + _libssh2_htonu32(exchange_state->k_value, + exchange_state->k_value_len - 4); + if(_libssh2_bn_bits(exchange_state->k) % 8) { + _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); + } + else { + exchange_state->k_value[4] = 0; + _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); + } + + /* verify hash */ + + switch(type) { + case LIBSSH2_EC_CURVE_NISTP256: + LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256); + break; + + case LIBSSH2_EC_CURVE_NISTP384: + LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(384); + break; + case LIBSSH2_EC_CURVE_NISTP521: + LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(512); + break; + } + + if(rc != 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN, + "Unable to verify hostkey signature"); + goto clean_exit; + } + + exchange_state->c = SSH_MSG_NEWKEYS; + exchange_state->state = libssh2_NB_state_sent; + } + + if(exchange_state->state == libssh2_NB_state_sent) { + rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + ret = _libssh2_error(session, rc, + "Unable to send NEWKEYS message"); + goto clean_exit; + } + + exchange_state->state = libssh2_NB_state_sent2; + } + + if(exchange_state->state == libssh2_NB_state_sent2) { + rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS, + &exchange_state->tmp, + &exchange_state->tmp_len, 0, NULL, 0, + &exchange_state->req_state); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS"); + goto clean_exit; + } + + /* The first key exchange has been performed, + switch to active crypt/comp/mac mode */ + session->state |= LIBSSH2_STATE_NEWKEYS; + _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message"); + + /* This will actually end up being just packet_type(1) + for this packet type anyway */ + LIBSSH2_FREE(session, exchange_state->tmp); + + if(!session->session_id) { + + size_t digest_length = 0; + + if(type == LIBSSH2_EC_CURVE_NISTP256) + digest_length = SHA256_DIGEST_LENGTH; + else if(type == LIBSSH2_EC_CURVE_NISTP384) + digest_length = SHA384_DIGEST_LENGTH; + else if(type == LIBSSH2_EC_CURVE_NISTP521) + digest_length = SHA512_DIGEST_LENGTH; + else{ + ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, + "Unknown SHA digest for EC curve"); + goto clean_exit; + + } + session->session_id = LIBSSH2_ALLOC(session, digest_length); + if(!session->session_id) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate buffer for " + "SHA digest"); + goto clean_exit; + } + memcpy(session->session_id, exchange_state->h_sig_comp, + digest_length); + session->session_id_len = digest_length; + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "session_id calculated"); + } + + /* Cleanup any existing cipher */ + if(session->local.crypt->dtor) { + session->local.crypt->dtor(session, + &session->local.crypt_abstract); + } + + /* Calculate IV/Secret/Key for each direction */ + if(session->local.crypt->init) { + unsigned char *iv = NULL, *secret = NULL; + int free_iv = 0, free_secret = 0; + + LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv, + session->local.crypt-> + iv_len, "A"); + if(!iv) { + ret = -1; + goto clean_exit; + } + + LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret, + session->local.crypt-> + secret_len, "C"); + + if(!secret) { + LIBSSH2_FREE(session, iv); + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + if(session->local.crypt-> + init(session, session->local.crypt, iv, &free_iv, secret, + &free_secret, 1, &session->local.crypt_abstract)) { + LIBSSH2_FREE(session, iv); + LIBSSH2_FREE(session, secret); + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + + if(free_iv) { + _libssh2_explicit_zero(iv, session->local.crypt->iv_len); + LIBSSH2_FREE(session, iv); + } + + if(free_secret) { + _libssh2_explicit_zero(secret, + session->local.crypt->secret_len); + LIBSSH2_FREE(session, secret); + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Client to Server IV and Key calculated"); + + if(session->remote.crypt->dtor) { + /* Cleanup any existing cipher */ + session->remote.crypt->dtor(session, + &session->remote.crypt_abstract); + } + + if(session->remote.crypt->init) { + unsigned char *iv = NULL, *secret = NULL; + int free_iv = 0, free_secret = 0; + + LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv, + session->remote.crypt-> + iv_len, "B"); + + if(!iv) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret, + session->remote.crypt-> + secret_len, "D"); + + if(!secret) { + LIBSSH2_FREE(session, iv); + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + if(session->remote.crypt-> + init(session, session->remote.crypt, iv, &free_iv, secret, + &free_secret, 0, &session->remote.crypt_abstract)) { + LIBSSH2_FREE(session, iv); + LIBSSH2_FREE(session, secret); + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + + if(free_iv) { + _libssh2_explicit_zero(iv, session->remote.crypt->iv_len); + LIBSSH2_FREE(session, iv); + } + + if(free_secret) { + _libssh2_explicit_zero(secret, + session->remote.crypt->secret_len); + LIBSSH2_FREE(session, secret); + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server to Client IV and Key calculated"); + + if(session->local.mac->dtor) { + session->local.mac->dtor(session, &session->local.mac_abstract); + } + + if(session->local.mac->init) { + unsigned char *key = NULL; + int free_key = 0; + + LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key, + session->local.mac-> + key_len, "E"); + + if(!key) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + session->local.mac->init(session, key, &free_key, + &session->local.mac_abstract); + + if(free_key) { + _libssh2_explicit_zero(key, session->local.mac->key_len); + LIBSSH2_FREE(session, key); + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Client to Server HMAC Key calculated"); + + if(session->remote.mac->dtor) { + session->remote.mac->dtor(session, &session->remote.mac_abstract); + } + + if(session->remote.mac->init) { + unsigned char *key = NULL; + int free_key = 0; + + LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key, + session->remote.mac-> + key_len, "F"); + + if(!key) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + session->remote.mac->init(session, key, &free_key, + &session->remote.mac_abstract); + + if(free_key) { + _libssh2_explicit_zero(key, session->remote.mac->key_len); + LIBSSH2_FREE(session, key); + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server to Client HMAC Key calculated"); + + /* Initialize compression for each direction */ + + /* Cleanup any existing compression */ + if(session->local.comp && session->local.comp->dtor) { + session->local.comp->dtor(session, 1, + &session->local.comp_abstract); + } + + if(session->local.comp && session->local.comp->init) { + if(session->local.comp->init(session, 1, + &session->local.comp_abstract)) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Client to Server compression initialized"); + + if(session->remote.comp && session->remote.comp->dtor) { + session->remote.comp->dtor(session, 0, + &session->remote.comp_abstract); + } + + if(session->remote.comp && session->remote.comp->init) { + if(session->remote.comp->init(session, 0, + &session->remote.comp_abstract)) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server to Client compression initialized"); + + } + +clean_exit: + _libssh2_bn_free(exchange_state->k); + exchange_state->k = NULL; + + if(exchange_state->k_value) { + LIBSSH2_FREE(session, exchange_state->k_value); + exchange_state->k_value = NULL; + } + + exchange_state->state = libssh2_NB_state_idle; + + return ret; +} + +/* kex_method_ecdh_key_exchange + * + * Elliptic Curve Diffie Hellman Key Exchange + * supports SHA256/384/512 hashes based on negotated ecdh method + * + */ + +static int +kex_method_ecdh_key_exchange +(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) +{ + int ret = 0; + int rc = 0; + unsigned char *s; + libssh2_curve_type type; + + if(key_state->state == libssh2_NB_state_idle) { + + key_state->public_key_oct = NULL; + key_state->state = libssh2_NB_state_created; + } + + if(key_state->state == libssh2_NB_state_created) { + rc = kex_session_ecdh_curve_type(session->kex->name, &type); + + if(rc != 0) { + ret = _libssh2_error(session, -1, + "Unknown KEX nistp curve type"); + goto ecdh_clean_exit; + } + + rc = _libssh2_ecdsa_create_key(session, &key_state->private_key, + &key_state->public_key_oct, + &key_state->public_key_oct_len, type); + + if(rc != 0) { + ret = _libssh2_error(session, rc, + "Unable to create private key"); + goto ecdh_clean_exit; + } + + key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT; + s = key_state->request + 1; + _libssh2_store_str(&s, (const char *)key_state->public_key_oct, + key_state->public_key_oct_len); + key_state->request_len = key_state->public_key_oct_len + 5; + + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Initiating ECDH SHA2 NISTP256"); + + key_state->state = libssh2_NB_state_sent; + } + + if(key_state->state == libssh2_NB_state_sent) { + rc = _libssh2_transport_send(session, key_state->request, + key_state->request_len, NULL, 0); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + ret = _libssh2_error(session, rc, + "Unable to send ECDH_INIT"); + goto ecdh_clean_exit; + } + + key_state->state = libssh2_NB_state_sent1; + } + + if(key_state->state == libssh2_NB_state_sent1) { + rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY, + &key_state->data, &key_state->data_len, + 0, NULL, 0, &key_state->req_state); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + ret = _libssh2_error(session, rc, + "Timeout waiting for ECDH_REPLY reply"); + goto ecdh_clean_exit; + } + + key_state->state = libssh2_NB_state_sent2; + } + + if(key_state->state == libssh2_NB_state_sent2) { + + (void)kex_session_ecdh_curve_type(session->kex->name, &type); + + ret = ecdh_sha2_nistp(session, type, key_state->data, + key_state->data_len, + (unsigned char *)key_state->public_key_oct, + key_state->public_key_oct_len, + key_state->private_key, + &key_state->exchange_state); + + if(ret == LIBSSH2_ERROR_EAGAIN) { + return ret; + } + + LIBSSH2_FREE(session, key_state->data); + } + +ecdh_clean_exit: + + if(key_state->public_key_oct) { + LIBSSH2_FREE(session, key_state->public_key_oct); + key_state->public_key_oct = NULL; + } + + if(key_state->private_key) { + _libssh2_ecdsa_free(key_state->private_key); + key_state->private_key = NULL; + } + + key_state->state = libssh2_NB_state_idle; + + return ret; +} + +#endif /*LIBSSH2_ECDSA*/ + + +#if LIBSSH2_ED25519 + +/* curve25519_sha256 + * Elliptic Curve Key Exchange + */ + +static int +curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data, + size_t data_len, + unsigned char public_key[LIBSSH2_ED25519_KEY_LEN], + unsigned char private_key[LIBSSH2_ED25519_KEY_LEN], + kmdhgGPshakex_state_t *exchange_state) +{ + int ret = 0; + int rc; + int public_key_len = LIBSSH2_ED25519_KEY_LEN; + + if(data_len < 5) { + return _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Data is too short"); + } + + if(exchange_state->state == libssh2_NB_state_idle) { + + /* Setup initial values */ + exchange_state->k = _libssh2_bn_init(); + + exchange_state->state = libssh2_NB_state_created; + } + + if(exchange_state->state == libssh2_NB_state_created) { + /* parse INIT reply data */ + unsigned char *server_public_key, *server_host_key; + size_t server_public_key_len, hostkey_len; + struct string_buf buf; + + if(data_len < 5) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected key length"); + goto clean_exit; + } + + buf.data = data; + buf.len = data_len; + buf.dataptr = buf.data; + buf.dataptr++; /* advance past packet type */ + + if(_libssh2_get_string(&buf, &server_host_key, &hostkey_len)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected key length"); + goto clean_exit; + } + + session->server_hostkey_len = (uint32_t)hostkey_len; + session->server_hostkey = LIBSSH2_ALLOC(session, + session->server_hostkey_len); + if(!session->server_hostkey) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for a copy " + "of the host key"); + goto clean_exit; + } + + memcpy(session->server_hostkey, server_host_key, + session->server_hostkey_len); + +#if LIBSSH2_MD5 + { + libssh2_md5_ctx fingerprint_ctx; + + if(libssh2_md5_init(&fingerprint_ctx)) { + libssh2_md5_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len); + libssh2_md5_final(fingerprint_ctx, + session->server_hostkey_md5); + session->server_hostkey_md5_valid = TRUE; + } + else { + session->server_hostkey_md5_valid = FALSE; + } + } +#ifdef LIBSSH2DEBUG + { + char fingerprint[50], *fprint = fingerprint; + int i; + for(i = 0; i < 16; i++, fprint += 3) { + snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]); + } + *(--fprint) = '\0'; + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server's MD5 Fingerprint: %s", fingerprint); + } +#endif /* LIBSSH2DEBUG */ +#endif /* ! LIBSSH2_MD5 */ + + { + libssh2_sha1_ctx fingerprint_ctx; + + if(libssh2_sha1_init(&fingerprint_ctx)) { + libssh2_sha1_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len); + libssh2_sha1_final(fingerprint_ctx, + session->server_hostkey_sha1); + session->server_hostkey_sha1_valid = TRUE; + } + else { + session->server_hostkey_sha1_valid = FALSE; + } + } +#ifdef LIBSSH2DEBUG + { + char fingerprint[64], *fprint = fingerprint; + int i; + + for(i = 0; i < 20; i++, fprint += 3) { + snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]); + } + *(--fprint) = '\0'; + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server's SHA1 Fingerprint: %s", fingerprint); + } +#endif /* LIBSSH2DEBUG */ + + /* SHA256 */ + { + libssh2_sha256_ctx fingerprint_ctx; + + if(libssh2_sha256_init(&fingerprint_ctx)) { + libssh2_sha256_update(fingerprint_ctx, session->server_hostkey, + session->server_hostkey_len); + libssh2_sha256_final(fingerprint_ctx, + session->server_hostkey_sha256); + session->server_hostkey_sha256_valid = TRUE; + } + else { + session->server_hostkey_sha256_valid = FALSE; + } + } +#ifdef LIBSSH2DEBUG + { + char *base64Fingerprint = NULL; + _libssh2_base64_encode(session, + (const char *) + session->server_hostkey_sha256, + SHA256_DIGEST_LENGTH, &base64Fingerprint); + if(base64Fingerprint != NULL) { + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server's SHA256 Fingerprint: %s", + base64Fingerprint); + LIBSSH2_FREE(session, base64Fingerprint); + } + } +#endif /* LIBSSH2DEBUG */ + + if(session->hostkey->init(session, session->server_hostkey, + session->server_hostkey_len, + &session->server_hostkey_abstract)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to initialize hostkey importer"); + goto clean_exit; + } + + /* server public key Q_S */ + if(_libssh2_get_string(&buf, &server_public_key, + &server_public_key_len)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unexpected key length"); + goto clean_exit; + } + + if(server_public_key_len != LIBSSH2_ED25519_KEY_LEN) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unexpected curve25519 server " + "public key length"); + goto clean_exit; + } + + /* server signature */ + if(_libssh2_get_string(&buf, &exchange_state->h_sig, + &(exchange_state->h_sig_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unexpected curve25519 server sig length"); + goto clean_exit; + } + + /* Compute the shared secret K */ + rc = _libssh2_curve25519_gen_k(&exchange_state->k, private_key, + server_public_key); + if(rc != 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, + "Unable to create ECDH shared secret"); + goto clean_exit; + } + + exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5; + if(_libssh2_bn_bits(exchange_state->k) % 8) { + /* don't need leading 00 */ + exchange_state->k_value_len--; + } + exchange_state->k_value = + LIBSSH2_ALLOC(session, exchange_state->k_value_len); + if(!exchange_state->k_value) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate buffer for K"); + goto clean_exit; + } + _libssh2_htonu32(exchange_state->k_value, + exchange_state->k_value_len - 4); + if(_libssh2_bn_bits(exchange_state->k) % 8) { + _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4); + } + else { + exchange_state->k_value[4] = 0; + _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5); + } + + /*/ verify hash */ + LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256); + + if(rc != 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN, + "Unable to verify hostkey signature"); + goto clean_exit; + } + + exchange_state->c = SSH_MSG_NEWKEYS; + exchange_state->state = libssh2_NB_state_sent; + } + + if(exchange_state->state == libssh2_NB_state_sent) { + rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + ret = _libssh2_error(session, rc, + "Unable to send NEWKEYS message"); + goto clean_exit; + } + + exchange_state->state = libssh2_NB_state_sent2; + } + + if(exchange_state->state == libssh2_NB_state_sent2) { + rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS, + &exchange_state->tmp, + &exchange_state->tmp_len, 0, NULL, 0, + &exchange_state->req_state); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS"); + goto clean_exit; + } + + /* The first key exchange has been performed, switch to active + crypt/comp/mac mode */ + + session->state |= LIBSSH2_STATE_NEWKEYS; + _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Received NEWKEYS message"); + + /* This will actually end up being just packet_type(1) for this packet + type anyway */ + LIBSSH2_FREE(session, exchange_state->tmp); + + if(!session->session_id) { + + size_t digest_length = SHA256_DIGEST_LENGTH; + session->session_id = LIBSSH2_ALLOC(session, digest_length); + if(!session->session_id) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allxcocate buffer for " + "SHA digest"); + goto clean_exit; + } + memcpy(session->session_id, exchange_state->h_sig_comp, + digest_length); + session->session_id_len = digest_length; + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "session_id calculated"); + } + + /* Cleanup any existing cipher */ + if(session->local.crypt->dtor) { + session->local.crypt->dtor(session, + &session->local.crypt_abstract); + } + + /* Calculate IV/Secret/Key for each direction */ + if(session->local.crypt->init) { + unsigned char *iv = NULL, *secret = NULL; + int free_iv = 0, free_secret = 0; + + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv, + session->local.crypt-> + iv_len, "A"); + if(!iv) { + ret = -1; + goto clean_exit; + } + + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret, + session->local.crypt-> + secret_len, "C"); + + if(!secret) { + LIBSSH2_FREE(session, iv); + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + if(session->local.crypt-> + init(session, session->local.crypt, iv, &free_iv, secret, + &free_secret, 1, &session->local.crypt_abstract)) { + LIBSSH2_FREE(session, iv); + LIBSSH2_FREE(session, secret); + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + + if(free_iv) { + _libssh2_explicit_zero(iv, session->local.crypt->iv_len); + LIBSSH2_FREE(session, iv); + } + + if(free_secret) { + _libssh2_explicit_zero(secret, + session->local.crypt->secret_len); + LIBSSH2_FREE(session, secret); + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Client to Server IV and Key calculated"); + + if(session->remote.crypt->dtor) { + /* Cleanup any existing cipher */ + session->remote.crypt->dtor(session, + &session->remote.crypt_abstract); + } + + if(session->remote.crypt->init) { + unsigned char *iv = NULL, *secret = NULL; + int free_iv = 0, free_secret = 0; + + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv, + session->remote.crypt-> + iv_len, "B"); + + if(!iv) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret, + session->remote.crypt-> + secret_len, "D"); + + if(!secret) { + LIBSSH2_FREE(session, iv); + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + if(session->remote.crypt-> + init(session, session->remote.crypt, iv, &free_iv, secret, + &free_secret, 0, &session->remote.crypt_abstract)) { + LIBSSH2_FREE(session, iv); + LIBSSH2_FREE(session, secret); + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + + if(free_iv) { + _libssh2_explicit_zero(iv, session->remote.crypt->iv_len); + LIBSSH2_FREE(session, iv); + } + + if(free_secret) { + _libssh2_explicit_zero(secret, + session->remote.crypt->secret_len); + LIBSSH2_FREE(session, secret); + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server to Client IV and Key calculated"); + + if(session->local.mac->dtor) { + session->local.mac->dtor(session, &session->local.mac_abstract); + } + + if(session->local.mac->init) { + unsigned char *key = NULL; + int free_key = 0; + + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key, + session->local.mac-> + key_len, "E"); + + if(!key) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + session->local.mac->init(session, key, &free_key, + &session->local.mac_abstract); + + if(free_key) { + _libssh2_explicit_zero(key, session->local.mac->key_len); + LIBSSH2_FREE(session, key); + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Client to Server HMAC Key calculated"); + + if(session->remote.mac->dtor) { + session->remote.mac->dtor(session, &session->remote.mac_abstract); + } + + if(session->remote.mac->init) { + unsigned char *key = NULL; + int free_key = 0; + + LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key, + session->remote.mac-> + key_len, "F"); + + if(!key) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + session->remote.mac->init(session, key, &free_key, + &session->remote.mac_abstract); + + if(free_key) { + _libssh2_explicit_zero(key, session->remote.mac->key_len); + LIBSSH2_FREE(session, key); + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server to Client HMAC Key calculated"); + + /* Initialize compression for each direction */ + + /* Cleanup any existing compression */ + if(session->local.comp && session->local.comp->dtor) { + session->local.comp->dtor(session, 1, + &session->local.comp_abstract); + } + + if(session->local.comp && session->local.comp->init) { + if(session->local.comp->init(session, 1, + &session->local.comp_abstract)) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Client to Server compression initialized"); + + if(session->remote.comp && session->remote.comp->dtor) { + session->remote.comp->dtor(session, 0, + &session->remote.comp_abstract); + } + + if(session->remote.comp && session->remote.comp->init) { + if(session->remote.comp->init(session, 0, + &session->remote.comp_abstract)) { + ret = LIBSSH2_ERROR_KEX_FAILURE; + goto clean_exit; + } + } + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Server to Client compression initialized"); + } + +clean_exit: + _libssh2_bn_free(exchange_state->k); + exchange_state->k = NULL; + + if(exchange_state->k_value) { + LIBSSH2_FREE(session, exchange_state->k_value); + exchange_state->k_value = NULL; + } + + exchange_state->state = libssh2_NB_state_idle; + + return ret; +} + +/* kex_method_curve25519_key_exchange + * + * Elliptic Curve X25519 Key Exchange with SHA256 hash + * + */ + +static int +kex_method_curve25519_key_exchange +(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) +{ + int ret = 0; + int rc = 0; + + if(key_state->state == libssh2_NB_state_idle) { + + key_state->public_key_oct = NULL; + key_state->state = libssh2_NB_state_created; + } + + if(key_state->state == libssh2_NB_state_created) { + unsigned char *s = NULL; + + rc = strcmp(session->kex->name, "curve25519-sha256@libssh.org"); + if(rc != 0) + rc = strcmp(session->kex->name, "curve25519-sha256"); + + if(rc != 0) { + ret = _libssh2_error(session, -1, + "Unknown KEX curve25519 curve type"); + goto clean_exit; + } + + rc = _libssh2_curve25519_new(session, NULL, + &key_state->curve25519_public_key, + &key_state->curve25519_private_key); + + if(rc != 0) { + ret = _libssh2_error(session, rc, + "Unable to create private key"); + goto clean_exit; + } + + key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT; + s = key_state->request + 1; + _libssh2_store_str(&s, (const char *)key_state->curve25519_public_key, + LIBSSH2_ED25519_KEY_LEN); + key_state->request_len = LIBSSH2_ED25519_KEY_LEN + 5; + + _libssh2_debug(session, LIBSSH2_TRACE_KEX, + "Initiating curve25519 SHA2"); + + key_state->state = libssh2_NB_state_sent; + } + + if(key_state->state == libssh2_NB_state_sent) { + rc = _libssh2_transport_send(session, key_state->request, + key_state->request_len, NULL, 0); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + ret = _libssh2_error(session, rc, + "Unable to send ECDH_INIT"); + goto clean_exit; + } + + key_state->state = libssh2_NB_state_sent1; + } + + if(key_state->state == libssh2_NB_state_sent1) { + rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY, + &key_state->data, &key_state->data_len, + 0, NULL, 0, &key_state->req_state); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return rc; + } + else if(rc) { + ret = _libssh2_error(session, rc, + "Timeout waiting for ECDH_REPLY reply"); + goto clean_exit; + } + + key_state->state = libssh2_NB_state_sent2; + } + + if(key_state->state == libssh2_NB_state_sent2) { + + ret = curve25519_sha256(session, key_state->data, key_state->data_len, + key_state->curve25519_public_key, + key_state->curve25519_private_key, + &key_state->exchange_state); + + if(ret == LIBSSH2_ERROR_EAGAIN) { + return ret; + } + + LIBSSH2_FREE(session, key_state->data); + } + +clean_exit: + + if(key_state->curve25519_public_key) { + _libssh2_explicit_zero(key_state->curve25519_public_key, + LIBSSH2_ED25519_KEY_LEN); + LIBSSH2_FREE(session, key_state->curve25519_public_key); + key_state->curve25519_public_key = NULL; + } + + if(key_state->curve25519_private_key) { + _libssh2_explicit_zero(key_state->curve25519_private_key, + LIBSSH2_ED25519_KEY_LEN); + LIBSSH2_FREE(session, key_state->curve25519_private_key); + key_state->curve25519_private_key = NULL; + } + + key_state->state = libssh2_NB_state_idle; + + return ret; +} + + +#endif /*LIBSSH2_ED25519*/ + + #define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY 0x0001 #define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY 0x0002 @@ -1731,7 +3277,54 @@ kex_method_diffie_helman_group_exchange_sha256 = { LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, }; +#if LIBSSH2_ECDSA +static const LIBSSH2_KEX_METHOD +kex_method_ecdh_sha2_nistp256 = { + "ecdh-sha2-nistp256", + kex_method_ecdh_key_exchange, + LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, +}; + +static const LIBSSH2_KEX_METHOD +kex_method_ecdh_sha2_nistp384 = { + "ecdh-sha2-nistp384", + kex_method_ecdh_key_exchange, + LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, +}; + +static const LIBSSH2_KEX_METHOD +kex_method_ecdh_sha2_nistp521 = { + "ecdh-sha2-nistp521", + kex_method_ecdh_key_exchange, + LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, +}; +#endif + +#if LIBSSH2_ED25519 +static const LIBSSH2_KEX_METHOD +kex_method_ssh_curve25519_sha256_libssh = { + "curve25519-sha256@libssh.org", + kex_method_curve25519_key_exchange, + LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, +}; +static const LIBSSH2_KEX_METHOD +kex_method_ssh_curve25519_sha256 = { + "curve25519-sha256", + kex_method_curve25519_key_exchange, + LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, +}; +#endif + static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { +#if LIBSSH2_ECDSA + &kex_method_ecdh_sha2_nistp256, + &kex_method_ecdh_sha2_nistp384, + &kex_method_ecdh_sha2_nistp521, +#endif +#if LIBSSH2_ED25519 + &kex_method_ssh_curve25519_sha256, + &kex_method_ssh_curve25519_sha256_libssh, +#endif &kex_method_diffie_helman_group_exchange_sha256, &kex_method_diffie_helman_group_exchange_sha1, &kex_method_diffie_helman_group14_sha1, @@ -1746,7 +3339,8 @@ typedef struct _LIBSSH2_COMMON_METHOD /* kex_method_strlen * Calculate the length of a particular method list's resulting string - * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1 (because the last coma isn't used) + * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1 + * (because the last coma isn't used) * Another sign of bad coding practices gone mad. Pretend you don't see this. */ static size_t @@ -1754,11 +3348,11 @@ kex_method_strlen(LIBSSH2_COMMON_METHOD ** method) { size_t len = 0; - if (!method || !*method) { + if(!method || !*method) { return 0; } - while (*method && (*method)->name) { + while(*method && (*method)->name) { len += strlen((*method)->name) + 1; method++; } @@ -1778,11 +3372,11 @@ kex_method_list(unsigned char *buf, size_t list_strlen, _libssh2_htonu32(buf, list_strlen); buf += 4; - if (!method || !*method) { + if(!method || !*method) { return 4; } - while (*method && (*method)->name) { + while(*method && (*method)->name) { int mlen = strlen((*method)->name); memcpy(buf, (*method)->name, mlen); buf += mlen; @@ -1800,12 +3394,13 @@ kex_method_list(unsigned char *buf, size_t list_strlen, kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar))) #define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \ - if (prefvar) { \ + if(prefvar) { \ _libssh2_htonu32((buf), (prefvarlen)); \ buf += 4; \ memcpy((buf), (prefvar), (prefvarlen)); \ buf += (prefvarlen); \ - } else { \ + } \ + else { \ buf += kex_method_list((buf), (prefvarlen), \ (LIBSSH2_COMMON_METHOD**)(defaultvar)); \ } @@ -1826,7 +3421,7 @@ static int kexinit(LIBSSH2_SESSION * session) unsigned char *data, *s; int rc; - if (session->kexinit_state == libssh2_NB_state_idle) { + if(session->kexinit_state == libssh2_NB_state_idle) { kex_len = LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods); hostkey_len = @@ -1860,7 +3455,7 @@ static int kexinit(LIBSSH2_SESSION * session) lang_cs_len + lang_sc_len; s = data = LIBSSH2_ALLOC(session, data_len); - if (!data) { + if(!data) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory"); } @@ -1907,7 +3502,7 @@ static int kexinit(LIBSSH2_SESSION * session) #ifdef LIBSSH2DEBUG { /* Funnily enough, they'll all "appear" to be '\0' terminated */ - unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */ + unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */ _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent KEX: %s", p); p += kex_len + 4; @@ -1933,7 +3528,8 @@ static int kexinit(LIBSSH2_SESSION * session) #endif /* LIBSSH2DEBUG */ session->kexinit_state = libssh2_NB_state_created; - } else { + } + else { data = session->kexinit_data; data_len = session->kexinit_data_len; /* zap the variables to ensure there is NOT a double free later */ @@ -1942,12 +3538,12 @@ static int kexinit(LIBSSH2_SESSION * session) } rc = _libssh2_transport_send(session, data, data_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { session->kexinit_data = data; session->kexinit_data_len = data_len; return rc; } - else if (rc) { + else if(rc) { LIBSSH2_FREE(session, data); session->kexinit_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, @@ -1955,7 +3551,7 @@ static int kexinit(LIBSSH2_SESSION * session) } - if (session->local.kexinit) { + if(session->local.kexinit) { LIBSSH2_FREE(session, session->local.kexinit); } @@ -1969,7 +3565,7 @@ static int kexinit(LIBSSH2_SESSION * session) /* kex_agree_instr * Kex specific variant of strstr() - * Needle must be preceed by BOL or ',', and followed by ',' or EOL + * Needle must be precede by BOL or ',', and followed by ',' or EOL */ static unsigned char * kex_agree_instr(unsigned char *haystack, unsigned long haystack_len, @@ -1978,12 +3574,12 @@ kex_agree_instr(unsigned char *haystack, unsigned long haystack_len, unsigned char *s; /* Haystack too short to bother trying */ - if (haystack_len < needle_len) { + if(haystack_len < needle_len) { return NULL; } /* Needle at start of haystack */ - if ((strncmp((char *) haystack, (char *) needle, needle_len) == 0) && + if((strncmp((char *) haystack, (char *) needle, needle_len) == 0) && (needle_len == haystack_len || haystack[needle_len] == ',')) { return haystack; } @@ -1991,11 +3587,11 @@ kex_agree_instr(unsigned char *haystack, unsigned long haystack_len, s = haystack; /* Search until we run out of comas or we run out of haystack, whichever comes first */ - while ((s = (unsigned char *) strchr((char *) s, ',')) + while((s = (unsigned char *) strchr((char *) s, ',')) && ((haystack_len - (s - haystack)) > needle_len)) { s++; /* Needle at X position */ - if ((strncmp((char *) s, (char *) needle, needle_len) == 0) && + if((strncmp((char *) s, (char *) needle, needle_len) == 0) && (((s - haystack) + needle_len) == haystack_len || s[needle_len] == ',')) { return s; @@ -2013,8 +3609,8 @@ static const LIBSSH2_COMMON_METHOD * kex_get_method_by_name(const char *name, size_t name_len, const LIBSSH2_COMMON_METHOD ** methodlist) { - while (*methodlist) { - if ((strlen((*methodlist)->name) == name_len) && + while(*methodlist) { + if((strlen((*methodlist)->name) == name_len) && (strncmp((*methodlist)->name, name, name_len) == 0)) { return *methodlist; } @@ -2035,31 +3631,31 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session, const LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods(); unsigned char *s; - if (session->hostkey_prefs) { + if(session->hostkey_prefs) { s = (unsigned char *) session->hostkey_prefs; - while (s && *s) { + while(s && *s) { unsigned char *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if (kex_agree_instr(hostkey, hostkey_len, s, method_len)) { + if(kex_agree_instr(hostkey, hostkey_len, s, method_len)) { const LIBSSH2_HOSTKEY_METHOD *method = (const LIBSSH2_HOSTKEY_METHOD *) kex_get_method_by_name((char *) s, method_len, (const LIBSSH2_COMMON_METHOD **) hostkeyp); - if (!method) { + if(!method) { /* Invalid method -- Should never be reached */ return -1; } /* So far so good, but does it suit our purposes? (Encrypting vs Signing) */ - if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == + if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) || (method->encrypt)) { /* Either this hostkey can do encryption or this kex just doesn't require it */ - if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) + if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) == 0) || (method->sig_verify)) { /* Either this hostkey can do signing or this kex just doesn't require it */ @@ -2074,18 +3670,18 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session, return -1; } - while (hostkeyp && (*hostkeyp) && (*hostkeyp)->name) { + while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) { s = kex_agree_instr(hostkey, hostkey_len, (unsigned char *) (*hostkeyp)->name, strlen((*hostkeyp)->name)); - if (s) { + if(s) { /* So far so good, but does it suit our purposes? (Encrypting vs Signing) */ - if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) || + if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) || ((*hostkeyp)->encrypt)) { /* Either this hostkey can do encryption or this kex just doesn't require it */ - if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) == + if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) == 0) || ((*hostkeyp)->sig_verify)) { /* Either this hostkey can do signing or this kex just doesn't require it */ @@ -2112,19 +3708,20 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods; unsigned char *s; - if (session->kex_prefs) { + if(session->kex_prefs) { s = (unsigned char *) session->kex_prefs; - while (s && *s) { + while(s && *s) { unsigned char *q, *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if ((q = kex_agree_instr(kex, kex_len, s, method_len))) { + q = kex_agree_instr(kex, kex_len, s, method_len); + if(q) { const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *) kex_get_method_by_name((char *) s, method_len, (const LIBSSH2_COMMON_METHOD **) kexp); - if (!method) { + if(!method) { /* Invalid method -- Should never be reached */ return -1; } @@ -2132,13 +3729,13 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, /* We've agreed on a key exchange method, * Can we agree on a hostkey that works with this kex? */ - if (kex_agree_hostkey(session, method->flags, hostkey, + if(kex_agree_hostkey(session, method->flags, hostkey, hostkey_len) == 0) { session->kex = method; - if (session->burn_optimistic_kexinit && (kex == q)) { - /* Server sent an optimistic packet, - * and client agrees with preference - * cancel burning the first KEX_INIT packet that comes in */ + if(session->burn_optimistic_kexinit && (kex == q)) { + /* Server sent an optimistic packet, and client agrees + * with preference cancel burning the first KEX_INIT + * packet that comes in */ session->burn_optimistic_kexinit = 0; } return 0; @@ -2150,21 +3747,21 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex, return -1; } - while (*kexp && (*kexp)->name) { + while(*kexp && (*kexp)->name) { s = kex_agree_instr(kex, kex_len, (unsigned char *) (*kexp)->name, strlen((*kexp)->name)); - if (s) { + if(s) { /* We've agreed on a key exchange method, * Can we agree on a hostkey that works with this kex? */ - if (kex_agree_hostkey(session, (*kexp)->flags, hostkey, + if(kex_agree_hostkey(session, (*kexp)->flags, hostkey, hostkey_len) == 0) { session->kex = *kexp; - if (session->burn_optimistic_kexinit && (kex == s)) { - /* Server sent an optimistic packet, - * and client agrees with preference - * cancel burning the first KEX_INIT packet that comes in */ + if(session->burn_optimistic_kexinit && (kex == s)) { + /* Server sent an optimistic packet, and client agrees + * with preference cancel burning the first KEX_INIT + * packet that comes in */ session->burn_optimistic_kexinit = 0; } return 0; @@ -2190,21 +3787,21 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session, (void) session; - if (endpoint->crypt_prefs) { + if(endpoint->crypt_prefs) { s = (unsigned char *) endpoint->crypt_prefs; - while (s && *s) { + while(s && *s) { unsigned char *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if (kex_agree_instr(crypt, crypt_len, s, method_len)) { + if(kex_agree_instr(crypt, crypt_len, s, method_len)) { const LIBSSH2_CRYPT_METHOD *method = (const LIBSSH2_CRYPT_METHOD *) kex_get_method_by_name((char *) s, method_len, (const LIBSSH2_COMMON_METHOD **) cryptp); - if (!method) { + if(!method) { /* Invalid method -- Should never be reached */ return -1; } @@ -2218,11 +3815,11 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session, return -1; } - while (*cryptp && (*cryptp)->name) { + while(*cryptp && (*cryptp)->name) { s = kex_agree_instr(crypt, crypt_len, (unsigned char *) (*cryptp)->name, strlen((*cryptp)->name)); - if (s) { + if(s) { endpoint->crypt = *cryptp; return 0; } @@ -2245,20 +3842,20 @@ static int kex_agree_mac(LIBSSH2_SESSION * session, unsigned char *s; (void) session; - if (endpoint->mac_prefs) { + if(endpoint->mac_prefs) { s = (unsigned char *) endpoint->mac_prefs; - while (s && *s) { + while(s && *s) { unsigned char *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if (kex_agree_instr(mac, mac_len, s, method_len)) { + if(kex_agree_instr(mac, mac_len, s, method_len)) { const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *) kex_get_method_by_name((char *) s, method_len, (const LIBSSH2_COMMON_METHOD **) macp); - if (!method) { + if(!method) { /* Invalid method -- Should never be reached */ return -1; } @@ -2272,10 +3869,10 @@ static int kex_agree_mac(LIBSSH2_SESSION * session, return -1; } - while (*macp && (*macp)->name) { + while(*macp && (*macp)->name) { s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name, strlen((*macp)->name)); - if (s) { + if(s) { endpoint->mac = *macp; return 0; } @@ -2298,21 +3895,21 @@ static int kex_agree_comp(LIBSSH2_SESSION *session, unsigned char *s; (void) session; - if (endpoint->comp_prefs) { + if(endpoint->comp_prefs) { s = (unsigned char *) endpoint->comp_prefs; - while (s && *s) { + while(s && *s) { unsigned char *p = (unsigned char *) strchr((char *) s, ','); size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if (kex_agree_instr(comp, comp_len, s, method_len)) { + if(kex_agree_instr(comp, comp_len, s, method_len)) { const LIBSSH2_COMP_METHOD *method = (const LIBSSH2_COMP_METHOD *) kex_get_method_by_name((char *) s, method_len, (const LIBSSH2_COMMON_METHOD **) compp); - if (!method) { + if(!method) { /* Invalid method -- Should never be reached */ return -1; } @@ -2326,10 +3923,10 @@ static int kex_agree_comp(LIBSSH2_SESSION *session, return -1; } - while (*compp && (*compp)->name) { + while(*compp && (*compp)->name) { s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name, strlen((*compp)->name)); - if (s) { + if(s) { endpoint->comp = *compp; return 0; } @@ -2360,7 +3957,7 @@ static int kex_string_pair(unsigned char **sp, /* parsing position */ /* the length of the string must fit within the current pointer and the end of the packet */ - if (*lenp > (data_len - (s - data) -4)) + if(*lenp > (data_len - (s - data) -4)) return 1; *strp = s + 4; s += 4 + *lenp; @@ -2411,30 +4008,31 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data, session->burn_optimistic_kexinit = *(s++); /* Next uint32 in packet is all zeros (reserved) */ - if (data_len < (unsigned) (s - data)) + if(data_len < (unsigned) (s - data)) return -1; /* short packet */ - if (kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) { + if(kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) { return -1; } - if (kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len) - || kex_agree_crypt(session, &session->remote, crypt_sc, crypt_sc_len)) { + if(kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len) + || kex_agree_crypt(session, &session->remote, crypt_sc, + crypt_sc_len)) { return -1; } - if (kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) || + if(kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) || kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) { return -1; } - if (kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) || + if(kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) || kex_agree_comp(session, &session->remote, comp_sc, comp_sc_len)) { return -1; } #if 0 - if (libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len) + if(libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len) || libssh2_kex_agree_lang(session, &session->remote, lang_sc, lang_sc_len)) { return -1; @@ -2478,14 +4076,14 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, session->state |= LIBSSH2_STATE_KEX_ACTIVE; - if (key_state->state == libssh2_NB_state_idle) { + if(key_state->state == libssh2_NB_state_idle) { /* Prevent loop in packet_add() */ session->state |= LIBSSH2_STATE_EXCHANGING_KEYS; - if (reexchange) { + if(reexchange) { session->kex = NULL; - if (session->hostkey && session->hostkey->dtor) { + if(session->hostkey && session->hostkey->dtor) { session->hostkey->dtor(session, &session->server_hostkey_abstract); } @@ -2495,8 +4093,8 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, key_state->state = libssh2_NB_state_created; } - if (!session->kex || !session->hostkey) { - if (key_state->state == libssh2_NB_state_created) { + if(!session->kex || !session->hostkey) { + if(key_state->state == libssh2_NB_state_created) { /* Preserve in case of failure */ key_state->oldlocal = session->local.kexinit; key_state->oldlocal_len = session->local.kexinit_len; @@ -2506,12 +4104,13 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, key_state->state = libssh2_NB_state_sent; } - if (key_state->state == libssh2_NB_state_sent) { + if(key_state->state == libssh2_NB_state_sent) { retcode = kexinit(session); - if (retcode == LIBSSH2_ERROR_EAGAIN) { + if(retcode == LIBSSH2_ERROR_EAGAIN) { session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; return retcode; - } else if (retcode) { + } + else if(retcode) { session->local.kexinit = key_state->oldlocal; session->local.kexinit_len = key_state->oldlocal_len; key_state->state = libssh2_NB_state_idle; @@ -2523,18 +4122,18 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, key_state->state = libssh2_NB_state_sent1; } - if (key_state->state == libssh2_NB_state_sent1) { + if(key_state->state == libssh2_NB_state_sent1) { retcode = _libssh2_packet_require(session, SSH_MSG_KEXINIT, &key_state->data, &key_state->data_len, 0, NULL, 0, &key_state->req_state); - if (retcode == LIBSSH2_ERROR_EAGAIN) { + if(retcode == LIBSSH2_ERROR_EAGAIN) { session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; return retcode; } - else if (retcode) { - if (session->local.kexinit) { + else if(retcode) { + if(session->local.kexinit) { LIBSSH2_FREE(session, session->local.kexinit); } session->local.kexinit = key_state->oldlocal; @@ -2545,42 +4144,45 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, return -1; } - if (session->remote.kexinit) { + if(session->remote.kexinit) { LIBSSH2_FREE(session, session->remote.kexinit); } session->remote.kexinit = key_state->data; session->remote.kexinit_len = key_state->data_len; - if (kex_agree_methods(session, key_state->data, + if(kex_agree_methods(session, key_state->data, key_state->data_len)) rc = LIBSSH2_ERROR_KEX_FAILURE; key_state->state = libssh2_NB_state_sent2; } - } else { + } + else { key_state->state = libssh2_NB_state_sent2; } - if (rc == 0 && session->kex) { - if (key_state->state == libssh2_NB_state_sent2) { + if(rc == 0 && session->kex) { + if(key_state->state == libssh2_NB_state_sent2) { retcode = session->kex->exchange_keys(session, &key_state->key_state_low); - if (retcode == LIBSSH2_ERROR_EAGAIN) { + if(retcode == LIBSSH2_ERROR_EAGAIN) { session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; return retcode; - } else if (retcode) { - rc = _libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE, + } + else if(retcode) { + rc = _libssh2_error(session, + LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE, "Unrecoverable error exchanging keys"); } } } /* Done with kexinit buffers */ - if (session->local.kexinit) { + if(session->local.kexinit) { LIBSSH2_FREE(session, session->local.kexinit); session->local.kexinit = NULL; } - if (session->remote.kexinit) { + if(session->remote.kexinit) { LIBSSH2_FREE(session, session->remote.kexinit); session->remote.kexinit = NULL; } @@ -2606,7 +4208,7 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type, int prefs_len = strlen(prefs); const LIBSSH2_COMMON_METHOD **mlist; - switch (method_type) { + switch(method_type) { case LIBSSH2_METHOD_KEX: prefvar = &session->kex_prefs; mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods; @@ -2665,40 +4267,43 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type, } s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1); - if (!newprefs) { + if(!newprefs) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocated space for method preferences"); } memcpy(s, prefs, prefs_len + 1); - while (s && *s && mlist) { + while(s && *s && mlist) { char *p = strchr(s, ','); int method_len = p ? (p - s) : (int) strlen(s); - if (!kex_get_method_by_name(s, method_len, mlist)) { + if(!kex_get_method_by_name(s, method_len, mlist)) { /* Strip out unsupported method */ - if (p) { + if(p) { memcpy(s, p + 1, strlen(s) - method_len); - } else { - if (s > newprefs) { + } + else { + if(s > newprefs) { *(--s) = '\0'; - } else { + } + else { *s = '\0'; } } } - - s = p ? (p + 1) : NULL; + else { + s = p ? (p + 1) : NULL; + } } - if (strlen(newprefs) == 0) { + if(strlen(newprefs) == 0) { LIBSSH2_FREE(session, newprefs); return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, "The requested method(s) are not currently " "supported"); } - if (*prefvar) { + if(*prefvar) { LIBSSH2_FREE(session, *prefvar); } *prefvar = newprefs; @@ -2714,7 +4319,7 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type, LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, int method_type, - const char*** algs) + const char ***algs) { unsigned int i; unsigned int j; @@ -2722,11 +4327,11 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, const LIBSSH2_COMMON_METHOD **mlist; /* to prevent coredumps due to dereferencing of NULL */ - if (NULL == algs) + if(NULL == algs) return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, "algs must not be NULL"); - switch (method_type) { + switch(method_type) { case LIBSSH2_METHOD_KEX: mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods; break; @@ -2747,7 +4352,8 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, case LIBSSH2_METHOD_COMP_CS: case LIBSSH2_METHOD_COMP_SC: - mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods(session); + mlist = (const LIBSSH2_COMMON_METHOD **) + _libssh2_comp_methods(session); break; default: @@ -2756,7 +4362,7 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, } /* switch */ /* weird situation */ - if (NULL==mlist) + if(NULL == mlist) return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "No algorithm found"); @@ -2773,28 +4379,28 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, */ /* count the number of supported algorithms */ - for ( i=0, ialg=0; NULL!=mlist[i]; i++) { + for(i = 0, ialg = 0; NULL != mlist[i]; i++) { /* do not count fields with NULL name */ - if (mlist[i]->name) + if(mlist[i]->name) ialg++; } /* weird situation, no algorithm found */ - if (0==ialg) + if(0 == ialg) return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "No algorithm found"); /* allocate buffer */ - *algs = (const char**) LIBSSH2_ALLOC(session, ialg*sizeof(const char*)); - if ( NULL==*algs ) { + *algs = (const char **) LIBSSH2_ALLOC(session, ialg*sizeof(const char *)); + if(NULL == *algs) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Memory allocation failed"); } /* Past this point *algs must be deallocated in case of an error!! */ /* copy non-NULL pointers only */ - for ( i=0, j=0; NULL!=mlist[i] && jname ){ + for(i = 0, j = 0; NULL != mlist[i] && j < ialg; i++) { + if(NULL == mlist[i]->name) { /* maybe a weird situation but if it occurs, do not include NULL pointers */ continue; @@ -2805,7 +4411,7 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, } /* correct number of pointers copied? (test the code above) */ - if ( j!=ialg ) { + if(j != ialg) { /* deallocate buffer */ LIBSSH2_FREE(session, (void *)*algs); *algs = NULL; diff --git a/libssh2/src/knownhost.c b/libssh2/src/knownhost.c index a32dcf876..b9dc47a80 100644 --- a/libssh2/src/knownhost.c +++ b/libssh2/src/knownhost.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2014 by Daniel Stenberg + * Copyright (c) 2009-2019 by Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -71,7 +71,7 @@ static void free_host(LIBSSH2_SESSION *session, struct known_host *entry) if(entry) { if(entry->comment) LIBSSH2_FREE(session, entry->comment); - if (entry->key_type_name) + if(entry->key_type_name) LIBSSH2_FREE(session, entry->key_type_name); if(entry->key) LIBSSH2_FREE(session, entry->key); @@ -149,7 +149,8 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL, "No key type set"); - if(!(entry = LIBSSH2_CALLOC(hosts->session, sizeof(struct known_host)))) + entry = LIBSSH2_CALLOC(hosts->session, sizeof(struct known_host)); + if(!entry) return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for known host " "entry"); @@ -159,13 +160,13 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, switch(entry->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) { case LIBSSH2_KNOWNHOST_TYPE_PLAIN: case LIBSSH2_KNOWNHOST_TYPE_CUSTOM: - entry->name = LIBSSH2_ALLOC(hosts->session, hostlen+1); + entry->name = LIBSSH2_ALLOC(hosts->session, hostlen + 1); if(!entry->name) { rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for host name"); goto error; } - memcpy(entry->name, host, hostlen+1); + memcpy(entry->name, host, hostlen + 1); entry->name_len = hostlen; break; case LIBSSH2_KNOWNHOST_TYPE_SHA1: @@ -193,14 +194,14 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, /* the provided key is base64 encoded already */ if(!keylen) keylen = strlen(key); - entry->key = LIBSSH2_ALLOC(hosts->session, keylen+1); + entry->key = LIBSSH2_ALLOC(hosts->session, keylen + 1); if(!entry->key) { rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for key"); goto error; } - memcpy(entry->key, key, keylen+1); - entry->key[keylen]=0; /* force a terminating zero trailer */ + memcpy(entry->key, key, keylen + 1); + entry->key[keylen] = 0; /* force a terminating zero trailer */ } else { /* key is raw, we base64 encode it and store it as such */ @@ -216,28 +217,28 @@ knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, entry->key = ptr; } - if (key_type_name && ((typemask & LIBSSH2_KNOWNHOST_KEY_MASK) == + if(key_type_name && ((typemask & LIBSSH2_KNOWNHOST_KEY_MASK) == LIBSSH2_KNOWNHOST_KEY_UNKNOWN)) { - entry->key_type_name = LIBSSH2_ALLOC(hosts->session, key_type_len+1); - if (!entry->key_type_name) { + entry->key_type_name = LIBSSH2_ALLOC(hosts->session, key_type_len + 1); + if(!entry->key_type_name) { rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for key type"); goto error; } memcpy(entry->key_type_name, key_type_name, key_type_len); - entry->key_type_name[key_type_len]=0; + entry->key_type_name[key_type_len] = 0; entry->key_type_len = key_type_len; } - if (comment) { - entry->comment = LIBSSH2_ALLOC(hosts->session, commentlen+1); + if(comment) { + entry->comment = LIBSSH2_ALLOC(hosts->session, commentlen + 1); if(!entry->comment) { rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for comment"); goto error; } - memcpy(entry->comment, comment, commentlen+1); - entry->comment[commentlen]=0; /* force a terminating zero trailer */ + memcpy(entry->comment, comment, commentlen + 1); + entry->comment[commentlen] = 0; /* force a terminating zero trailer */ entry->comment_len = commentlen; } else { @@ -370,7 +371,7 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, plain 'host' */ if(port >= 0) { int len = snprintf(hostbuff, sizeof(hostbuff), "[%s]:%d", hostp, port); - if (len < 0 || len >= (int)sizeof(hostbuff)) { + if(len < 0 || len >= (int)sizeof(hostbuff)) { _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, "Known-host write buffer too small"); @@ -401,7 +402,7 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, do { node = _libssh2_list_first(&hosts->head); - while (node) { + while(node) { switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) { case LIBSSH2_KNOWNHOST_TYPE_PLAIN: if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) @@ -450,13 +451,13 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, - if key_type is set to zero, ignore it an match always - otherwise match when both key types are equal */ - if ( (host_key_type != LIBSSH2_KNOWNHOST_KEY_UNKNOWN ) && - ( (host_key_type == 0) || - (host_key_type == known_key_type) ) ) { + if(host_key_type != LIBSSH2_KNOWNHOST_KEY_UNKNOWN && + (host_key_type == 0 || + host_key_type == known_key_type)) { /* host name and key type match, now compare the keys */ if(!strcmp(key, node->key)) { /* they match! */ - if (ext) + if(ext) *ext = knownhost_to_external(node); badkey = NULL; rc = LIBSSH2_KNOWNHOST_CHECK_MATCH; @@ -472,14 +473,14 @@ knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, } match = 0; /* don't count this as a match anymore */ } - node= _libssh2_list_next(&node->node); + node = _libssh2_list_next(&node->node); } host = hostp; } while(!match && --numcheck); if(badkey) { /* key mismatch */ - if (ext) + if(ext) *ext = knownhost_to_external(badkey); rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH; } @@ -646,7 +647,7 @@ static int oldstyle_hostline(LIBSSH2_KNOWNHOSTS *hosts, /* copy host name to the temp buffer and zero terminate */ memcpy(hostbuf, name, namelen); - hostbuf[namelen]=0; + hostbuf[namelen] = 0; rc = knownhost_add(hosts, hostbuf, NULL, key_type_name, key_type_len, @@ -685,7 +686,7 @@ static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts, for(p = salt; *p && (*p != '|'); p++) ; - if(*p=='|') { + if(*p == '|') { const char *hash = NULL; size_t saltlen = p - salt; if(saltlen >= (sizeof(saltbuf)-1)) /* weird length */ @@ -698,11 +699,11 @@ static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts, saltbuf[saltlen] = 0; /* zero terminate */ salt = saltbuf; /* point to the stack based buffer */ - hash = p+1; /* the host hash is after the separator */ + hash = p + 1; /* the host hash is after the separator */ /* now make the host point to the hash */ host = hash; - hostlen -= saltlen+1; /* deduct the salt and separator */ + hostlen -= saltlen + 1; /* deduct the salt and separator */ /* check that the lengths seem sensible */ if(hostlen >= sizeof(hostbuf)-1) @@ -712,7 +713,7 @@ static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts, "(unexpected length)"); memcpy(hostbuf, host, hostlen); - hostbuf[hostlen]=0; + hostbuf[hostlen] = 0; return knownhost_add(hosts, hostbuf, salt, key_type_name, key_type_len, @@ -766,17 +767,25 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts, default: key_type_name = key; - while (keylen && *key && + while(keylen && *key && (*key != ' ') && (*key != '\t')) { key++; keylen--; } key_type_len = key - key_type_name; - if (!strncmp(key_type_name, "ssh-dss", key_type_len)) + if(!strncmp(key_type_name, "ssh-dss", key_type_len)) key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS; - else if (!strncmp(key_type_name, "ssh-rsa", key_type_len)) + else if(!strncmp(key_type_name, "ssh-rsa", key_type_len)) key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA; + else if(!strncmp(key_type_name, "ecdsa-sha2-nistp256", key_type_len)) + key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_256; + else if(!strncmp(key_type_name, "ecdsa-sha2-nistp384", key_type_len)) + key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_384; + else if(!strncmp(key_type_name, "ecdsa-sha2-nistp521", key_type_len)) + key_type = LIBSSH2_KNOWNHOST_KEY_ECDSA_521; + else if(!strncmp(key_type_name, "ssh-ed25519", key_type_len)) + key_type = LIBSSH2_KNOWNHOST_KEY_ED25519; else key_type = LIBSSH2_KNOWNHOST_KEY_UNKNOWN; @@ -800,7 +809,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts, keylen -= commentlen; /* Distinguish empty comment (a space) from no comment (no space) */ - if (commentlen == 0) + if(commentlen == 0) comment = NULL; /* skip whitespaces */ @@ -879,7 +888,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts, cp = line; /* skip leading whitespaces */ - while(len && ((*cp==' ') || (*cp == '\t'))) { + while(len && ((*cp == ' ') || (*cp == '\t'))) { cp++; len--; } @@ -892,7 +901,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts, hostp = cp; /* move over the host to the separator */ - while(len && *cp && (*cp!=' ') && (*cp != '\t')) { + while(len && *cp && (*cp != ' ') && (*cp != '\t')) { cp++; len--; } @@ -900,7 +909,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts, hostlen = cp - hostp; /* the key starts after the whitespaces */ - while(len && *cp && ((*cp==' ') || (*cp == '\t'))) { + while(len && *cp && ((*cp == ' ') || (*cp == '\t'))) { cp++; len--; } @@ -954,7 +963,7 @@ libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts, "Unsupported type of known-host information " "store"); - file = fopen(filename, "r"); + file = fopen(filename, FOPEN_READTEXT); if(file) { while(fgets(buf, sizeof(buf), file)) { if(libssh2_knownhost_readline(hosts, buf, strlen(buf), type)) { @@ -1016,13 +1025,30 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, key_type_name = "ssh-dss"; key_type_len = 7; break; + case LIBSSH2_KNOWNHOST_KEY_ECDSA_256: + key_type_name = "ecdsa-sha2-nistp256"; + key_type_len = 19; + break; + case LIBSSH2_KNOWNHOST_KEY_ECDSA_384: + key_type_name = "ecdsa-sha2-nistp384"; + key_type_len = 19; + break; + case LIBSSH2_KNOWNHOST_KEY_ECDSA_521: + key_type_name = "ecdsa-sha2-nistp521"; + key_type_len = 19; + break; + case LIBSSH2_KNOWNHOST_KEY_ED25519: + key_type_name = "ssh-ed25519"; + key_type_len = 11; + break; case LIBSSH2_KNOWNHOST_KEY_UNKNOWN: key_type_name = node->key_type_name; - if (key_type_name) { + if(key_type_name) { key_type_len = node->key_type_len; break; } /* otherwise fallback to default and error */ + /* FALL-THROUGH */ default: return _libssh2_error(hosts->session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, @@ -1033,7 +1059,7 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, - Hashed (SHA1) or unhashed hostname - key name or no key name (RSA1) - comment or no comment - + This means there are 2^3 different formats: ("|1|%s|%s %s %s %s\n", salt, hashed_host, key_name, key, comment) ("|1|%s|%s %s %s\n", salt, hashed_host, key_name, key) @@ -1043,7 +1069,7 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, ("%s %s %s\n", host, key_name, key) ("%s %s %s\n", host, key, comment) ("%s %s\n", host, key) - + Even if the buffer is too small, we have to set outlen to the number of characters the complete line would have taken. We also don't write anything to the buffer unless we are sure we can write everything to the @@ -1087,10 +1113,10 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, if(node->comment && key_type_len) snprintf(buf, buflen, "|1|%s|%s %s %s %s\n", saltalloc, namealloc, key_type_name, node->key, node->comment); - else if (node->comment) + else if(node->comment) snprintf(buf, buflen, "|1|%s|%s %s %s\n", saltalloc, namealloc, node->key, node->comment); - else if (key_type_len) + else if(key_type_len) snprintf(buf, buflen, "|1|%s|%s %s %s\n", saltalloc, namealloc, key_type_name, node->key); else @@ -1109,10 +1135,10 @@ knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, if(node->comment && key_type_len) snprintf(buf, buflen, "%s %s %s %s\n", node->name, key_type_name, node->key, node->comment); - else if (node->comment) + else if(node->comment) snprintf(buf, buflen, "%s %s %s\n", node->name, node->key, node->comment); - else if (key_type_len) + else if(key_type_len) snprintf(buf, buflen, "%s %s %s\n", node->name, key_type_name, node->key); else @@ -1178,7 +1204,7 @@ libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts, "Unsupported type of known-host information " "store"); - file = fopen(filename, "w"); + file = fopen(filename, FOPEN_WRITETEXT); if(!file) return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE, "Failed to open file"); diff --git a/libssh2/src/libgcrypt.c b/libssh2/src/libgcrypt.c index 366d007a3..0aff176a6 100644 --- a/libssh2/src/libgcrypt.c +++ b/libssh2/src/libgcrypt.c @@ -66,17 +66,18 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, (void) e2data; (void) e2len; - if (ddata) { + if(ddata) { rc = gcry_sexp_build (rsa, NULL, "(private-key(rsa(n%b)(e%b)(d%b)(q%b)(p%b)(u%b)))", nlen, ndata, elen, edata, dlen, ddata, plen, pdata, qlen, qdata, coefflen, coeffdata); - } else { + } + else { rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))", nlen, ndata, elen, edata); } - if (rc) { + if(rc) { *rsa = NULL; return -1; } @@ -99,12 +100,12 @@ _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa, rc = gcry_sexp_build(&s_hash, NULL, "(data (flags pkcs1) (hash sha1 %b))", SHA_DIGEST_LENGTH, hash); - if (rc != 0) { + if(rc != 0) { return -1; } rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig); - if (rc != 0) { + if(rc != 0) { gcry_sexp_release(s_hash); return -1; } @@ -130,18 +131,19 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, { int rc; - if (x_len) { + if(x_len) { rc = gcry_sexp_build (dsactx, NULL, "(private-key(dsa(p%b)(q%b)(g%b)(y%b)(x%b)))", p_len, p, q_len, q, g_len, g, y_len, y, x_len, x); - } else { + } + else { rc = gcry_sexp_build(dsactx, NULL, "(public-key(dsa(p%b)(q%b)(g%b)(y%b)))", p_len, p, q_len, q, g_len, g, y_len, y); } - if (rc) { + if(rc) { *dsactx = NULL; return -1; } @@ -172,84 +174,83 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, unsigned char *n, *e, *d, *p, *q, *e1, *e2, *coeff; unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen; - (void) passphrase; - - fp = fopen(filename, "r"); - if (!fp) { + fp = fopen(filename, FOPEN_READTEXT); + if(!fp) { return -1; } ret = _libssh2_pem_parse(session, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----", + passphrase, fp, &data, &datalen); fclose(fp); - if (ret) { + if(ret) { return -1; } save_data = data; - if (_libssh2_pem_decode_sequence(&data, &datalen)) { + if(_libssh2_pem_decode_sequence(&data, &datalen)) { ret = -1; goto fail; } /* First read Version field (should be 0). */ ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen); - if (ret != 0 || (nlen != 1 && *n != '\0')) { + if(ret != 0 || (nlen != 1 && *n != '\0')) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &e, &elen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &d, &dlen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &e1, &e1len); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &e2, &e2len); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &coeff, &coefflen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } - if (_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen, + if(_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen, q, qlen, e1, e1len, e2, e2len, coeff, coefflen)) { ret = -1; goto fail; @@ -285,72 +286,71 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, unsigned char *p, *q, *g, *y, *x; unsigned int plen, qlen, glen, ylen, xlen; - (void) passphrase; - - fp = fopen(filename, "r"); - if (!fp) { + fp = fopen(filename, FOPEN_READTEXT); + if(!fp) { return -1; } ret = _libssh2_pem_parse(session, "-----BEGIN DSA PRIVATE KEY-----", "-----END DSA PRIVATE KEY-----", + passphrase, fp, &data, &datalen); fclose(fp); - if (ret) { + if(ret) { return -1; } save_data = data; - if (_libssh2_pem_decode_sequence(&data, &datalen)) { + if(_libssh2_pem_decode_sequence(&data, &datalen)) { ret = -1; goto fail; } /* First read Version field (should be 0). */ ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen); - if (ret != 0 || (plen != 1 && *p != '\0')) { + if(ret != 0 || (plen != 1 && *p != '\0')) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &g, &glen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &y, &ylen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } ret = _libssh2_pem_decode_integer(&data, &datalen, &x, &xlen); - if (ret != 0) { + if(ret != 0) { ret = -1; goto fail; } - if (datalen != 0) { + if(datalen != 0) { ret = -1; goto fail; } - if (_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) { + if(_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) { ret = -1; goto fail; } @@ -375,11 +375,11 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, const char *tmp; size_t size; - if (hash_len != SHA_DIGEST_LENGTH) { + if(hash_len != SHA_DIGEST_LENGTH) { return -1; } - if (gcry_sexp_build(&data, NULL, + if(gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))", hash_len, hash)) { return -1; @@ -389,32 +389,36 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, gcry_sexp_release(data); - if (rc != 0) { + if(rc != 0) { return -1; } data = gcry_sexp_find_token(sig_sexp, "s", 0); - if (!data) { + if(!data) { return -1; } tmp = gcry_sexp_nth_data(data, 1, &size); - if (!tmp) { + if(!tmp) { + gcry_sexp_release(data); return -1; } - if (tmp[0] == '\0') { + if(tmp[0] == '\0') { tmp++; size--; } *signature = LIBSSH2_ALLOC(session, size); - if (!*signature) { + if(!*signature) { + gcry_sexp_release(data); return -1; } memcpy(*signature, tmp, size); *signature_len = size; + gcry_sexp_release(data); + return rc; } @@ -430,14 +434,15 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, const char *tmp; size_t size; - if (hash_len != SHA_DIGEST_LENGTH) { + if(hash_len != SHA_DIGEST_LENGTH) { return -1; } memcpy(zhash + 1, hash, hash_len); zhash[0] = 0; - if (gcry_sexp_build(&data, NULL, "(data (value %b))", hash_len + 1, zhash)) { + if(gcry_sexp_build(&data, NULL, "(data (value %b))", + hash_len + 1, zhash)) { return -1; } @@ -445,7 +450,7 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, gcry_sexp_release(data); - if (ret != 0) { + if(ret != 0) { return -1; } @@ -454,19 +459,19 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, /* Extract R. */ data = gcry_sexp_find_token(sig_sexp, "r", 0); - if (!data) + if(!data) goto err; tmp = gcry_sexp_nth_data(data, 1, &size); - if (!tmp) + if(!tmp) goto err; - if (tmp[0] == '\0') { + if(tmp[0] == '\0') { tmp++; size--; } - if (size < 1 || size > 20) + if(size < 1 || size > 20) goto err; memcpy(sig + (20 - size), tmp, size); @@ -476,19 +481,19 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, /* Extract S. */ data = gcry_sexp_find_token(sig_sexp, "s", 0); - if (!data) + if(!data) goto err; tmp = gcry_sexp_nth_data(data, 1, &size); - if (!tmp) + if(!tmp) goto err; - if (tmp[0] == '\0') { + if(tmp[0] == '\0') { tmp++; size--; } - if (size < 1 || size > 20) + if(size < 1 || size > 20) goto err; memcpy(sig + 20 + (20 - size), tmp, size); @@ -498,10 +503,10 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, ret = -1; out: - if (sig_sexp) { + if(sig_sexp) { gcry_sexp_release(sig_sexp); } - if (data) { + if(data) { gcry_sexp_release(data); } return ret; @@ -519,12 +524,12 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, libssh2_sha1(m, m_len, hash + 1); hash[0] = 0; - if (gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))", + if(gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))", SHA_DIGEST_LENGTH + 1, hash)) { return -1; } - if (gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r %b)(s %b)))", + if(gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r %b)(s %b)))", 20, sig, 20, sig + 20)) { gcry_sexp_release(s_hash); return -1; @@ -543,30 +548,30 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h, unsigned char *iv, unsigned char *secret, int encrypt) { int ret; - int cipher = _libssh2_gcry_cipher (algo); - int mode = _libssh2_gcry_mode (algo); + int cipher = _libssh2_gcry_cipher(algo); + int mode = _libssh2_gcry_mode(algo); int keylen = gcry_cipher_get_algo_keylen(cipher); (void) encrypt; ret = gcry_cipher_open(h, cipher, mode, 0); - if (ret) { + if(ret) { return -1; } ret = gcry_cipher_setkey(*h, secret, keylen); - if (ret) { + if(ret) { gcry_cipher_close(*h); return -1; } - if (mode != GCRY_CIPHER_MODE_STREAM) { + if(mode != GCRY_CIPHER_MODE_STREAM) { int blklen = gcry_cipher_get_algo_blklen(cipher); - if (mode == GCRY_CIPHER_MODE_CTR) + if(mode == GCRY_CIPHER_MODE_CTR) ret = gcry_cipher_setctr(*h, iv, blklen); else ret = gcry_cipher_setiv(*h, iv, blklen); - if (ret) { + if(ret) { gcry_cipher_close(*h); return -1; } @@ -580,12 +585,13 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, _libssh2_cipher_type(algo), int encrypt, unsigned char *block, size_t blklen) { - int cipher = _libssh2_gcry_cipher (algo); + int cipher = _libssh2_gcry_cipher(algo); int ret; - if (encrypt) { + if(encrypt) { ret = gcry_cipher_encrypt(*ctx, block, blklen, block, blklen); - } else { + } + else { ret = gcry_cipher_decrypt(*ctx, block, blklen, block, blklen); } return ret; @@ -602,8 +608,9 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, const char *passphrase) { return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unable to extract public key from private key in memory: " - "Method unimplemented in libgcrypt backend"); + "Unable to extract public key from private " + "key in memory: " + "Method unimplemented in libgcrypt backend"); } int @@ -624,4 +631,37 @@ void _libssh2_init_aes_ctr(void) { /* no implementation */ } + +void +_libssh2_dh_init(_libssh2_dh_ctx *dhctx) +{ + *dhctx = gcry_mpi_new(0); /* Random from client */ +} + +int +_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, + _libssh2_bn *g, _libssh2_bn *p, int group_order) +{ + /* Generate x and e */ + gcry_mpi_randomize(*dhctx, group_order * 8 - 1, GCRY_WEAK_RANDOM); + gcry_mpi_powm(public, g, *dhctx, p); + return 0; +} + +int +_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p) +{ + /* Compute the shared secret */ + gcry_mpi_powm(secret, f, *dhctx, p); + return 0; +} + +void +_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx) +{ + gcry_mpi_release(*dhctx); + *dhctx = NULL; +} + #endif /* LIBSSH2_LIBGCRYPT */ diff --git a/libssh2/src/libgcrypt.h b/libssh2/src/libgcrypt.h index 11d6ad2dc..ec88aded6 100644 --- a/libssh2/src/libgcrypt.h +++ b/libssh2/src/libgcrypt.h @@ -54,10 +54,16 @@ #define LIBSSH2_RSA 1 #define LIBSSH2_DSA 1 +#define LIBSSH2_ECDSA 0 +#define LIBSSH2_ED25519 0 #define MD5_DIGEST_LENGTH 16 #define SHA_DIGEST_LENGTH 20 #define SHA256_DIGEST_LENGTH 32 +#define SHA384_DIGEST_LENGTH 48 +#define SHA512_DIGEST_LENGTH 64 + +#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) #define _libssh2_random(buf, len) \ (gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1) @@ -68,60 +74,82 @@ /* returns 0 in case of failure */ #define libssh2_sha1_init(ctx) \ - (GPG_ERR_NO_ERROR == gcry_md_open (ctx, GCRY_MD_SHA1, 0)) + (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_SHA1, 0)) #define libssh2_sha1_update(ctx, data, len) \ - gcry_md_write (ctx, (unsigned char *) data, len) + gcry_md_write(ctx, (unsigned char *) data, len) #define libssh2_sha1_final(ctx, out) \ - memcpy (out, gcry_md_read (ctx, 0), SHA_DIGEST_LENGTH), gcry_md_close (ctx) + memcpy(out, gcry_md_read(ctx, 0), SHA_DIGEST_LENGTH), gcry_md_close(ctx) #define libssh2_sha1(message, len, out) \ - gcry_md_hash_buffer (GCRY_MD_SHA1, out, message, len) + gcry_md_hash_buffer(GCRY_MD_SHA1, out, message, len) #define libssh2_sha256_ctx gcry_md_hd_t #define libssh2_sha256_init(ctx) \ - (GPG_ERR_NO_ERROR == gcry_md_open (ctx, GCRY_MD_SHA256, 0)) + (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_SHA256, 0)) #define libssh2_sha256_update(ctx, data, len) \ - gcry_md_write (ctx, (unsigned char *) data, len) + gcry_md_write(ctx, (unsigned char *) data, len) #define libssh2_sha256_final(ctx, out) \ - memcpy (out, gcry_md_read (ctx, 0), SHA256_DIGEST_LENGTH), gcry_md_close (ctx) + memcpy(out, gcry_md_read(ctx, 0), SHA256_DIGEST_LENGTH), gcry_md_close(ctx) #define libssh2_sha256(message, len, out) \ - gcry_md_hash_buffer (GCRY_MD_SHA256, out, message, len) + gcry_md_hash_buffer(GCRY_MD_SHA256, out, message, len) + +#define libssh2_sha384_ctx gcry_md_hd_t + +#define libssh2_sha384_init(ctx) \ + (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_SHA384, 0)) +#define libssh2_sha384_update(ctx, data, len) \ + gcry_md_write(ctx, (unsigned char *) data, len) +#define libssh2_sha384_final(ctx, out) \ + memcpy(out, gcry_md_read(ctx, 0), SHA384_DIGEST_LENGTH), gcry_md_close(ctx) +#define libssh2_sha384(message, len, out) \ + gcry_md_hash_buffer(GCRY_MD_SHA384, out, message, len) + +#define libssh2_sha512_ctx gcry_md_hd_t + +#define libssh2_sha512_init(ctx) \ + (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_SHA512, 0)) +#define libssh2_sha512_update(ctx, data, len) \ + gcry_md_write(ctx, (unsigned char *) data, len) +#define libssh2_sha512_final(ctx, out) \ + memcpy(out, gcry_md_read(ctx, 0), SHA512_DIGEST_LENGTH), gcry_md_close(ctx) +#define libssh2_sha512(message, len, out) \ + gcry_md_hash_buffer(GCRY_MD_SHA512, out, message, len) #define libssh2_md5_ctx gcry_md_hd_t /* returns 0 in case of failure */ #define libssh2_md5_init(ctx) \ - (GPG_ERR_NO_ERROR == gcry_md_open (ctx, GCRY_MD_MD5, 0)) + (GPG_ERR_NO_ERROR == gcry_md_open(ctx, GCRY_MD_MD5, 0)) #define libssh2_md5_update(ctx, data, len) \ - gcry_md_write (ctx, (unsigned char *) data, len) + gcry_md_write(ctx, (unsigned char *) data, len) #define libssh2_md5_final(ctx, out) \ - memcpy (out, gcry_md_read (ctx, 0), MD5_DIGEST_LENGTH), gcry_md_close (ctx) + memcpy(out, gcry_md_read(ctx, 0), MD5_DIGEST_LENGTH), gcry_md_close(ctx) #define libssh2_md5(message, len, out) \ - gcry_md_hash_buffer (GCRY_MD_MD5, out, message, len) + gcry_md_hash_buffer(GCRY_MD_MD5, out, message, len) #define libssh2_hmac_ctx gcry_md_hd_t #define libssh2_hmac_ctx_init(ctx) #define libssh2_hmac_sha1_init(ctx, key, keylen) \ - gcry_md_open (ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey (*ctx, key, keylen) + gcry_md_open(ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC), \ + gcry_md_setkey(*ctx, key, keylen) #define libssh2_hmac_md5_init(ctx, key, keylen) \ - gcry_md_open (ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey (*ctx, key, keylen) + gcry_md_open(ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC), \ + gcry_md_setkey(*ctx, key, keylen) #define libssh2_hmac_ripemd160_init(ctx, key, keylen) \ - gcry_md_open (ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey (*ctx, key, keylen) + gcry_md_open(ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC), \ + gcry_md_setkey(*ctx, key, keylen) #define libssh2_hmac_sha256_init(ctx, key, keylen) \ - gcry_md_open (ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey (*ctx, key, keylen) + gcry_md_open(ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC), \ + gcry_md_setkey(*ctx, key, keylen) #define libssh2_hmac_sha512_init(ctx, key, keylen) \ - gcry_md_open (ctx, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC), \ - gcry_md_setkey (*ctx, key, keylen) + gcry_md_open(ctx, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC), \ + gcry_md_setkey(*ctx, key, keylen) #define libssh2_hmac_update(ctx, data, datalen) \ - gcry_md_write (ctx, (unsigned char *) data, datalen) + gcry_md_write(ctx, (unsigned char *) data, datalen) #define libssh2_hmac_final(ctx, data) \ - memcpy (data, gcry_md_read (ctx, 0), \ - gcry_md_get_algo_dlen (gcry_md_get_algo (ctx))) + memcpy(data, gcry_md_read(ctx, 0), \ + gcry_md_get_algo_dlen(gcry_md_get_algo(ctx))) #define libssh2_hmac_cleanup(ctx) gcry_md_close (*ctx); #define libssh2_crypto_init() gcry_control (GCRYCTL_DISABLE_SECMEM) @@ -135,6 +163,11 @@ #define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx) +#if LIBSSH2_ECDSA +#else +#define _libssh2_ec_key void +#endif + #define _libssh2_cipher_type(name) int name #define _libssh2_cipher_ctx gcry_cipher_hd_t @@ -171,13 +204,31 @@ #define _libssh2_bn_ctx_new() 0 #define _libssh2_bn_ctx_free(bnctx) ((void)0) #define _libssh2_bn_init() gcry_mpi_new(0) -#define _libssh2_bn_init_from_bin() NULL /* because gcry_mpi_scan() creates a new bignum */ -#define _libssh2_bn_rand(bn, bits, top, bottom) gcry_mpi_randomize (bn, bits, GCRY_WEAK_RANDOM) -#define _libssh2_bn_mod_exp(r, a, p, m, ctx) gcry_mpi_powm (r, a, p, m) +#define _libssh2_bn_init_from_bin() NULL /* because gcry_mpi_scan() creates a + new bignum */ #define _libssh2_bn_set_word(bn, val) gcry_mpi_set_ui(bn, val) -#define _libssh2_bn_from_bin(bn, len, val) gcry_mpi_scan(&((bn)), GCRYMPI_FMT_USG, val, len, NULL) -#define _libssh2_bn_to_bin(bn, val) gcry_mpi_print (GCRYMPI_FMT_USG, val, _libssh2_bn_bytes(bn), NULL, bn) -#define _libssh2_bn_bytes(bn) (gcry_mpi_get_nbits (bn) / 8 + ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1)) +#define _libssh2_bn_from_bin(bn, len, val) \ + gcry_mpi_scan(&((bn)), GCRYMPI_FMT_USG, val, len, NULL) +#define _libssh2_bn_to_bin(bn, val) \ + gcry_mpi_print(GCRYMPI_FMT_USG, val, _libssh2_bn_bytes(bn), NULL, bn) +#define _libssh2_bn_bytes(bn) \ + (gcry_mpi_get_nbits (bn) / 8 + \ + ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1)) #define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn) #define _libssh2_bn_free(bn) gcry_mpi_release(bn) +#define _libssh2_dh_ctx struct gcry_mpi * +#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx) +#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \ + _libssh2_dh_key_pair(dhctx, public, g, p, group_order) +#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \ + _libssh2_dh_secret(dhctx, secret, f, p) +#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx) +extern void _libssh2_dh_init(_libssh2_dh_ctx *dhctx); +extern int _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, + _libssh2_bn *g, _libssh2_bn *p, + int group_order); +extern int _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p); +extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx); + diff --git a/libssh2/src/libssh2_config.h.in b/libssh2/src/libssh2_config.h.in index af4ab9ca0..307c62553 100644 --- a/libssh2/src/libssh2_config.h.in +++ b/libssh2/src/libssh2_config.h.in @@ -64,8 +64,8 @@ /* Define if you have the gcrypt library. */ #undef HAVE_LIBGCRYPT -/* Define if you have the mbedtls library. */ -#undef HAVE_LIBMBEDTLS +/* Define if you have the mbedcrypto library. */ +#undef HAVE_LIBMBEDCRYPTO /* Define if you have the ssl library. */ #undef HAVE_LIBSSL @@ -79,6 +79,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the `memset_s' function. */ +#undef HAVE_MEMSET_S + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H @@ -178,10 +181,10 @@ /* Use mbedtls */ #undef LIBSSH2_MBEDTLS -/* Use OpenSSL */ +/* Use openssl */ #undef LIBSSH2_OPENSSL -/* Use Windows CNG */ +/* Use wincng */ #undef LIBSSH2_WINCNG /* Define to the sub-directory where libtool stores uninstalled libraries. */ diff --git a/libssh2/src/libssh2_priv.h b/libssh2/src/libssh2_priv.h index bb5d1a50a..33c5ad3f8 100644 --- a/libssh2/src/libssh2_priv.h +++ b/libssh2/src/libssh2_priv.h @@ -58,18 +58,15 @@ #include #include -/* The following CPP block should really only be in session.c and - packet.c. However, AIX have #define's for 'events' and 'revents' - and we are using those names in libssh2.h, so we need to include - the AIX headers first, to make sure all code is compiled with - consistent names of these fields. While arguable the best would to - change libssh2.h to use other names, that would break backwards - compatibility. For more information, see: - https://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00003.html - https://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00224.html +/* The following CPP block should really only be in session.c and packet.c. + However, AIX have #define's for 'events' and 'revents' and we are using + those names in libssh2.h, so we need to include the AIX headers first, to + make sure all code is compiled with consistent names of these fields. + While arguable the best would to change libssh2.h to use other names, that + would break backwards compatibility. */ #ifdef HAVE_POLL -# include +# include #else # if defined(HAVE_SELECT) && !defined(WIN32) # ifdef HAVE_SYS_SELECT_H @@ -118,13 +115,13 @@ struct iovec { size_t iov_len; - void * iov_base; + void *iov_base; }; static inline int writev(int sock, struct iovec *iov, int nvecs) { DWORD ret; - if (WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) { + if(WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) { return ret; } return -1; @@ -166,7 +163,7 @@ static inline int writev(int sock, struct iovec *iov, int nvecs) * padding length, payload, padding, and MAC.)." */ #define MAX_SSH_PACKET_LEN 35000 -#define MAX_SHA_DIGEST_LEN SHA256_DIGEST_LENGTH +#define MAX_SHA_DIGEST_LEN SHA512_DIGEST_LENGTH #define LIBSSH2_ALLOC(session, count) \ session->alloc((count), &(session)->abstract) @@ -260,11 +257,10 @@ typedef struct kmdhgGPshakex_state_t size_t s_packet_len; size_t tmp_len; _libssh2_bn_ctx *ctx; - _libssh2_bn *x; + _libssh2_dh_ctx x; _libssh2_bn *e; _libssh2_bn *f; _libssh2_bn *k; - unsigned char *s; unsigned char *f_value; unsigned char *k_value; unsigned char *h_sig; @@ -283,10 +279,18 @@ typedef struct key_exchange_state_low_t kmdhgGPshakex_state_t exchange_state; _libssh2_bn *p; /* SSH2 defined value (p_value) */ _libssh2_bn *g; /* SSH2 defined value (2) */ - unsigned char request[13]; + unsigned char request[256]; /* Must fit EC_MAX_POINT_LEN + data */ unsigned char *data; size_t request_len; size_t data_len; + _libssh2_ec_key *private_key; /* SSH2 ecdh private key */ + unsigned char *public_key_oct; /* SSH2 ecdh public key octal value */ + size_t public_key_oct_len; /* SSH2 ecdh public key octal value + length */ + unsigned char *curve25519_public_key; /* curve25519 public key, 32 + bytes */ + unsigned char *curve25519_private_key; /* curve25519 private key, 32 + bytes */ } key_exchange_state_low_t; typedef struct key_exchange_state_t @@ -418,7 +422,8 @@ struct _LIBSSH2_CHANNEL /* State variables used in libssh2_channel_receive_window_adjust() */ libssh2_nonblocking_states adjust_state; - unsigned char adjust_adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */ + unsigned char adjust_adjust[9]; /* packet_type(1) + channel(4) + + adjustment(4) */ /* State variables used in libssh2_channel_read_ex() */ libssh2_nonblocking_states read_state; @@ -621,6 +626,9 @@ struct _LIBSSH2_SESSION unsigned char server_hostkey_sha1[SHA_DIGEST_LENGTH]; int server_hostkey_sha1_valid; + unsigned char server_hostkey_sha256[SHA256_DIGEST_LENGTH]; + int server_hostkey_sha256_valid; + /* (remote as source of data -- packet_read ) */ libssh2_endpoint_data remote; @@ -654,8 +662,9 @@ struct _LIBSSH2_SESSION struct transportpacket packet; #ifdef LIBSSH2DEBUG int showmask; /* what debug/trace messages to display */ - libssh2_trace_handler_func tracehandler; /* callback to display trace messages */ - void* tracehandler_context; /* context for the trace handler */ + libssh2_trace_handler_func tracehandler; /* callback to display trace + messages */ + void *tracehandler_context; /* context for the trace handler */ #endif /* State variables used in libssh2_banner_send() */ @@ -862,7 +871,8 @@ struct _LIBSSH2_KEX_METHOD { const char *name; - /* Key exchange, populates session->* and returns 0 on success, non-0 on error */ + /* Key exchange, populates session->* and returns 0 on success, non-0 on + error */ int (*exchange_keys) (LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state); @@ -879,8 +889,10 @@ struct _LIBSSH2_HOSTKEY_METHOD int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile, unsigned const char *passphrase, void **abstract); int (*initPEMFromMemory) (LIBSSH2_SESSION * session, - const char *privkeyfiledata, size_t privkeyfiledata_len, - unsigned const char *passphrase, void **abstract); + const char *privkeyfiledata, + size_t privkeyfiledata_len, + unsigned const char *passphrase, + void **abstract); int (*sig_verify) (LIBSSH2_SESSION * session, const unsigned char *sig, size_t sig_len, const unsigned char *m, size_t m_len, void **abstract); @@ -896,6 +908,7 @@ struct _LIBSSH2_HOSTKEY_METHOD struct _LIBSSH2_CRYPT_METHOD { const char *name; + const char *pem_annotation; int blocksize; @@ -942,7 +955,8 @@ struct _LIBSSH2_COMP_METHOD void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...); #else -#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__) +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__GNUC__) /* C99 supported and also by older GCC */ #define _libssh2_debug(x,y,z,...) do {} while (0) #else @@ -963,7 +977,8 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) /* Initial packet state, prior to MAC check */ #define LIBSSH2_MAC_UNCONFIRMED 1 -/* When MAC type is "none" (proto initiation phase) all packets are deemed "confirmed" */ +/* When MAC type is "none" (proto initiation phase) all packets are deemed + "confirmed" */ #define LIBSSH2_MAC_CONFIRMED 0 /* Something very bad is going on */ #define LIBSSH2_MAC_INVALID -1 @@ -988,13 +1003,18 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) #define SSH_MSG_KEXDH_INIT 30 #define SSH_MSG_KEXDH_REPLY 31 -/* diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256 */ +/* diffie-hellman-group-exchange-sha1 and + diffie-hellman-group-exchange-sha256 */ #define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30 #define SSH_MSG_KEX_DH_GEX_REQUEST 34 #define SSH_MSG_KEX_DH_GEX_GROUP 31 #define SSH_MSG_KEX_DH_GEX_INIT 32 #define SSH_MSG_KEX_DH_GEX_REPLY 33 +/* ecdh */ +#define SSH2_MSG_KEX_ECDH_INIT 30 +#define SSH2_MSG_KEX_ECDH_REPLY 31 + /* User Authentication */ #define SSH_MSG_USERAUTH_REQUEST 50 #define SSH_MSG_USERAUTH_FAILURE 51 @@ -1049,31 +1069,75 @@ int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void); const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void); +/* misc.c */ +int _libssh2_bcrypt_pbkdf(const char *pass, + size_t passlen, + const uint8_t *salt, + size_t saltlen, + uint8_t *key, + size_t keylen, + unsigned int rounds); + /* pem.c */ int _libssh2_pem_parse(LIBSSH2_SESSION * session, const char *headerbegin, const char *headerend, + const unsigned char *passphrase, FILE * fp, unsigned char **data, unsigned int *datalen); int _libssh2_pem_parse_memory(LIBSSH2_SESSION * session, const char *headerbegin, const char *headerend, const char *filedata, size_t filedata_len, unsigned char **data, unsigned int *datalen); + /* OpenSSL keys */ +int +_libssh2_openssh_pem_parse(LIBSSH2_SESSION * session, + const unsigned char *passphrase, + FILE * fp, struct string_buf **decrypted_buf); +int +_libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session, + const unsigned char *passphrase, + const char *filedata, size_t filedata_len, + struct string_buf **decrypted_buf); + int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen); int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen, unsigned char **i, unsigned int *ilen); /* global.c */ -void _libssh2_init_if_needed (void); +void _libssh2_init_if_needed(void); #define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0])) /* define to output the libssh2_int64_t type in a *printf() */ -#if defined( __BORLANDC__ ) || defined( _MSC_VER ) || defined( __MINGW32__ ) +#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__) #define LIBSSH2_INT64_T_FORMAT "I64d" #else #define LIBSSH2_INT64_T_FORMAT "lld" #endif +/* In Windows the default file mode is text but an application can override it. +Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 +*/ +#if defined(WIN32) || defined(MSDOS) +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "wt" +#define FOPEN_APPENDTEXT "at" +#elif defined(__CYGWIN__) +/* Cygwin has specific behavior we need to address when WIN32 is not defined. +https://cygwin.com/cygwin-ug-net/using-textbinary.html +For write we want our output to have line endings of LF and be compatible with +other Cygwin utilities. For read we want to handle input that may have line +endings either CRLF or LF so 't' is appropriate. +*/ +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "w" +#define FOPEN_APPENDTEXT "a" +#else +#define FOPEN_READTEXT "r" +#define FOPEN_WRITETEXT "w" +#define FOPEN_APPENDTEXT "a" +#endif + #endif /* LIBSSH2_H */ diff --git a/libssh2/src/mac.c b/libssh2/src/mac.c index 5ec26eb3b..5ac71df4c 100644 --- a/libssh2/src/mac.c +++ b/libssh2/src/mac.c @@ -86,7 +86,7 @@ mac_method_common_init(LIBSSH2_SESSION * session, unsigned char *key, static int mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract) { - if (*abstract) { + if(*abstract) { LIBSSH2_FREE(session, *abstract); } *abstract = NULL; @@ -118,7 +118,7 @@ mac_method_hmac_sha2_512_hash(LIBSSH2_SESSION * session, libssh2_hmac_sha512_init(&ctx, *abstract, 64); libssh2_hmac_update(ctx, seqno_buf, 4); libssh2_hmac_update(ctx, packet, packet_len); - if (addtl && addtl_len) { + if(addtl && addtl_len) { libssh2_hmac_update(ctx, addtl, addtl_len); } libssh2_hmac_final(ctx, buf); @@ -163,7 +163,7 @@ mac_method_hmac_sha2_256_hash(LIBSSH2_SESSION * session, libssh2_hmac_sha256_init(&ctx, *abstract, 32); libssh2_hmac_update(ctx, seqno_buf, 4); libssh2_hmac_update(ctx, packet, packet_len); - if (addtl && addtl_len) { + if(addtl && addtl_len) { libssh2_hmac_update(ctx, addtl, addtl_len); } libssh2_hmac_final(ctx, buf); @@ -208,7 +208,7 @@ mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session, libssh2_hmac_sha1_init(&ctx, *abstract, 20); libssh2_hmac_update(ctx, seqno_buf, 4); libssh2_hmac_update(ctx, packet, packet_len); - if (addtl && addtl_len) { + if(addtl && addtl_len) { libssh2_hmac_update(ctx, addtl, addtl_len); } libssh2_hmac_final(ctx, buf); @@ -281,7 +281,7 @@ mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf, libssh2_hmac_md5_init(&ctx, *abstract, 16); libssh2_hmac_update(ctx, seqno_buf, 4); libssh2_hmac_update(ctx, packet, packet_len); - if (addtl && addtl_len) { + if(addtl && addtl_len) { libssh2_hmac_update(ctx, addtl, addtl_len); } libssh2_hmac_final(ctx, buf); @@ -354,7 +354,7 @@ mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session, libssh2_hmac_ripemd160_init(&ctx, *abstract, 20); libssh2_hmac_update(ctx, seqno_buf, 4); libssh2_hmac_update(ctx, packet, packet_len); - if (addtl && addtl_len) { + if(addtl && addtl_len) { libssh2_hmac_update(ctx, addtl, addtl_len); } libssh2_hmac_final(ctx, buf); diff --git a/libssh2/src/mbedtls.c b/libssh2/src/mbedtls.c index 1d181e18f..8bbcfd8d0 100644 --- a/libssh2/src/mbedtls.c +++ b/libssh2/src/mbedtls.c @@ -1,7 +1,52 @@ +/* Copyright (c) 2016, Art + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the copyright holder nor the names + * of any other contributors may be used to endorse or + * promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ + #include "libssh2_priv.h" #ifdef LIBSSH2_MBEDTLS /* compile only if we build with mbedtls */ +/*******************************************************************/ +/* + * mbedTLS backend: Global context handles + */ + +static mbedtls_entropy_context _libssh2_mbedtls_entropy; +static mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg; + /*******************************************************************/ /* * mbedTLS backend: Generic functions @@ -18,7 +63,7 @@ _libssh2_mbedtls_init(void) ret = mbedtls_ctr_drbg_seed(&_libssh2_mbedtls_ctr_drbg, mbedtls_entropy_func, &_libssh2_mbedtls_entropy, NULL, 0); - if (ret != 0) + if(ret != 0) mbedtls_ctr_drbg_free(&_libssh2_mbedtls_ctr_drbg); } @@ -44,11 +89,11 @@ _libssh2_mbedtls_safe_free(void *buf, int len) (void)len; #endif - if (!buf) + if(!buf) return; #ifdef LIBSSH2_CLEAR_MEMORY - if (len > 0) + if(len > 0) memset(buf, 0, len); #endif @@ -65,7 +110,7 @@ _libssh2_mbedtls_cipher_init(_libssh2_cipher_ctx *ctx, const mbedtls_cipher_info_t *cipher_info; int ret, op; - if (!ctx) + if(!ctx) return -1; op = encrypt == 0 ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT; @@ -99,11 +144,10 @@ _libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx, (void) encrypt; (void) algo; - osize = blocklen+mbedtls_cipher_get_block_size(ctx); + osize = blocklen + mbedtls_cipher_get_block_size(ctx); output = (unsigned char *)mbedtls_calloc(osize, sizeof(char)); - if(output) - { + if(output) { ret = mbedtls_cipher_reset(ctx); if(!ret) @@ -112,7 +156,7 @@ _libssh2_mbedtls_cipher_crypt(_libssh2_cipher_ctx *ctx, if(!ret) ret = mbedtls_cipher_finish(ctx, output + olen, &finish_olen); - if (!ret) { + if(!ret) { olen += finish_olen; memcpy(block, output, olen); } @@ -148,8 +192,8 @@ _libssh2_mbedtls_hash_init(mbedtls_md_context_t *ctx, mbedtls_md_init(ctx); ret = mbedtls_md_setup(ctx, md_info, hmac); - if (!ret){ - if (hmac) + if(!ret) { + if(hmac) ret = mbedtls_md_hmac_starts(ctx, key, keylen); else ret = mbedtls_md_starts(ctx); @@ -196,50 +240,61 @@ _libssh2_mbedtls_bignum_init(void) _libssh2_bn *bignum; bignum = (_libssh2_bn *)mbedtls_calloc(1, sizeof(_libssh2_bn)); - if (bignum) { + if(bignum) { mbedtls_mpi_init(bignum); } return bignum; } -int +void +_libssh2_mbedtls_bignum_free(_libssh2_bn *bn) +{ + if(bn) { + mbedtls_mpi_free(bn); + mbedtls_free(bn); + } +} + +static int _libssh2_mbedtls_bignum_random(_libssh2_bn *bn, int bits, int top, int bottom) { size_t len; int err; int i; - if (!bn || bits <= 0) + if(!bn || bits <= 0) return -1; len = (bits + 7) >> 3; - err = mbedtls_mpi_fill_random(bn, len, mbedtls_ctr_drbg_random, &_libssh2_mbedtls_ctr_drbg); - if (err) + err = mbedtls_mpi_fill_random(bn, len, mbedtls_ctr_drbg_random, + &_libssh2_mbedtls_ctr_drbg); + if(err) return -1; /* Zero unsued bits above the most significant bit*/ - for(i=len*8-1;bits<=i;--i) { + for(i = len*8 - 1; bits <= i; --i) { err = mbedtls_mpi_set_bit(bn, i, 0); - if (err) + if(err) return -1; } - /* If `top` is -1, the most significant bit of the random number can be zero. - If top is 0, the most significant bit of the random number is set to 1, - and if top is 1, the two most significant bits of the number will be set - to 1, so that the product of two such random numbers will always have 2*bits length. + /* If `top` is -1, the most significant bit of the random number can be + zero. If top is 0, the most significant bit of the random number is + set to 1, and if top is 1, the two most significant bits of the number + will be set to 1, so that the product of two such random numbers will + always have 2*bits length. */ - for(i=0;i<=top;++i) { + for(i = 0; i <= top; ++i) { err = mbedtls_mpi_set_bit(bn, bits-i-1, 1); - if (err) + if(err) return -1; } /* make odd by setting first bit in least significant byte */ - if (bottom) { + if(bottom) { err = mbedtls_mpi_set_bit(bn, 0, 1); - if (err) + if(err) return -1; } @@ -275,42 +330,40 @@ _libssh2_mbedtls_rsa_new(libssh2_rsa_ctx **rsa, libssh2_rsa_ctx *ctx; ctx = (libssh2_rsa_ctx *) mbedtls_calloc(1, sizeof(libssh2_rsa_ctx)); - if (ctx != NULL) { + if(ctx != NULL) { mbedtls_rsa_init(ctx, MBEDTLS_RSA_PKCS_V15, 0); } else return -1; - if( (ret = mbedtls_mpi_read_binary(&(ctx->E), edata, elen) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->N), ndata, nlen) ) != 0 ) - { + /* !checksrc! disable ASSIGNWITHINCONDITION 1 */ + if((ret = mbedtls_mpi_read_binary(&(ctx->E), edata, elen) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->N), ndata, nlen) ) != 0) { ret = -1; } - if (!ret) - { + if(!ret) { ctx->len = mbedtls_mpi_size(&(ctx->N)); } - if (!ret && ddata) - { - if( (ret = mbedtls_mpi_read_binary(&(ctx->D) , ddata, dlen) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->P) , pdata, plen) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->Q) , qdata, qlen) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->DP), e1data, e1len) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->DQ), e2data, e2len) ) != 0 || - (ret = mbedtls_mpi_read_binary(&(ctx->QP), coeffdata, coefflen) ) != 0 ) - { + if(!ret && ddata) { + /* !checksrc! disable ASSIGNWITHINCONDITION 1 */ + if((ret = mbedtls_mpi_read_binary(&(ctx->D), ddata, dlen) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->P), pdata, plen) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->Q), qdata, qlen) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->DP), e1data, e1len) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->DQ), e2data, e2len) ) != 0 || + (ret = mbedtls_mpi_read_binary(&(ctx->QP), coeffdata, coefflen) ) + != 0) { ret = -1; } ret = mbedtls_rsa_check_privkey(ctx); } - else if (!ret) - { + else if(!ret) { ret = mbedtls_rsa_check_pubkey(ctx); } - if (ret && ctx) { + if(ret && ctx) { _libssh2_mbedtls_rsa_free(ctx); ctx = NULL; } @@ -326,17 +379,17 @@ _libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa, { int ret; mbedtls_pk_context pkey; + mbedtls_rsa_context *pk_rsa; *rsa = (libssh2_rsa_ctx *) LIBSSH2_ALLOC(session, sizeof(libssh2_rsa_ctx)); - if (*rsa == NULL) + if(*rsa == NULL) return -1; mbedtls_rsa_init(*rsa, MBEDTLS_RSA_PKCS_V15, 0); mbedtls_pk_init(&pkey); ret = mbedtls_pk_parse_keyfile(&pkey, filename, (char *)passphrase); - if( ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) - { + if(ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) { mbedtls_pk_free(&pkey); mbedtls_rsa_free(*rsa); LIBSSH2_FREE(session, *rsa); @@ -344,7 +397,7 @@ _libssh2_mbedtls_rsa_new_private(libssh2_rsa_ctx **rsa, return -1; } - mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(pkey); + pk_rsa = mbedtls_pk_rsa(pkey); mbedtls_rsa_copy(*rsa, pk_rsa); mbedtls_pk_free(&pkey); @@ -360,17 +413,33 @@ _libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, { int ret; mbedtls_pk_context pkey; + mbedtls_rsa_context *pk_rsa; + void *filedata_nullterm; + size_t pwd_len; - *rsa = (libssh2_rsa_ctx *) mbedtls_calloc( 1, sizeof( libssh2_rsa_ctx ) ); - if (*rsa == NULL) + *rsa = (libssh2_rsa_ctx *) mbedtls_calloc(1, sizeof(libssh2_rsa_ctx)); + if(*rsa == NULL) return -1; + /* + mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'" + private-key from memory will fail if the last byte is not a null byte + */ + filedata_nullterm = mbedtls_calloc(filedata_len + 1, 1); + if(filedata_nullterm == NULL) { + return -1; + } + memcpy(filedata_nullterm, filedata, filedata_len); + mbedtls_pk_init(&pkey); - ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)filedata, - filedata_len, NULL, 0); - if( ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) - { + pwd_len = passphrase != NULL ? strlen((const char *)passphrase) : 0; + ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)filedata_nullterm, + filedata_len + 1, + passphrase, pwd_len); + _libssh2_mbedtls_safe_free(filedata_nullterm, filedata_len); + + if(ret != 0 || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) { mbedtls_pk_free(&pkey); mbedtls_rsa_free(*rsa); LIBSSH2_FREE(session, *rsa); @@ -378,7 +447,7 @@ _libssh2_mbedtls_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, return -1; } - mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(pkey); + pk_rsa = mbedtls_pk_rsa(pkey); mbedtls_rsa_copy(*rsa, pk_rsa); mbedtls_pk_free(&pkey); @@ -400,7 +469,8 @@ _libssh2_mbedtls_rsa_sha1_verify(libssh2_rsa_ctx *rsa, return -1; /* failure */ ret = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, - MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH, hash, sig); + MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH, + hash, sig); return (ret == 0) ? 0 : -1; } @@ -421,14 +491,14 @@ _libssh2_mbedtls_rsa_sha1_sign(LIBSSH2_SESSION *session, sig_len = rsa->len; sig = LIBSSH2_ALLOC(session, sig_len); - if (!sig) { + if(!sig) { return -1; } ret = mbedtls_rsa_pkcs1_sign(rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, SHA_DIGEST_LENGTH, hash, sig); - if (ret) { + if(ret) { LIBSSH2_FREE(session, sig); return -1; } @@ -453,8 +523,8 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, { int e_bytes, n_bytes; unsigned long len; - unsigned char* key; - unsigned char* p; + unsigned char *key; + unsigned char *p; e_bytes = mbedtls_mpi_size(&rsa->E); n_bytes = mbedtls_mpi_size(&rsa->N); @@ -463,7 +533,7 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, len = 4 + 7 + 4 + e_bytes + 4 + n_bytes; key = LIBSSH2_ALLOC(session, len); - if (!key) { + if(!key) { return NULL; } @@ -498,36 +568,38 @@ _libssh2_mbedtls_pub_priv_key(LIBSSH2_SESSION *session, unsigned char *key = NULL, *mth = NULL; size_t keylen = 0, mthlen = 0; int ret; + mbedtls_rsa_context *rsa; - if( mbedtls_pk_get_type(pkey) != MBEDTLS_PK_RSA ) - { + if(mbedtls_pk_get_type(pkey) != MBEDTLS_PK_RSA) { mbedtls_pk_free(pkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Key type not supported"); } - // write method + /* write method */ mthlen = 7; mth = LIBSSH2_ALLOC(session, mthlen); - if (mth) { + if(mth) { memcpy(mth, "ssh-rsa", mthlen); - } else { + } + else { ret = -1; } - mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pkey); + rsa = mbedtls_pk_rsa(*pkey); key = gen_publickey_from_rsa(session, rsa, &keylen); - if (key == NULL) { + if(key == NULL) { ret = -1; } - // write output - if (ret) { - if (mth) + /* write output */ + if(ret) { + if(mth) LIBSSH2_FREE(session, mth); - if (key) + if(key) LIBSSH2_FREE(session, key); - } else { + } + else { *method = mth; *method_len = mthlen; *pubkeydata = key; @@ -552,8 +624,7 @@ _libssh2_mbedtls_pub_priv_keyfile(LIBSSH2_SESSION *session, mbedtls_pk_init(&pkey); ret = mbedtls_pk_parse_keyfile(&pkey, privatekey, passphrase); - if( ret != 0 ) - { + if(ret != 0) { mbedtls_strerror(ret, (char *)buf, sizeof(buf)); mbedtls_pk_free(&pkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, buf); @@ -580,12 +651,29 @@ _libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session, mbedtls_pk_context pkey; char buf[1024]; int ret; + void *privatekeydata_nullterm; + size_t pwd_len; + + /* + mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'" + private-key from memory will fail if the last byte is not a null byte + */ + privatekeydata_nullterm = mbedtls_calloc(privatekeydata_len + 1, 1); + if(privatekeydata_nullterm == NULL) { + return -1; + } + memcpy(privatekeydata_nullterm, privatekeydata, privatekeydata_len); mbedtls_pk_init(&pkey); - ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)privatekeydata, - privatekeydata_len, NULL, 0); - if( ret != 0 ) - { + + pwd_len = passphrase != NULL ? strlen((const char *)passphrase) : 0; + ret = mbedtls_pk_parse_key(&pkey, + (unsigned char *)privatekeydata_nullterm, + privatekeydata_len + 1, + (const unsigned char *)passphrase, pwd_len); + _libssh2_mbedtls_safe_free(privatekeydata_nullterm, privatekeydata_len); + + if(ret != 0) { mbedtls_strerror(ret, (char *)buf, sizeof(buf)); mbedtls_pk_free(&pkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, buf); @@ -603,4 +691,43 @@ void _libssh2_init_aes_ctr(void) { /* no implementation */ } + + +/*******************************************************************/ +/* + * mbedTLS backend: Diffie-Hellman functions + */ + +void +_libssh2_dh_init(_libssh2_dh_ctx *dhctx) +{ + *dhctx = _libssh2_mbedtls_bignum_init(); /* Random from client */ +} + +int +_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, + _libssh2_bn *g, _libssh2_bn *p, int group_order) +{ + /* Generate x and e */ + _libssh2_mbedtls_bignum_random(*dhctx, group_order * 8 - 1, 0, -1); + mbedtls_mpi_exp_mod(public, g, *dhctx, p, NULL); + return 0; +} + +int +_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p) +{ + /* Compute the shared secret */ + mbedtls_mpi_exp_mod(secret, f, *dhctx, p, NULL); + return 0; +} + +void +_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx) +{ + _libssh2_mbedtls_bignum_free(*dhctx); + *dhctx = NULL; +} + #endif /* LIBSSH2_MBEDTLS */ diff --git a/libssh2/src/mbedtls.h b/libssh2/src/mbedtls.h index 248583ed3..88b0e54d6 100644 --- a/libssh2/src/mbedtls.h +++ b/libssh2/src/mbedtls.h @@ -1,3 +1,40 @@ +/* Copyright (c) 2016, Art + * 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 #include @@ -27,19 +64,21 @@ #define LIBSSH2_RSA 1 #define LIBSSH2_DSA 0 +#define LIBSSH2_ECDSA 0 +#define LIBSSH2_ED25519 0 #define MD5_DIGEST_LENGTH 16 #define SHA_DIGEST_LENGTH 20 #define SHA256_DIGEST_LENGTH 32 +#define SHA384_DIGEST_LENGTH 48 #define SHA512_DIGEST_LENGTH 64 -/*******************************************************************/ -/* - * mbedTLS backend: Global context handles - */ +#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) -mbedtls_entropy_context _libssh2_mbedtls_entropy; -mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg; +#if LIBSSH2_ECDSA +#else +#define _libssh2_ec_key void +#endif /*******************************************************************/ /* @@ -80,6 +119,8 @@ mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg; _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_RIPEMD160, key, keylen) #define libssh2_hmac_sha256_init(pctx, key, keylen) \ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA256, key, keylen) +#define libssh2_hmac_sha384_init(pctx, key, keylen) \ + _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA384, key, keylen) #define libssh2_hmac_sha512_init(pctx, key, keylen) \ _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA512, key, keylen) @@ -117,6 +158,23 @@ mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg; _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_SHA256, hash) +/*******************************************************************/ +/* + * mbedTLS backend: SHA384 functions + */ + +#define libssh2_sha384_ctx mbedtls_md_context_t + +#define libssh2_sha384_init(pctx) \ + _libssh2_mbedtls_hash_init(pctx, MBEDTLS_MD_SHA384, NULL, 0) +#define libssh2_sha384_update(ctx, data, datalen) \ + mbedtls_md_update(&ctx, (unsigned char *) data, datalen) +#define libssh2_sha384_final(ctx, hash) \ + _libssh2_mbedtls_hash_final(&ctx, hash) +#define libssh2_sha384(data, datalen, hash) \ + _libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_SHA384, hash) + + /*******************************************************************/ /* * mbedTLS backend: SHA512 functions @@ -239,10 +297,6 @@ mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg; _libssh2_mbedtls_bignum_init() #define _libssh2_bn_init_from_bin() \ _libssh2_mbedtls_bignum_init() -#define _libssh2_bn_rand(bn, bits, top, bottom) \ - _libssh2_mbedtls_bignum_random(bn, bits, top, bottom) -#define _libssh2_bn_mod_exp(r, a, p, m, ctx) \ - mbedtls_mpi_exp_mod(r, a, p, m, NULL) #define _libssh2_bn_set_word(bn, word) \ mbedtls_mpi_lset(bn, word) #define _libssh2_bn_from_bin(bn, len, bin) \ @@ -254,7 +308,21 @@ mbedtls_ctr_drbg_context _libssh2_mbedtls_ctr_drbg; #define _libssh2_bn_bits(bn) \ mbedtls_mpi_bitlen(bn) #define _libssh2_bn_free(bn) \ - mbedtls_mpi_free(bn) + _libssh2_mbedtls_bignum_free(bn) + + +/*******************************************************************/ +/* + * mbedTLS backend: Diffie-Hellman support. + */ + +#define _libssh2_dh_ctx mbedtls_mpi * +#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx) +#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \ + _libssh2_dh_key_pair(dhctx, public, g, p, group_order) +#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \ + _libssh2_dh_secret(dhctx, secret, f, p) +#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx) /*******************************************************************/ @@ -302,9 +370,6 @@ _libssh2_mbedtls_bignum_init(void); void _libssh2_mbedtls_bignum_free(_libssh2_bn *bn); -int -_libssh2_mbedtls_bignum_random(_libssh2_bn *bn, int bits, int top, int bottom); - int _libssh2_mbedtls_rsa_new(libssh2_rsa_ctx **rsa, const unsigned char *edata, @@ -369,3 +434,14 @@ _libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session, const char *privatekeydata, size_t privatekeydata_len, const char *passphrase); + +extern void +_libssh2_dh_init(_libssh2_dh_ctx *dhctx); +extern int +_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, + _libssh2_bn *g, _libssh2_bn *p, int group_order); +extern int +_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p); +extern void +_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx); diff --git a/libssh2/src/misc.c b/libssh2/src/misc.c index f7faae7b6..bd084c854 100644 --- a/libssh2/src/misc.c +++ b/libssh2/src/misc.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2014 by Daniel Stenberg + * Copyright (c) 2009-2019 by Daniel Stenberg * Copyright (c) 2010 Simon Josefsson * All rights reserved. * @@ -39,6 +39,11 @@ #include "libssh2_priv.h" #include "misc.h" +#include "blf.h" + +#ifdef HAVE_STDLIB_H +#include +#endif #ifdef HAVE_UNISTD_H #include @@ -48,21 +53,28 @@ #include #endif +#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY +#ifdef HAVE_WINDOWS_H +#include +#endif +#endif + #include #include -int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errmsg, int errflags) +int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, + const char *errmsg, int errflags) { - if (session->err_flags & LIBSSH2_ERR_FLAG_DUP) + if(session->err_flags & LIBSSH2_ERR_FLAG_DUP) LIBSSH2_FREE(session, (char *)session->err_msg); session->err_code = errcode; session->err_flags = 0; - if ((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) { + if((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) { size_t len = strlen(errmsg); char *copy = LIBSSH2_ALLOC(session, len + 1); - if (copy) { + if(copy) { memcpy(copy, errmsg, len + 1); session->err_flags = LIBSSH2_ERR_FLAG_DUP; session->err_msg = copy; @@ -86,7 +98,7 @@ int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errm return errcode; } -int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg) +int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg) { return _libssh2_error_flags(session, errcode, errmsg, 0); } @@ -94,7 +106,7 @@ int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg) #ifdef WIN32 static int wsa2errno(void) { - switch (WSAGetLastError()) { + switch(WSAGetLastError()) { case WSAEWOULDBLOCK: return EAGAIN; @@ -127,20 +139,20 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, rc = recv(sock, buffer, length, flags); #ifdef WIN32 - if (rc < 0 ) + if(rc < 0) return -wsa2errno(); #elif defined(__VMS) - if (rc < 0 ){ - if ( errno == EWOULDBLOCK ) + if(rc < 0) { + if(errno == EWOULDBLOCK) return -EAGAIN; else return -errno; } #else - if (rc < 0 ){ + if(rc < 0) { /* Sometimes the first recv() function call sets errno to ENOENT on Solaris and HP-UX */ - if ( errno == ENOENT ) + if(errno == ENOENT) return -EAGAIN; else return -errno; @@ -163,17 +175,17 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length, rc = send(sock, buffer, length, flags); #ifdef WIN32 - if (rc < 0 ) + if(rc < 0) return -wsa2errno(); #elif defined(__VMS) - if (rc < 0 ) { - if ( errno == EWOULDBLOCK ) + if(rc < 0) { + if(errno == EWOULDBLOCK) return -EAGAIN; else return -errno; } #else - if (rc < 0 ) + if(rc < 0) return -errno; #endif return rc; @@ -269,15 +281,16 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data, *data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1); d = (unsigned char *) *data; - if (!d) { + if(!d) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for base64 decoding"); } for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) { - if ((v = base64_reverse_table[*s]) < 0) + v = base64_reverse_table[*s]; + if(v < 0) continue; - switch (i % 4) { + switch(i % 4) { case 0: d[len] = (unsigned char)(v << 2); break; @@ -295,10 +308,11 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data, } i++; } - if ((i % 4) == 1) { + if((i % 4) == 1) { /* Invalid -- We have a byte which belongs exclusively to a partial octet */ LIBSSH2_FREE(session, *data); + *data = NULL; return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64"); } @@ -321,68 +335,69 @@ static const char table64[]= size_t _libssh2_base64_encode(LIBSSH2_SESSION *session, const char *inp, size_t insize, char **outptr) { - unsigned char ibuf[3]; - unsigned char obuf[4]; - int i; - int inputparts; - char *output; - char *base64data; - const char *indata = inp; + unsigned char ibuf[3]; + unsigned char obuf[4]; + int i; + int inputparts; + char *output; + char *base64data; + const char *indata = inp; - *outptr = NULL; /* set to NULL in case of failure before we reach the end */ + *outptr = NULL; /* set to NULL in case of failure before we reach the + end */ - if(0 == insize) - insize = strlen(indata); + if(0 == insize) + insize = strlen(indata); - base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4); - if(NULL == output) - return 0; + base64data = output = LIBSSH2_ALLOC(session, insize * 4 / 3 + 4); + if(NULL == output) + return 0; - while(insize > 0) { - for (i = inputparts = 0; i < 3; i++) { - if(insize > 0) { - inputparts++; - ibuf[i] = *indata; - indata++; - insize--; - } - else - ibuf[i] = 0; + while(insize > 0) { + for(i = inputparts = 0; i < 3; i++) { + if(insize > 0) { + inputparts++; + ibuf[i] = *indata; + indata++; + insize--; + } + else + ibuf[i] = 0; + } + + obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); + obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ + ((ibuf[1] & 0xF0) >> 4)); + obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ + ((ibuf[2] & 0xC0) >> 6)); + obuf[3] = (unsigned char) (ibuf[2] & 0x3F); + + switch(inputparts) { + case 1: /* only one byte read */ + snprintf(output, 5, "%c%c==", + table64[obuf[0]], + table64[obuf[1]]); + break; + case 2: /* two bytes read */ + snprintf(output, 5, "%c%c%c=", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]]); + break; + default: + snprintf(output, 5, "%c%c%c%c", + table64[obuf[0]], + table64[obuf[1]], + table64[obuf[2]], + table64[obuf[3]]); + break; + } + output += 4; } + *output = 0; + *outptr = base64data; /* make it return the actual data memory */ - obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); - obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ - ((ibuf[1] & 0xF0) >> 4)); - obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ - ((ibuf[2] & 0xC0) >> 6)); - obuf[3] = (unsigned char) (ibuf[2] & 0x3F); - - switch(inputparts) { - case 1: /* only one byte read */ - snprintf(output, 5, "%c%c==", - table64[obuf[0]], - table64[obuf[1]]); - break; - case 2: /* two bytes read */ - snprintf(output, 5, "%c%c%c=", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]]); - break; - default: - snprintf(output, 5, "%c%c%c%c", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]], - table64[obuf[3]] ); - break; - } - output += 4; - } - *output=0; - *outptr = base64data; /* make it return the actual data memory */ - - return strlen(base64data); /* return the length of the new data */ + return strlen(base64data); /* return the length of the new data */ } /* ---- End of Base64 Encoding ---- */ @@ -403,7 +418,7 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask) } LIBSSH2_API int -libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, +libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context, libssh2_trace_handler_func callback) { session->tracehandler = callback; @@ -431,18 +446,18 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) "Publickey", "Socket", }; - const char* contexttext = contexts[0]; + const char *contexttext = contexts[0]; unsigned int contextindex; - if (!(session->showmask & context)) { + if(!(session->showmask & context)) { /* no such output asked for */ return; } /* Find the first matching context string for this message */ - for (contextindex = 0; contextindex < ARRAY_SIZE(contexts); + for(contextindex = 0; contextindex < ARRAY_SIZE(contexts); contextindex++) { - if ((context & (1 << contextindex)) != 0) { + if((context & (1 << contextindex)) != 0) { contexttext = contexts[contextindex]; break; } @@ -457,7 +472,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ", (int)now.tv_sec, (int)now.tv_usec, contexttext); - if (len >= buflen) + if(len >= buflen) msglen = buflen - 1; else { buflen -= len; @@ -468,7 +483,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) msglen += len < buflen ? len : buflen - 1; } - if (session->tracehandler) + if(session->tracehandler) (session->tracehandler)(session, session->tracehandler_context, buffer, msglen); else @@ -485,7 +500,7 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask) } LIBSSH2_API int -libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, +libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context, libssh2_trace_handler_func callback) { (void) session; @@ -615,21 +630,20 @@ void _libssh2_list_insert(struct list_node *after, /* insert before this */ #define _W32_FT_OFFSET (116444736000000000) int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp) - { - union { - unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */ - FILETIME ft; - } _now; - (void)tzp; - if(tp) - { - GetSystemTimeAsFileTime (&_now.ft); - tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 ); - tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000); +{ + union { + unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } _now; + (void)tzp; + if(tp) { + GetSystemTimeAsFileTime(&_now.ft); + tp->tv_usec = (long)((_now.ns100 / 10) % 1000000); + tp->tv_sec = (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000); } - /* Always return 0 as per Open Group Base Specifications Issue 6. - Do not set errno on error. */ - return 0; + /* Always return 0 as per Open Group Base Specifications Issue 6. + Do not set errno on error. */ + return 0; } @@ -643,3 +657,218 @@ void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size) } return p; } + +/* XOR operation on buffers input1 and input2, result in output. + It is safe to use an input buffer as the output buffer. */ +void _libssh2_xor_data(unsigned char *output, + const unsigned char *input1, + const unsigned char *input2, + size_t length) +{ + size_t i; + + for(i = 0; i < length; i++) + *output++ = *input1++ ^ *input2++; +} + +/* Increments an AES CTR buffer to prepare it for use with the + next AES block. */ +void _libssh2_aes_ctr_increment(unsigned char *ctr, + size_t length) +{ + unsigned char *pc; + unsigned int val, carry; + + pc = ctr + length - 1; + carry = 1; + + while(pc >= ctr) { + val = (unsigned int)*pc + carry; + *pc-- = val & 0xFF; + carry = val >> 8; + } +} + +#ifdef WIN32 +static void * (__cdecl * const volatile memset_libssh)(void *, int, size_t) = + memset; +#else +static void * (* const volatile memset_libssh)(void *, int, size_t) = memset; +#endif + +void _libssh2_explicit_zero(void *buf, size_t size) +{ +#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY + SecureZeroMemory(buf, size); + (void)memset_libssh; /* Silence unused variable warning */ +#elif defined(HAVE_MEMSET_S) + (void)memset_s(buf, size, 0, size); + (void)memset_libssh; /* Silence unused variable warning */ +#else + memset_libssh(buf, 0, size); +#endif +} + +/* String buffer */ + +struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session) +{ + struct string_buf *ret; + + ret = _libssh2_calloc(session, sizeof(*ret)); + if(ret == NULL) + return NULL; + + return ret; +} + +void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf) +{ + if(buf == NULL) + return; + + if(buf->data != NULL) + LIBSSH2_FREE(session, buf->data); + + LIBSSH2_FREE(session, buf); + buf = NULL; +} + +int _libssh2_get_u32(struct string_buf *buf, uint32_t *out) +{ + if(!_libssh2_check_length(buf, 4)) { + return -1; + } + + *out = _libssh2_ntohu32(buf->dataptr); + buf->dataptr += 4; + return 0; +} + +int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out) +{ + if(!_libssh2_check_length(buf, 8)) { + return -1; + } + + *out = _libssh2_ntohu64(buf->dataptr); + buf->dataptr += 8; + return 0; +} + +int _libssh2_match_string(struct string_buf *buf, const char *match) +{ + unsigned char *out; + size_t len = 0; + if(_libssh2_get_string(buf, &out, &len) || len != strlen(match) || + strncmp((char *)out, match, strlen(match)) != 0) { + return -1; + } + return 0; +} + +int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf, + size_t *outlen) +{ + uint32_t data_len; + if(_libssh2_get_u32(buf, &data_len) != 0) { + return -1; + } + if(!_libssh2_check_length(buf, data_len)) { + return -1; + } + *outbuf = buf->dataptr; + buf->dataptr += data_len; + + if(outlen) + *outlen = (size_t)data_len; + + return 0; +} + +int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf, + unsigned char **outbuf, size_t *outlen) +{ + size_t str_len; + unsigned char *str; + + if(_libssh2_get_string(buf, &str, &str_len)) { + return -1; + } + + *outbuf = LIBSSH2_ALLOC(session, str_len); + if(*outbuf) { + memcpy(*outbuf, str, str_len); + } + else { + return -1; + } + + if(outlen) + *outlen = str_len; + + return 0; +} + +int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf, + size_t *outlen) +{ + uint32_t data_len; + uint32_t bn_len; + unsigned char *bnptr; + + if(_libssh2_get_u32(buf, &data_len)) { + return -1; + } + if(!_libssh2_check_length(buf, data_len)) { + return -1; + } + + bn_len = data_len; + bnptr = buf->dataptr; + + /* trim leading zeros */ + while(bn_len > 0 && *bnptr == 0x00) { + bn_len--; + bnptr++; + } + + *outbuf = bnptr; + buf->dataptr += data_len; + + if(outlen) + *outlen = (size_t)bn_len; + + return 0; +} + +/* Given the current location in buf, _libssh2_check_length ensures + callers can read the next len number of bytes out of the buffer + before reading the buffer content */ + +int _libssh2_check_length(struct string_buf *buf, size_t len) +{ + unsigned char *endp = &buf->data[buf->len]; + size_t left = endp - buf->dataptr; + return ((len <= left) && (left <= buf->len)); +} + +/* Wrappers */ + +int _libssh2_bcrypt_pbkdf(const char *pass, + size_t passlen, + const uint8_t *salt, + size_t saltlen, + uint8_t *key, + size_t keylen, + unsigned int rounds) +{ + /* defined in bcrypt_pbkdf.c */ + return bcrypt_pbkdf(pass, + passlen, + salt, + saltlen, + key, + keylen, + rounds); +} diff --git a/libssh2/src/misc.h b/libssh2/src/misc.h index 54ae5461d..5481e666c 100644 --- a/libssh2/src/misc.h +++ b/libssh2/src/misc.h @@ -1,6 +1,6 @@ #ifndef __LIBSSH2_MISC_H #define __LIBSSH2_MISC_H -/* Copyright (c) 2009-2014 by Daniel Stenberg +/* Copyright (c) 2009-2019 by Daniel Stenberg * * All rights reserved. * @@ -49,8 +49,15 @@ struct list_node { struct list_head *head; }; -int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errmsg, int errflags); -int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg); +struct string_buf { + unsigned char *data; + unsigned char *dataptr; + size_t len; +}; + +int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, + const char *errmsg, int errflags); +int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg); void _libssh2_list_init(struct list_head *head); @@ -70,7 +77,7 @@ void *_libssh2_list_prev(struct list_node *node); /* remove this node from the list */ void _libssh2_list_remove(struct list_node *entry); -size_t _libssh2_base64_encode(struct _LIBSSH2_SESSION *session, +size_t _libssh2_base64_encode(LIBSSH2_SESSION *session, const char *inp, size_t insize, char **outptr); unsigned int _libssh2_ntohu32(const unsigned char *buf); @@ -78,7 +85,22 @@ libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf); void _libssh2_htonu32(unsigned char *buf, uint32_t val); void _libssh2_store_u32(unsigned char **buf, uint32_t value); void _libssh2_store_str(unsigned char **buf, const char *str, size_t len); -void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size); +void *_libssh2_calloc(LIBSSH2_SESSION *session, size_t size); +void _libssh2_explicit_zero(void *buf, size_t size); + +struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session); +void _libssh2_string_buf_free(LIBSSH2_SESSION *session, + struct string_buf *buf); +int _libssh2_get_u32(struct string_buf *buf, uint32_t *out); +int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out); +int _libssh2_match_string(struct string_buf *buf, const char *match); +int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf, + size_t *outlen); +int _libssh2_copy_string(LIBSSH2_SESSION* session, struct string_buf *buf, + unsigned char **outbuf, size_t *outlen); +int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf, + size_t *outlen); +int _libssh2_check_length(struct string_buf *buf, size_t requested_len); #if defined(LIBSSH2_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) /* provide a private one */ @@ -93,4 +115,11 @@ int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp); #endif #endif +void _libssh2_xor_data(unsigned char *output, + const unsigned char *input1, + const unsigned char *input2, + size_t length); + +void _libssh2_aes_ctr_increment(unsigned char *ctr, size_t length); + #endif /* _LIBSSH2_MISC_H */ diff --git a/libssh2/src/openssl.c b/libssh2/src/openssl.c index 4f63ef92b..04d5ec2ff 100644 --- a/libssh2/src/openssl.c +++ b/libssh2/src/openssl.c @@ -43,11 +43,37 @@ #ifdef LIBSSH2_OPENSSL /* compile only if we build with openssl */ #include +#include "misc.h" #ifndef EVP_MAX_BLOCK_LENGTH #define EVP_MAX_BLOCK_LENGTH 32 #endif +int +read_openssh_private_key_from_memory(void **key_ctx, LIBSSH2_SESSION *session, + const char *key_type, + const char *filedata, + size_t filedata_len, + unsigned const char *passphrase); + +static unsigned char * +write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes) +{ + unsigned char *p = buf; + + /* Left space for bn size which will be written below. */ + p += 4; + + *p = 0; + BN_bn2bin(bn, p + 1); + if(!(*(p + 1) & 0x80)) { + memmove(p, p + 1, --bn_bytes); + } + _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */ + + return p + bn_bytes; +} + int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, const unsigned char *edata, @@ -81,7 +107,7 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, n = BN_new(); BN_bin2bn(ndata, nlen, n); - if (ddata) { + if(ddata) { d = BN_new(); BN_bin2bn(ddata, dlen, d); @@ -107,6 +133,7 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, #else (*rsa)->e = e; (*rsa)->n = n; + (*rsa)->d = d; #endif #ifdef HAVE_OPAQUE_STRUCTS @@ -135,7 +162,7 @@ _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx, unsigned char hash[SHA_DIGEST_LENGTH]; int ret; - if (_libssh2_sha1(m, m_len, hash)) + if(_libssh2_sha1(m, m_len, hash)) return -1; /* failure */ ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH, (unsigned char *) sig, sig_len, rsactx); @@ -173,7 +200,7 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, pub_key = BN_new(); BN_bin2bn(y, y_len, pub_key); - if (x_len) { + if(x_len) { priv_key = BN_new(); BN_bin2bn(x, x_len, priv_key); } @@ -220,7 +247,7 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, dsasig->r = r; dsasig->s = s; #endif - if (!_libssh2_sha1(m, m_len, hash)) + if(!_libssh2_sha1(m, m_len, hash)) /* _libssh2_sha1() succeeded */ ret = DSA_do_verify(hash, SHA_DIGEST_LENGTH, dsasig, dsactx); @@ -230,6 +257,147 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx, } #endif /* LIBSSH_DSA */ +#if LIBSSH2_ECDSA + +/* _libssh2_ecdsa_key_get_curve_type + * + * returns key curve type that maps to libssh2_curve_type + * + */ + +libssh2_curve_type +_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key) +{ + const EC_GROUP *group = EC_KEY_get0_group(key); + return EC_GROUP_get_curve_name(group); +} + +/* _libssh2_ecdsa_curve_type_from_name + * + * returns 0 for success, key curve type that maps to libssh2_curve_type + * + */ + +int +_libssh2_ecdsa_curve_type_from_name(const char *name, + libssh2_curve_type *out_type) +{ + int ret = 0; + libssh2_curve_type type; + + if(name == NULL || strlen(name) != 19) + return -1; + + if(strcmp(name, "ecdsa-sha2-nistp256") == 0) + type = LIBSSH2_EC_CURVE_NISTP256; + else if(strcmp(name, "ecdsa-sha2-nistp384") == 0) + type = LIBSSH2_EC_CURVE_NISTP384; + else if(strcmp(name, "ecdsa-sha2-nistp521") == 0) + type = LIBSSH2_EC_CURVE_NISTP521; + else { + ret = -1; + } + + if(ret == 0 && out_type) { + *out_type = type; + } + + return ret; +} + +/* _libssh2_ecdsa_curve_name_with_octal_new + * + * Creates a new public key given an octal string, length and type + * + */ + +int +_libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ec_ctx, + const unsigned char *k, + size_t k_len, libssh2_curve_type curve) +{ + + int ret = 0; + const EC_GROUP *ec_group = NULL; + EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve); + EC_POINT *point = NULL; + + if(ec_key) { + ec_group = EC_KEY_get0_group(ec_key); + point = EC_POINT_new(ec_group); + ret = EC_POINT_oct2point(ec_group, point, k, k_len, NULL); + ret = EC_KEY_set_public_key(ec_key, point); + + if(point != NULL) + EC_POINT_free(point); + + if(ec_ctx != NULL) + *ec_ctx = ec_key; + } + + return (ret == 1) ? 0 : -1; +} + +#define LIBSSH2_ECDSA_VERIFY(digest_type) \ +{ \ + unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \ + libssh2_sha##digest_type(m, m_len, hash); \ + ret = ECDSA_do_verify(hash, SHA##digest_type##_DIGEST_LENGTH, \ + ecdsa_sig, ec_key); \ + \ +} + +int +_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, + const unsigned char *r, size_t r_len, + const unsigned char *s, size_t s_len, + const unsigned char *m, size_t m_len) +{ + int ret = 0; + EC_KEY *ec_key = (EC_KEY*)ctx; + libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_key); + +#ifdef HAVE_OPAQUE_STRUCTS + ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new(); + BIGNUM *pr = BN_new(); + BIGNUM *ps = BN_new(); + + BN_bin2bn(r, r_len, pr); + BN_bin2bn(s, s_len, ps); + ECDSA_SIG_set0(ecdsa_sig, pr, ps); + +#else + ECDSA_SIG ecdsa_sig_; + ECDSA_SIG *ecdsa_sig = &ecdsa_sig_; + ecdsa_sig_.r = BN_new(); + BN_bin2bn(r, r_len, ecdsa_sig_.r); + ecdsa_sig_.s = BN_new(); + BN_bin2bn(s, s_len, ecdsa_sig_.s); +#endif + + if(type == LIBSSH2_EC_CURVE_NISTP256) { + LIBSSH2_ECDSA_VERIFY(256); + } + else if(type == LIBSSH2_EC_CURVE_NISTP384) { + LIBSSH2_ECDSA_VERIFY(384); + } + else if(type == LIBSSH2_EC_CURVE_NISTP521) { + LIBSSH2_ECDSA_VERIFY(512); + } + +#ifdef HAVE_OPAQUE_STRUCTS + if(ecdsa_sig) + ECDSA_SIG_free(ecdsa_sig); +#else + BN_clear_free(ecdsa_sig_.s); + BN_clear_free(ecdsa_sig_.r); +#endif + + return (ret == 1) ? 0 : -1; +} + +#endif /* LIBSSH2_ECDSA */ + int _libssh2_cipher_init(_libssh2_cipher_ctx * h, _libssh2_cipher_type(algo), @@ -259,7 +427,7 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx, #else ret = EVP_Cipher(ctx, buf, block, blocksize); #endif - if (ret == 1) { + if(ret == 1) { memcpy(block, buf, blocksize); } return ret == 1 ? 0 : 1; @@ -289,7 +457,7 @@ aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const EVP_CIPHER *aes_cipher; (void) enc; - switch (EVP_CIPHER_CTX_key_length(ctx)) { + switch(EVP_CIPHER_CTX_key_length(ctx)) { case 16: aes_cipher = EVP_aes_128_ecb(); break; @@ -304,7 +472,7 @@ aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, } c = malloc(sizeof(*c)); - if (c == NULL) + if(c == NULL) return 0; #ifdef HAVE_OPAQUE_STRUCTS @@ -312,12 +480,12 @@ aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, #else c->aes_ctx = malloc(sizeof(EVP_CIPHER_CTX)); #endif - if (c->aes_ctx == NULL) { + if(c->aes_ctx == NULL) { free(c); return 0; } - if (EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) { + if(EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) { #ifdef HAVE_OPAQUE_STRUCTS EVP_CIPHER_CTX_free(c->aes_ctx); #else @@ -343,13 +511,12 @@ aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, { aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx); unsigned char b1[AES_BLOCK_SIZE]; - size_t i = 0; int outlen = 0; - if (inl != 16) /* libssh2 only ever encrypt one block */ + if(inl != 16) /* libssh2 only ever encrypt one block */ return 0; - if (c == NULL) { + if(c == NULL) { return 0; } @@ -360,19 +527,13 @@ aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, the ciphertext block C1. The counter X is then incremented */ - if (EVP_EncryptUpdate(c->aes_ctx, b1, &outlen, c->ctr, AES_BLOCK_SIZE) != 1) { + if(EVP_EncryptUpdate(c->aes_ctx, b1, &outlen, + c->ctr, AES_BLOCK_SIZE) != 1) { return 0; } - for (i = 0; i < 16; i++) - *out++ = *in++ ^ b1[i]; - - i = 15; - while (c->ctr[i]++ == 0xFF) { - if (i == 0) - break; - i--; - } + _libssh2_xor_data(out, in, b1, AES_BLOCK_SIZE); + _libssh2_aes_ctr_increment(c->ctr, AES_BLOCK_SIZE); return 1; } @@ -382,11 +543,11 @@ aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */ { aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx); - if (c == NULL) { + if(c == NULL) { return 1; } - if (c->aes_ctx != NULL) { + if(c->aes_ctx != NULL) { #ifdef HAVE_OPAQUE_STRUCTS EVP_CIPHER_CTX_free(c->aes_ctx); #else @@ -401,27 +562,27 @@ aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */ } static const EVP_CIPHER * -make_ctr_evp (size_t keylen, EVP_CIPHER *aes_ctr_cipher, int type) +make_ctr_evp (size_t keylen, EVP_CIPHER **aes_ctr_cipher, int type) { #ifdef HAVE_OPAQUE_STRUCTS - aes_ctr_cipher = EVP_CIPHER_meth_new(type, 16, keylen); - if (aes_ctr_cipher) { - EVP_CIPHER_meth_set_iv_length(aes_ctr_cipher, 16); - EVP_CIPHER_meth_set_init(aes_ctr_cipher, aes_ctr_init); - EVP_CIPHER_meth_set_do_cipher(aes_ctr_cipher, aes_ctr_do_cipher); - EVP_CIPHER_meth_set_cleanup(aes_ctr_cipher, aes_ctr_cleanup); + *aes_ctr_cipher = EVP_CIPHER_meth_new(type, 16, keylen); + if(*aes_ctr_cipher) { + EVP_CIPHER_meth_set_iv_length(*aes_ctr_cipher, 16); + EVP_CIPHER_meth_set_init(*aes_ctr_cipher, aes_ctr_init); + EVP_CIPHER_meth_set_do_cipher(*aes_ctr_cipher, aes_ctr_do_cipher); + EVP_CIPHER_meth_set_cleanup(*aes_ctr_cipher, aes_ctr_cleanup); } #else - aes_ctr_cipher->nid = type; - aes_ctr_cipher->block_size = 16; - aes_ctr_cipher->key_len = keylen; - aes_ctr_cipher->iv_len = 16; - aes_ctr_cipher->init = aes_ctr_init; - aes_ctr_cipher->do_cipher = aes_ctr_do_cipher; - aes_ctr_cipher->cleanup = aes_ctr_cleanup; + (*aes_ctr_cipher)->nid = type; + (*aes_ctr_cipher)->block_size = 16; + (*aes_ctr_cipher)->key_len = keylen; + (*aes_ctr_cipher)->iv_len = 16; + (*aes_ctr_cipher)->init = aes_ctr_init; + (*aes_ctr_cipher)->do_cipher = aes_ctr_do_cipher; + (*aes_ctr_cipher)->cleanup = aes_ctr_cleanup; #endif - return aes_ctr_cipher; + return *aes_ctr_cipher; } const EVP_CIPHER * @@ -429,12 +590,13 @@ _libssh2_EVP_aes_128_ctr(void) { #ifdef HAVE_OPAQUE_STRUCTS static EVP_CIPHER * aes_ctr_cipher; - return !aes_ctr_cipher? - make_ctr_evp (16, aes_ctr_cipher, NID_aes_128_ctr) : aes_ctr_cipher; + return !aes_ctr_cipher ? + make_ctr_evp(16, &aes_ctr_cipher, NID_aes_128_ctr) : aes_ctr_cipher; #else static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (16, &aes_ctr_cipher, 0) : &aes_ctr_cipher; + static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher; + return !aes_ctr_cipher.key_len ? + make_ctr_evp(16, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher; #endif } @@ -443,12 +605,13 @@ _libssh2_EVP_aes_192_ctr(void) { #ifdef HAVE_OPAQUE_STRUCTS static EVP_CIPHER * aes_ctr_cipher; - return !aes_ctr_cipher? - make_ctr_evp (24, aes_ctr_cipher, NID_aes_192_ctr) : aes_ctr_cipher; + return !aes_ctr_cipher ? + make_ctr_evp(24, &aes_ctr_cipher, NID_aes_192_ctr) : aes_ctr_cipher; #else static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (24, &aes_ctr_cipher, 0) : &aes_ctr_cipher; + static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher; + return !aes_ctr_cipher.key_len ? + make_ctr_evp(24, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher; #endif } @@ -457,25 +620,70 @@ _libssh2_EVP_aes_256_ctr(void) { #ifdef HAVE_OPAQUE_STRUCTS static EVP_CIPHER * aes_ctr_cipher; - return !aes_ctr_cipher? - make_ctr_evp (32, aes_ctr_cipher, NID_aes_256_ctr) : aes_ctr_cipher; + return !aes_ctr_cipher ? + make_ctr_evp(32, &aes_ctr_cipher, NID_aes_256_ctr) : aes_ctr_cipher; #else static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (32, &aes_ctr_cipher, 0) : &aes_ctr_cipher; + static EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher; + return !aes_ctr_cipher.key_len ? + make_ctr_evp(32, &aes_ctr_cipher_ptr, 0) : &aes_ctr_cipher; #endif } -void _libssh2_init_aes_ctr(void) +#endif /* LIBSSH2_AES_CTR */ + +#ifndef HAVE_EVP_AES_128_CTR +static EVP_CIPHER * aes_128_ctr_cipher = NULL; +static EVP_CIPHER * aes_192_ctr_cipher = NULL; +static EVP_CIPHER * aes_256_ctr_cipher = NULL; +#endif + +void _libssh2_openssl_crypto_init(void) { - _libssh2_EVP_aes_128_ctr(); - _libssh2_EVP_aes_192_ctr(); - _libssh2_EVP_aes_256_ctr(); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(LIBRESSL_VERSION_NUMBER) +#ifndef OPENSSL_NO_ENGINE + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); +#endif +#else + OpenSSL_add_all_algorithms(); + OpenSSL_add_all_ciphers(); + OpenSSL_add_all_digests(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); +#endif +#endif +#ifndef HAVE_EVP_AES_128_CTR + aes_128_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_128_ctr(); + aes_192_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_192_ctr(); + aes_256_ctr_cipher = (EVP_CIPHER *)_libssh2_EVP_aes_256_ctr(); +#endif } -#else -void _libssh2_init_aes_ctr(void) {} -#endif /* LIBSSH2_AES_CTR */ +void _libssh2_openssl_crypto_exit(void) +{ +#ifndef HAVE_EVP_AES_128_CTR +#ifdef HAVE_OPAQUE_STRUCTS + if(aes_128_ctr_cipher) { + EVP_CIPHER_meth_free(aes_128_ctr_cipher); + } + + if(aes_192_ctr_cipher) { + EVP_CIPHER_meth_free(aes_192_ctr_cipher); + } + + if(aes_256_ctr_cipher) { + EVP_CIPHER_meth_free(aes_256_ctr_cipher); + } +#endif + + aes_128_ctr_cipher = NULL; + aes_192_ctr_cipher = NULL; + aes_256_ctr_cipher = NULL; +#endif +} /* TODO: Optionally call a passphrase callback specified by the * calling program @@ -486,7 +694,7 @@ passphrase_cb(char *buf, int size, int rwflag, char *passphrase) int passphrase_len = strlen(passphrase); (void) rwflag; - if (passphrase_len > (size - 1)) { + if(passphrase_len > (size - 1)) { passphrase_len = size - 1; } memcpy(buf, passphrase, passphrase_len); @@ -496,12 +704,12 @@ passphrase_cb(char *buf, int size, int rwflag, char *passphrase) } typedef void * (*pem_read_bio_func)(BIO *, void **, pem_password_cb *, - void * u); + void *u); static int -read_private_key_from_memory(void ** key_ctx, +read_private_key_from_memory(void **key_ctx, pem_read_bio_func read_private_key, - const char * filedata, + const char *filedata, size_t filedata_len, unsigned const char *passphrase) { @@ -510,7 +718,7 @@ read_private_key_from_memory(void ** key_ctx, *key_ctx = NULL; bp = BIO_new_mem_buf((char *)filedata, filedata_len); - if (!bp) { + if(!bp) { return -1; } *key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb, @@ -520,10 +728,12 @@ read_private_key_from_memory(void ** key_ctx, return (*key_ctx) ? 0 : -1; } + + static int -read_private_key_from_file(void ** key_ctx, +read_private_key_from_file(void **key_ctx, pem_read_bio_func read_private_key, - const char * filename, + const char *filename, unsigned const char *passphrase) { BIO * bp; @@ -531,7 +741,7 @@ read_private_key_from_file(void ** key_ctx, *key_ctx = NULL; bp = BIO_new_file(filename, "r"); - if (!bp) { + if(!bp) { return -1; } @@ -548,282 +758,23 @@ _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa, const char *filedata, size_t filedata_len, unsigned const char *passphrase) { + int rc; + pem_read_bio_func read_rsa = (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; (void) session; _libssh2_init_if_needed(); - return read_private_key_from_memory((void **) rsa, read_rsa, - filedata, filedata_len, passphrase); -} + rc = read_private_key_from_memory((void **) rsa, read_rsa, + filedata, filedata_len, passphrase); -int -_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, - LIBSSH2_SESSION * session, - const char *filename, unsigned const char *passphrase) -{ - pem_read_bio_func read_rsa = - (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; - (void) session; - - _libssh2_init_if_needed (); - - return read_private_key_from_file((void **) rsa, read_rsa, - filename, passphrase); -} - -#if LIBSSH2_DSA -int -_libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa, - LIBSSH2_SESSION * session, - const char *filedata, size_t filedata_len, - unsigned const char *passphrase) -{ - pem_read_bio_func read_dsa = - (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; - (void) session; - - _libssh2_init_if_needed(); - - return read_private_key_from_memory((void **) dsa, read_dsa, - filedata, filedata_len, passphrase); -} - -int -_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, - LIBSSH2_SESSION * session, - const char *filename, unsigned const char *passphrase) -{ - pem_read_bio_func read_dsa = - (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; - (void) session; - - _libssh2_init_if_needed (); - - return read_private_key_from_file((void **) dsa, read_dsa, - filename, passphrase); -} -#endif /* LIBSSH_DSA */ - -int -_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, - libssh2_rsa_ctx * rsactx, - const unsigned char *hash, - size_t hash_len, - unsigned char **signature, size_t *signature_len) -{ - int ret; - unsigned char *sig; - unsigned int sig_len; - - sig_len = RSA_size(rsactx); - sig = LIBSSH2_ALLOC(session, sig_len); - - if (!sig) { - return -1; + if(rc) { + rc = read_openssh_private_key_from_memory((void **)rsa, session, + "ssh-rsa", filedata, filedata_len, passphrase); } - ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx); - - if (!ret) { - LIBSSH2_FREE(session, sig); - return -1; - } - - *signature = sig; - *signature_len = sig_len; - - return 0; -} - -#if LIBSSH2_DSA -int -_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, - const unsigned char *hash, - unsigned long hash_len, unsigned char *signature) -{ - DSA_SIG *sig; - const BIGNUM * r; - const BIGNUM * s; - int r_len, s_len; - (void) hash_len; - - sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx); - if (!sig) { - return -1; - } - -#ifdef HAVE_OPAQUE_STRUCTS - DSA_SIG_get0(sig, &r, &s); -#else - r = sig->r; - s = sig->s; -#endif - r_len = BN_num_bytes(r); - if (r_len < 1 || r_len > 20) { - DSA_SIG_free(sig); - return -1; - } - s_len = BN_num_bytes(s); - if (s_len < 1 || s_len > 20) { - DSA_SIG_free(sig); - return -1; - } - - memset(signature, 0, 40); - - BN_bn2bin(r, signature + (20 - r_len)); - BN_bn2bin(s, signature + 20 + (20 - s_len)); - - DSA_SIG_free(sig); - - return 0; -} -#endif /* LIBSSH_DSA */ - -int -_libssh2_sha1_init(libssh2_sha1_ctx *ctx) -{ -#ifdef HAVE_OPAQUE_STRUCTS - *ctx = EVP_MD_CTX_new(); - - if (*ctx == NULL) - return 0; - - if (EVP_DigestInit(*ctx, EVP_get_digestbyname("sha1"))) - return 1; - - EVP_MD_CTX_free(*ctx); - *ctx = NULL; - - return 0; -#else - EVP_MD_CTX_init(ctx); - return EVP_DigestInit(ctx, EVP_get_digestbyname("sha1")); -#endif -} - -int -_libssh2_sha1(const unsigned char *message, unsigned long len, - unsigned char *out) -{ -#ifdef HAVE_OPAQUE_STRUCTS - EVP_MD_CTX * ctx = EVP_MD_CTX_new(); - - if (ctx == NULL) - return 1; /* error */ - - if (EVP_DigestInit(ctx, EVP_get_digestbyname("sha1"))) { - EVP_DigestUpdate(ctx, message, len); - EVP_DigestFinal(ctx, out, NULL); - EVP_MD_CTX_free(ctx); - return 0; /* success */ - } - EVP_MD_CTX_free(ctx); -#else - EVP_MD_CTX ctx; - - EVP_MD_CTX_init(&ctx); - if (EVP_DigestInit(&ctx, EVP_get_digestbyname("sha1"))) { - EVP_DigestUpdate(&ctx, message, len); - EVP_DigestFinal(&ctx, out, NULL); - return 0; /* success */ - } -#endif - return 1; /* error */ -} - -int -_libssh2_sha256_init(libssh2_sha256_ctx *ctx) -{ -#ifdef HAVE_OPAQUE_STRUCTS - *ctx = EVP_MD_CTX_new(); - - if (*ctx == NULL) - return 0; - - if (EVP_DigestInit(*ctx, EVP_get_digestbyname("sha256"))) - return 1; - - EVP_MD_CTX_free(*ctx); - *ctx = NULL; - - return 0; -#else - EVP_MD_CTX_init(ctx); - return EVP_DigestInit(ctx, EVP_get_digestbyname("sha256")); -#endif -} - -int -_libssh2_sha256(const unsigned char *message, unsigned long len, - unsigned char *out) -{ -#ifdef HAVE_OPAQUE_STRUCTS - EVP_MD_CTX * ctx = EVP_MD_CTX_new(); - - if (ctx == NULL) - return 1; /* error */ - - if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha256"))) { - EVP_DigestUpdate(ctx, message, len); - EVP_DigestFinal(ctx, out, NULL); - EVP_MD_CTX_free(ctx); - return 0; /* success */ - } - EVP_MD_CTX_free(ctx); -#else - EVP_MD_CTX ctx; - - EVP_MD_CTX_init(&ctx); - if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha256"))) { - EVP_DigestUpdate(&ctx, message, len); - EVP_DigestFinal(&ctx, out, NULL); - return 0; /* success */ - } -#endif - return 1; /* error */ -} - -int -_libssh2_md5_init(libssh2_md5_ctx *ctx) -{ -#ifdef HAVE_OPAQUE_STRUCTS - *ctx = EVP_MD_CTX_new(); - - if (*ctx == NULL) - return 0; - - if (EVP_DigestInit(*ctx, EVP_get_digestbyname("md5"))) - return 1; - - EVP_MD_CTX_free(*ctx); - *ctx = NULL; - - return 0; -#else - EVP_MD_CTX_init(ctx); - return EVP_DigestInit(ctx, EVP_get_digestbyname("md5")); -#endif -} - -static unsigned char * -write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes) -{ - unsigned char *p = buf; - - /* Left space for bn size which will be written below. */ - p += 4; - - *p = 0; - BN_bn2bin(bn, p + 1); - if (!(*(p + 1) & 0x80)) { - memmove(p, p + 1, --bn_bytes); - } - _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */ - - return p + bn_bytes; +return rc; } static unsigned char * @@ -832,8 +783,8 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, { int e_bytes, n_bytes; unsigned long len; - unsigned char* key; - unsigned char* p; + unsigned char *key; + unsigned char *p; const BIGNUM * e; const BIGNUM * n; #ifdef HAVE_OPAQUE_STRUCTS @@ -849,7 +800,7 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, len = 4 + 7 + 4 + e_bytes + 4 + n_bytes; key = LIBSSH2_ALLOC(session, len); - if (key == NULL) { + if(key == NULL) { return NULL; } @@ -868,15 +819,349 @@ gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, return key; } +static int +gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + EVP_PKEY *pk) +{ + RSA* rsa = NULL; + unsigned char *key; + unsigned char *method_buf = NULL; + size_t key_len; + + _libssh2_debug(session, + LIBSSH2_TRACE_AUTH, + "Computing public key from RSA private key envelop"); + + rsa = EVP_PKEY_get1_RSA(pk); + if(rsa == NULL) { + /* Assume memory allocation error... what else could it be ? */ + goto __alloc_error; + } + + method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-rsa. */ + if(method_buf == NULL) { + goto __alloc_error; + } + + key = gen_publickey_from_rsa(session, rsa, &key_len); + if(key == NULL) { + goto __alloc_error; + } + RSA_free(rsa); + + memcpy(method_buf, "ssh-rsa", 7); + *method = method_buf; + *method_len = 7; + *pubkeydata = key; + *pubkeydata_len = key_len; + return 0; + + __alloc_error: + if(rsa != NULL) { + RSA_free(rsa); + } + if(method_buf != NULL) { + LIBSSH2_FREE(session, method_buf); + } + + return _libssh2_error(session, + LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for private key data"); +} + +static int _libssh2_rsa_new_additional_parameters(RSA *rsa) +{ + BN_CTX *ctx = NULL; + BIGNUM *aux = NULL; + BIGNUM *dmp1 = NULL; + BIGNUM *dmq1 = NULL; + const BIGNUM *p = NULL; + const BIGNUM *q = NULL; + const BIGNUM *d = NULL; + int rc = 0; + +#ifdef HAVE_OPAQUE_STRUCTS + RSA_get0_key(rsa, NULL, NULL, &d); + RSA_get0_factors(rsa, &p, &q); +#else + d = (*rsa).d; + p = (*rsa).p; + q = (*rsa).q; +#endif + + ctx = BN_CTX_new(); + if(ctx == NULL) + return -1; + + aux = BN_new(); + if(aux == NULL) { + rc = -1; + goto out; + } + + dmp1 = BN_new(); + if(dmp1 == NULL) { + rc = -1; + goto out; + } + + dmq1 = BN_new(); + if(dmq1 == NULL) { + rc = -1; + goto out; + } + + if((BN_sub(aux, q, BN_value_one()) == 0) || + (BN_mod(dmq1, d, aux, ctx) == 0) || + (BN_sub(aux, p, BN_value_one()) == 0) || + (BN_mod(dmp1, d, aux, ctx) == 0)) { + rc = -1; + goto out; + } + +#ifdef HAVE_OPAQUE_STRUCTS + RSA_set0_crt_params(rsa, dmp1, dmq1, NULL); +#else + (*rsa).dmp1 = dmp1; + (*rsa).dmq1 = dmq1; +#endif + +out: + if(aux) + BN_clear_free(aux); + BN_CTX_free(ctx); + + if(rc != 0) { + if(dmp1) + BN_clear_free(dmp1); + if(dmq1) + BN_clear_free(dmq1); + } + + return rc; +} + +static int +gen_publickey_from_rsa_openssh_priv_data(LIBSSH2_SESSION *session, + struct string_buf *decrypted, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + libssh2_rsa_ctx **rsa_ctx) +{ + int rc = 0; + size_t nlen, elen, dlen, plen, qlen, coefflen, commentlen; + unsigned char *n, *e, *d, *p, *q, *coeff, *comment; + RSA *rsa = NULL; + + _libssh2_debug(session, + LIBSSH2_TRACE_AUTH, + "Computing RSA keys from private key data"); + + /* public key data */ + if(_libssh2_get_bignum_bytes(decrypted, &n, &nlen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "RSA no n"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &e, &elen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "RSA no e"); + return -1; + } + + /* private key data */ + if(_libssh2_get_bignum_bytes(decrypted, &d, &dlen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "RSA no d"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &coeff, &coefflen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "RSA no coeff"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &p, &plen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "RSA no p"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &q, &qlen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "RSA no q"); + return -1; + } + + if(_libssh2_get_string(decrypted, &comment, &commentlen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "RSA no comment"); + return -1; + } + + if((rc = _libssh2_rsa_new(&rsa, e, elen, n, nlen, d, dlen, p, plen, + q, qlen, NULL, 0, NULL, 0, + coeff, coefflen)) != 0) { + _libssh2_debug(session, + LIBSSH2_TRACE_AUTH, + "Could not create RSA private key"); + goto fail; + } + + if(rsa != NULL) + rc = _libssh2_rsa_new_additional_parameters(rsa); + + if(rsa != NULL && pubkeydata != NULL && method != NULL) { + EVP_PKEY *pk = EVP_PKEY_new(); + EVP_PKEY_set1_RSA(pk, rsa); + + rc = gen_publickey_from_rsa_evp(session, method, method_len, + pubkeydata, pubkeydata_len, + pk); + + if(pk) + EVP_PKEY_free(pk); + } + + if(rsa_ctx != NULL) + *rsa_ctx = rsa; + else + RSA_free(rsa); + + return rc; + +fail: + + if(rsa != NULL) + RSA_free(rsa); + + return _libssh2_error(session, + LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for private key data"); +} + +static int +_libssh2_rsa_new_openssh_private(libssh2_rsa_ctx ** rsa, + LIBSSH2_SESSION * session, + const char *filename, + unsigned const char *passphrase) +{ + FILE *fp; + int rc; + unsigned char *buf = NULL; + struct string_buf *decrypted = NULL; + + if(session == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Session is required"); + return -1; + } + + _libssh2_init_if_needed(); + + fp = fopen(filename, "r"); + if(!fp) { + _libssh2_error(session, LIBSSH2_ERROR_FILE, + "Unable to open OpenSSH RSA private key file"); + return -1; + } + + rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted); + fclose(fp); + if(rc) { + return rc; + } + + /* We have a new key file, now try and parse it using supported types */ + rc = _libssh2_get_string(decrypted, &buf, NULL); + + if(rc != 0 || buf == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Public key type in decrypted key data not found"); + return -1; + } + + if(strcmp("ssh-rsa", (const char *)buf) == 0) { + rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted, + NULL, 0, + NULL, 0, rsa); + } + else { + rc = -1; + } + + if(decrypted) + _libssh2_string_buf_free(session, decrypted); + + return rc; +} + +int +_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, + LIBSSH2_SESSION * session, + const char *filename, unsigned const char *passphrase) +{ + int rc; + + pem_read_bio_func read_rsa = + (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; + (void) session; + + _libssh2_init_if_needed(); + + rc = read_private_key_from_file((void **) rsa, read_rsa, + filename, passphrase); + + if(rc) { + rc = _libssh2_rsa_new_openssh_private(rsa, session, + filename, passphrase); + } + + return rc; +} + #if LIBSSH2_DSA +int +_libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa, + LIBSSH2_SESSION * session, + const char *filedata, size_t filedata_len, + unsigned const char *passphrase) +{ + int rc; + + pem_read_bio_func read_dsa = + (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; + (void) session; + + _libssh2_init_if_needed(); + + rc = read_private_key_from_memory((void **)dsa, read_dsa, + filedata, filedata_len, passphrase); + + if(rc) { + rc = read_openssh_private_key_from_memory((void **)dsa, session, + "ssh-dsa", filedata, filedata_len, passphrase); + } + + return rc; +} + static unsigned char * gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, size_t *key_len) { int p_bytes, q_bytes, g_bytes, k_bytes; unsigned long len; - unsigned char* key; - unsigned char* p; + unsigned char *key; + unsigned char *p; const BIGNUM * p_bn; const BIGNUM * q; @@ -904,7 +1189,7 @@ gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, len = 4 + 7 + 4 + p_bytes + 4 + q_bytes + 4 + g_bytes + 4 + k_bytes; key = LIBSSH2_ALLOC(session, len); - if (key == NULL) { + if(key == NULL) { return NULL; } @@ -924,63 +1209,7 @@ gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, *key_len = (size_t)(p - key); return key; } -#endif /* LIBSSH_DSA */ -static int -gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - EVP_PKEY *pk) -{ - RSA* rsa = NULL; - unsigned char* key; - unsigned char* method_buf = NULL; - size_t key_len; - - _libssh2_debug(session, - LIBSSH2_TRACE_AUTH, - "Computing public key from RSA private key envelop"); - - rsa = EVP_PKEY_get1_RSA(pk); - if (rsa == NULL) { - /* Assume memory allocation error... what else could it be ? */ - goto __alloc_error; - } - - method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-rsa. */ - if (method_buf == NULL) { - goto __alloc_error; - } - - key = gen_publickey_from_rsa(session, rsa, &key_len); - if (key == NULL) { - goto __alloc_error; - } - RSA_free(rsa); - - memcpy(method_buf, "ssh-rsa", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; - return 0; - - __alloc_error: - if (rsa != NULL) { - RSA_free(rsa); - } - if (method_buf != NULL) { - LIBSSH2_FREE(session, method_buf); - } - - return _libssh2_error(session, - LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for private key data"); -} - -#if LIBSSH2_DSA static int gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, unsigned char **method, @@ -990,8 +1219,8 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, EVP_PKEY *pk) { DSA* dsa = NULL; - unsigned char* key; - unsigned char* method_buf = NULL; + unsigned char *key; + unsigned char *method_buf = NULL; size_t key_len; _libssh2_debug(session, @@ -999,18 +1228,18 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, "Computing public key from DSA private key envelop"); dsa = EVP_PKEY_get1_DSA(pk); - if (dsa == NULL) { + if(dsa == NULL) { /* Assume memory allocation error... what else could it be ? */ goto __alloc_error; } method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-dss. */ - if (method_buf == NULL) { + if(method_buf == NULL) { goto __alloc_error; } key = gen_publickey_from_dsa(session, dsa, &key_len); - if (key == NULL) { + if(key == NULL) { goto __alloc_error; } DSA_free(dsa); @@ -1023,10 +1252,10 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, return 0; __alloc_error: - if (dsa != NULL) { + if(dsa != NULL) { DSA_free(dsa); } - if (method_buf != NULL) { + if(method_buf != NULL) { LIBSSH2_FREE(session, method_buf); } @@ -1034,8 +1263,1646 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for private key data"); } + +static int +gen_publickey_from_dsa_openssh_priv_data(LIBSSH2_SESSION *session, + struct string_buf *decrypted, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + libssh2_dsa_ctx **dsa_ctx) +{ + int rc = 0; + size_t plen, qlen, glen, pub_len, priv_len; + unsigned char *p, *q, *g, *pub_key, *priv_key; + DSA *dsa = NULL; + + _libssh2_debug(session, + LIBSSH2_TRACE_AUTH, + "Computing DSA keys from private key data"); + + if(_libssh2_get_bignum_bytes(decrypted, &p, &plen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "DSA no p"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &q, &qlen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "DSA no q"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &g, &glen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "DSA no g"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &pub_key, &pub_len)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "DSA no public key"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &priv_key, &priv_len)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "DSA no private key"); + return -1; + } + + rc = _libssh2_dsa_new(&dsa, p, plen, q, qlen, g, glen, pub_key, pub_len, + priv_key, priv_len); + if(rc != 0) { + _libssh2_debug(session, + LIBSSH2_ERROR_PROTO, + "Could not create DSA private key"); + goto fail; + } + + if(dsa != NULL && pubkeydata != NULL && method != NULL) { + EVP_PKEY *pk = EVP_PKEY_new(); + EVP_PKEY_set1_DSA(pk, dsa); + + rc = gen_publickey_from_dsa_evp(session, method, method_len, + pubkeydata, pubkeydata_len, + pk); + + if(pk) + EVP_PKEY_free(pk); + } + + if(dsa_ctx != NULL) + *dsa_ctx = dsa; + else + DSA_free(dsa); + + return rc; + +fail: + + if(dsa != NULL) + DSA_free(dsa); + + return _libssh2_error(session, + LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for private key data"); +} + +static int +_libssh2_dsa_new_openssh_private(libssh2_dsa_ctx ** dsa, + LIBSSH2_SESSION * session, + const char *filename, + unsigned const char *passphrase) +{ + FILE *fp; + int rc; + unsigned char *buf = NULL; + struct string_buf *decrypted = NULL; + + if(session == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Session is required"); + return -1; + } + + _libssh2_init_if_needed(); + + fp = fopen(filename, "r"); + if(!fp) { + _libssh2_error(session, LIBSSH2_ERROR_FILE, + "Unable to open OpenSSH DSA private key file"); + return -1; + } + + rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted); + fclose(fp); + if(rc) { + return rc; + } + + /* We have a new key file, now try and parse it using supported types */ + rc = _libssh2_get_string(decrypted, &buf, NULL); + + if(rc != 0 || buf == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Public key type in decrypted key data not found"); + return -1; + } + + if(strcmp("ssh-dss", (const char *)buf) == 0) { + rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted, + NULL, 0, + NULL, 0, dsa); + } + else { + rc = -1; + } + + if(decrypted) + _libssh2_string_buf_free(session, decrypted); + + return rc; +} + +int +_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, + LIBSSH2_SESSION * session, + const char *filename, unsigned const char *passphrase) +{ + int rc; + + pem_read_bio_func read_dsa = + (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; + (void) session; + + _libssh2_init_if_needed(); + + rc = read_private_key_from_file((void **) dsa, read_dsa, + filename, passphrase); + + if(rc) { + rc = _libssh2_dsa_new_openssh_private(dsa, session, + filename, passphrase); + } + + return rc; +} + #endif /* LIBSSH_DSA */ +#if LIBSSH2_ECDSA + +int +_libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx, + LIBSSH2_SESSION * session, + const char *filedata, size_t filedata_len, + unsigned const char *passphrase) +{ + int rc; + + pem_read_bio_func read_ec = + (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; + (void) session; + + _libssh2_init_if_needed(); + + rc = read_private_key_from_memory((void **) ec_ctx, read_ec, + filedata, filedata_len, passphrase); + + if(rc) { + rc = read_openssh_private_key_from_memory((void **)ec_ctx, session, + "ssh-ecdsa", filedata, + filedata_len, passphrase); + } + + return rc; +} + +#endif /* LIBSSH2_ECDSA */ + + +#if LIBSSH2_ED25519 + +int +_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_x25519_ctx **out_ctx, + unsigned char **out_public_key, + unsigned char **out_private_key) +{ + EVP_PKEY *key = NULL; + EVP_PKEY_CTX *pctx = NULL; + PKCS8_PRIV_KEY_INFO *info = NULL; + ASN1_OCTET_STRING *oct = NULL; + X509_PUBKEY *pubkey = NULL; + libssh2_ed25519_ctx *ctx = NULL; + const unsigned char *pkcs, *priv, *pub; + int privLen, pubLen, pkcsLen; + int rc = -1; + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL); + if(pctx == NULL) + return -1; + + EVP_PKEY_keygen_init(pctx); + EVP_PKEY_keygen(pctx, &key); + info = EVP_PKEY2PKCS8(key); + + if(info == NULL || !PKCS8_pkey_get0(NULL, &pkcs, &pkcsLen, NULL, info)) + goto cleanExit; + + oct = d2i_ASN1_OCTET_STRING(NULL, &pkcs, pkcsLen); + if(oct == NULL) { + goto cleanExit; + } + + priv = ASN1_STRING_get0_data(oct); + privLen = ASN1_STRING_length(oct); + + if(privLen != LIBSSH2_ED25519_KEY_LEN) + goto cleanExit; + + pubkey = X509_PUBKEY_new(); + if(pubkey == NULL || !X509_PUBKEY_set(&pubkey, key)) + goto cleanExit; + + if(!X509_PUBKEY_get0_param(NULL, &pub, &pubLen, NULL, pubkey)) + goto cleanExit; + + if(pubLen != LIBSSH2_ED25519_KEY_LEN) + goto cleanExit; + + if(out_private_key != NULL) { + *out_private_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN); + if(*out_private_key == NULL) + goto cleanExit; + + memcpy(*out_private_key, priv, LIBSSH2_ED25519_KEY_LEN); + } + + if(out_public_key != NULL) { + *out_public_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN); + if(*out_public_key == NULL) + goto cleanExit; + + memcpy(*out_public_key, pub, LIBSSH2_ED25519_KEY_LEN); + } + + if(out_ctx != NULL) { + ctx = malloc(sizeof(libssh2_x25519_ctx)); + if(ctx == NULL) + goto cleanExit; + + ctx->private_key = + EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, + (const unsigned char *)priv, + LIBSSH2_ED25519_KEY_LEN); + + ctx->public_key = + EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, + (const unsigned char *)pub, + LIBSSH2_ED25519_KEY_LEN); + + if(ctx->public_key == NULL || ctx->private_key == NULL) { + _libssh2_x25519_free(ctx); + goto cleanExit; + } + + *out_ctx = ctx; + } + + /* success */ + rc = 0; + +cleanExit: + + if(info) + PKCS8_PRIV_KEY_INFO_free(info); + if(pctx) + EVP_PKEY_CTX_free(pctx); + if(oct) + ASN1_OCTET_STRING_free(oct); + if(pubkey) + X509_PUBKEY_free(pubkey); + if(key) + EVP_PKEY_free(key); + + return rc; +} + +static int +gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session, + struct string_buf *decrypted, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + libssh2_ed25519_ctx **out_ctx) +{ + libssh2_ed25519_ctx *ctx = NULL; + unsigned char *method_buf = NULL; + unsigned char *key = NULL; + int i, ret = 0; + unsigned char *pub_key, *priv_key, *buf; + size_t key_len = 0, tmp_len = 0; + unsigned char *p; + + _libssh2_debug(session, + LIBSSH2_TRACE_AUTH, + "Computing ED25519 keys from private key data"); + + if(_libssh2_get_string(decrypted, &pub_key, &tmp_len) || + tmp_len != LIBSSH2_ED25519_KEY_LEN) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Wrong public key length"); + return -1; + } + + if(_libssh2_get_string(decrypted, &priv_key, &tmp_len) || + tmp_len != LIBSSH2_ED25519_PRIVATE_KEY_LEN) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Wrong private key length"); + ret = -1; + goto clean_exit; + } + + ctx = _libssh2_ed25519_new_ctx(); + if(ctx == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for ed25519 key"); + ret = -1; + goto clean_exit; + } + + /* first 32 bytes of priv_key is the private key, the last 32 bytes are + the public key */ + ctx->private_key = + EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, + (const unsigned char *)priv_key, + LIBSSH2_ED25519_KEY_LEN); + + ctx->public_key = + EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, + (const unsigned char *)pub_key, + LIBSSH2_ED25519_KEY_LEN); + + /* comment */ + if(_libssh2_get_string(decrypted, &buf, &tmp_len)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unable to read comment"); + ret = -1; + goto clean_exit; + } + + if(tmp_len > 0) { + unsigned char *comment = LIBSSH2_CALLOC(session, tmp_len + 1); + if(comment != NULL) { + memcpy(comment, buf, tmp_len); + memcpy(comment + tmp_len, "\0", 1); + + _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Key comment: %s", + comment); + + LIBSSH2_FREE(session, comment); + } + } + + /* Padding */ + i = 1; + while(decrypted->dataptr < decrypted->data + decrypted->len) { + if(*decrypted->dataptr != i) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Wrong padding"); + ret = -1; + goto clean_exit; + } + i++; + decrypted->dataptr++; + } + + if(ret == 0) { + _libssh2_debug(session, + LIBSSH2_TRACE_AUTH, + "Computing public key from ED25519 " + "private key envelop"); + + method_buf = LIBSSH2_ALLOC(session, 11); /* ssh-ed25519. */ + if(method_buf == NULL) { + goto clean_exit; + } + + /* Key form is: type_len(4) + type(11) + pub_key_len(4) + + pub_key(32). */ + key_len = LIBSSH2_ED25519_KEY_LEN + 19; + key = LIBSSH2_CALLOC(session, key_len); + if(key == NULL) { + goto clean_exit; + } + + p = key; + + _libssh2_store_str(&p, "ssh-ed25519", 11); + _libssh2_store_str(&p, (const char *)pub_key, LIBSSH2_ED25519_KEY_LEN); + + memcpy(method_buf, "ssh-ed25519", 11); + + if(method != NULL) + *method = method_buf; + else + LIBSSH2_FREE(session, method_buf); + + if(method_len != NULL) + *method_len = 11; + + if(pubkeydata != NULL) + *pubkeydata = key; + else + LIBSSH2_FREE(session, key); + + if(pubkeydata_len != NULL) + *pubkeydata_len = key_len; + + if(out_ctx != NULL) + *out_ctx = ctx; + else if(ctx != NULL) + _libssh2_ed25519_free(ctx); + + return 0; + } + +clean_exit: + + if(ctx) + _libssh2_ed25519_free(ctx); + + if(method_buf) + LIBSSH2_FREE(session, method_buf); + + if(key) + LIBSSH2_FREE(session, key); + + return -1; +} + +int +_libssh2_ed25519_new_private(libssh2_ed25519_ctx ** ed_ctx, + LIBSSH2_SESSION * session, + const char *filename, const uint8_t *passphrase) +{ + int rc; + FILE *fp; + unsigned char *buf; + struct string_buf *decrypted = NULL; + libssh2_ed25519_ctx *ctx = NULL; + + if(session == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Session is required"); + return -1; + } + + _libssh2_init_if_needed(); + + fp = fopen(filename, "r"); + if(!fp) { + _libssh2_error(session, LIBSSH2_ERROR_FILE, + "Unable to open ED25519 private key file"); + return -1; + } + + rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted); + fclose(fp); + if(rc) { + return rc; + } + + /* We have a new key file, now try and parse it using supported types */ + rc = _libssh2_get_string(decrypted, &buf, NULL); + + if(rc != 0 || buf == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Public key type in decrypted key data not found"); + return -1; + } + + if(strcmp("ssh-ed25519", (const char *)buf) == 0) { + rc = gen_publickey_from_ed25519_openssh_priv_data(session, + decrypted, + NULL, + NULL, + NULL, + NULL, + &ctx); + } + else { + rc = -1; + } + + if(decrypted) + _libssh2_string_buf_free(session, decrypted); + + if(rc == 0) { + if(ed_ctx != NULL) + *ed_ctx = ctx; + else if(ctx != NULL) + _libssh2_ed25519_free(ctx); + } + + return rc; +} + +int +_libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx ** ed_ctx, + LIBSSH2_SESSION * session, + const char *filedata, + size_t filedata_len, + unsigned const char *passphrase) +{ + return read_openssh_private_key_from_memory((void **)ed_ctx, session, + "ssh-ed25519", + filedata, filedata_len, + passphrase); +} + +int +_libssh2_ed25519_new_public(libssh2_ed25519_ctx ** ed_ctx, + LIBSSH2_SESSION * session, + const unsigned char *raw_pub_key, + const uint8_t key_len) +{ + libssh2_ed25519_ctx *ctx = NULL; + EVP_PKEY *public_key = NULL; + + if(ed_ctx == NULL) + return -1; + + public_key = + EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, + (const unsigned char *)raw_pub_key, + key_len); + if(public_key == NULL) { + return _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "could not create ED25519 public key"); + } + + ctx = _libssh2_ed25519_new_ctx(); + if(ctx == NULL) { + return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "could not alloc public/private key"); + } + + ctx->public_key = public_key; + + if(ed_ctx != NULL) + *ed_ctx = ctx; + else if(ctx != NULL) + _libssh2_ed25519_free(ctx); + + return 0; +} + +#endif /* LIBSSH2_ED25519 */ + +int +_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, + libssh2_rsa_ctx * rsactx, + const unsigned char *hash, + size_t hash_len, + unsigned char **signature, size_t *signature_len) +{ + int ret; + unsigned char *sig; + unsigned int sig_len; + + sig_len = RSA_size(rsactx); + sig = LIBSSH2_ALLOC(session, sig_len); + + if(!sig) { + return -1; + } + + ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx); + + if(!ret) { + LIBSSH2_FREE(session, sig); + return -1; + } + + *signature = sig; + *signature_len = sig_len; + + return 0; +} + +#if LIBSSH2_DSA +int +_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, + const unsigned char *hash, + unsigned long hash_len, unsigned char *signature) +{ + DSA_SIG *sig; + const BIGNUM * r; + const BIGNUM * s; + int r_len, s_len; + (void) hash_len; + + sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx); + if(!sig) { + return -1; + } + +#ifdef HAVE_OPAQUE_STRUCTS + DSA_SIG_get0(sig, &r, &s); +#else + r = sig->r; + s = sig->s; +#endif + r_len = BN_num_bytes(r); + if(r_len < 1 || r_len > 20) { + DSA_SIG_free(sig); + return -1; + } + s_len = BN_num_bytes(s); + if(s_len < 1 || s_len > 20) { + DSA_SIG_free(sig); + return -1; + } + + memset(signature, 0, 40); + + BN_bn2bin(r, signature + (20 - r_len)); + BN_bn2bin(s, signature + 20 + (20 - s_len)); + + DSA_SIG_free(sig); + + return 0; +} +#endif /* LIBSSH_DSA */ + +#if LIBSSH2_ECDSA + +int +_libssh2_ecdsa_sign(LIBSSH2_SESSION * session, libssh2_ecdsa_ctx * ec_ctx, + const unsigned char *hash, unsigned long hash_len, + unsigned char **signature, size_t *signature_len) +{ + int r_len, s_len; + int rc = 0; + size_t out_buffer_len = 0; + unsigned char *sp; + const BIGNUM *pr = NULL, *ps = NULL; + unsigned char *temp_buffer = NULL; + unsigned char *out_buffer = NULL; + + ECDSA_SIG *sig = ECDSA_do_sign(hash, hash_len, ec_ctx); + if(sig == NULL) + return -1; +#ifdef HAVE_OPAQUE_STRUCTS + ECDSA_SIG_get0(sig, &pr, &ps); +#else + pr = sig->r; + ps = sig->s; +#endif + + r_len = BN_num_bytes(pr) + 1; + s_len = BN_num_bytes(ps) + 1; + + temp_buffer = malloc(r_len + s_len + 8); + if(temp_buffer == NULL) { + rc = -1; + goto clean_exit; + } + + sp = temp_buffer; + sp = write_bn(sp, pr, r_len); + sp = write_bn(sp, ps, s_len); + + out_buffer_len = (size_t)(sp - temp_buffer); + + out_buffer = LIBSSH2_CALLOC(session, out_buffer_len); + if(out_buffer == NULL) { + rc = -1; + goto clean_exit; + } + + memcpy(out_buffer, temp_buffer, out_buffer_len); + + *signature = out_buffer; + *signature_len = out_buffer_len; + +clean_exit: + + if(temp_buffer != NULL) + free(temp_buffer); + + if(sig) + ECDSA_SIG_free(sig); + + return rc; +} +#endif /* LIBSSH2_ECDSA */ + +int +_libssh2_sha1_init(libssh2_sha1_ctx *ctx) +{ +#ifdef HAVE_OPAQUE_STRUCTS + *ctx = EVP_MD_CTX_new(); + + if(*ctx == NULL) + return 0; + + if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha1"))) + return 1; + + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + + return 0; +#else + EVP_MD_CTX_init(ctx); + return EVP_DigestInit(ctx, EVP_get_digestbyname("sha1")); +#endif +} + +int +_libssh2_sha1(const unsigned char *message, unsigned long len, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + EVP_MD_CTX * ctx = EVP_MD_CTX_new(); + + if(ctx == NULL) + return 1; /* error */ + + if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha1"))) { + EVP_DigestUpdate(ctx, message, len); + EVP_DigestFinal(ctx, out, NULL); + EVP_MD_CTX_free(ctx); + return 0; /* success */ + } + EVP_MD_CTX_free(ctx); +#else + EVP_MD_CTX ctx; + + EVP_MD_CTX_init(&ctx); + if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha1"))) { + EVP_DigestUpdate(&ctx, message, len); + EVP_DigestFinal(&ctx, out, NULL); + return 0; /* success */ + } +#endif + return 1; /* error */ +} + +int +_libssh2_sha256_init(libssh2_sha256_ctx *ctx) +{ +#ifdef HAVE_OPAQUE_STRUCTS + *ctx = EVP_MD_CTX_new(); + + if(*ctx == NULL) + return 0; + + if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha256"))) + return 1; + + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + + return 0; +#else + EVP_MD_CTX_init(ctx); + return EVP_DigestInit(ctx, EVP_get_digestbyname("sha256")); +#endif +} + +int +_libssh2_sha256(const unsigned char *message, unsigned long len, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + EVP_MD_CTX * ctx = EVP_MD_CTX_new(); + + if(ctx == NULL) + return 1; /* error */ + + if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha256"))) { + EVP_DigestUpdate(ctx, message, len); + EVP_DigestFinal(ctx, out, NULL); + EVP_MD_CTX_free(ctx); + return 0; /* success */ + } + EVP_MD_CTX_free(ctx); +#else + EVP_MD_CTX ctx; + + EVP_MD_CTX_init(&ctx); + if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha256"))) { + EVP_DigestUpdate(&ctx, message, len); + EVP_DigestFinal(&ctx, out, NULL); + return 0; /* success */ + } +#endif + return 1; /* error */ +} + +int +_libssh2_sha384_init(libssh2_sha384_ctx *ctx) +{ +#ifdef HAVE_OPAQUE_STRUCTS + *ctx = EVP_MD_CTX_new(); + + if(*ctx == NULL) + return 0; + + if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha384"))) + return 1; + + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + + return 0; +#else + EVP_MD_CTX_init(ctx); + return EVP_DigestInit(ctx, EVP_get_digestbyname("sha384")); +#endif +} + +int +_libssh2_sha384(const unsigned char *message, unsigned long len, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + EVP_MD_CTX * ctx = EVP_MD_CTX_new(); + + if(ctx == NULL) + return 1; /* error */ + + if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha384"))) { + EVP_DigestUpdate(ctx, message, len); + EVP_DigestFinal(ctx, out, NULL); + EVP_MD_CTX_free(ctx); + return 0; /* success */ + } + EVP_MD_CTX_free(ctx); +#else + EVP_MD_CTX ctx; + + EVP_MD_CTX_init(&ctx); + if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha384"))) { + EVP_DigestUpdate(&ctx, message, len); + EVP_DigestFinal(&ctx, out, NULL); + return 0; /* success */ + } +#endif + return 1; /* error */ +} + +int +_libssh2_sha512_init(libssh2_sha512_ctx *ctx) +{ +#ifdef HAVE_OPAQUE_STRUCTS + *ctx = EVP_MD_CTX_new(); + + if(*ctx == NULL) + return 0; + + if(EVP_DigestInit(*ctx, EVP_get_digestbyname("sha512"))) + return 1; + + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + + return 0; +#else + EVP_MD_CTX_init(ctx); + return EVP_DigestInit(ctx, EVP_get_digestbyname("sha512")); +#endif +} + +int +_libssh2_sha512(const unsigned char *message, unsigned long len, + unsigned char *out) +{ +#ifdef HAVE_OPAQUE_STRUCTS + EVP_MD_CTX * ctx = EVP_MD_CTX_new(); + + if(ctx == NULL) + return 1; /* error */ + + if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha512"))) { + EVP_DigestUpdate(ctx, message, len); + EVP_DigestFinal(ctx, out, NULL); + EVP_MD_CTX_free(ctx); + return 0; /* success */ + } + EVP_MD_CTX_free(ctx); +#else + EVP_MD_CTX ctx; + + EVP_MD_CTX_init(&ctx); + if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha512"))) { + EVP_DigestUpdate(&ctx, message, len); + EVP_DigestFinal(&ctx, out, NULL); + return 0; /* success */ + } +#endif + return 1; /* error */ +} + +int +_libssh2_md5_init(libssh2_md5_ctx *ctx) +{ +#ifdef HAVE_OPAQUE_STRUCTS + *ctx = EVP_MD_CTX_new(); + + if(*ctx == NULL) + return 0; + + if(EVP_DigestInit(*ctx, EVP_get_digestbyname("md5"))) + return 1; + + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + + return 0; +#else + EVP_MD_CTX_init(ctx); + return EVP_DigestInit(ctx, EVP_get_digestbyname("md5")); +#endif +} + +#if LIBSSH2_ECDSA + +static int +gen_publickey_from_ec_evp(LIBSSH2_SESSION *session, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + EVP_PKEY *pk) +{ + int rc = 0; + EC_KEY *ec = NULL; + unsigned char *p; + unsigned char *method_buf = NULL; + unsigned char *key; + size_t key_len = 0; + unsigned char *octal_value = NULL; + size_t octal_len; + const EC_POINT *public_key; + const EC_GROUP *group; + BN_CTX *bn_ctx; + libssh2_curve_type type; + + _libssh2_debug(session, + LIBSSH2_TRACE_AUTH, + "Computing public key from EC private key envelop"); + + bn_ctx = BN_CTX_new(); + if(bn_ctx == NULL) + return -1; + + ec = EVP_PKEY_get1_EC_KEY(pk); + if(ec == NULL) { + rc = -1; + goto clean_exit; + } + + public_key = EC_KEY_get0_public_key(ec); + group = EC_KEY_get0_group(ec); + type = _libssh2_ecdsa_key_get_curve_type(ec); + + method_buf = LIBSSH2_ALLOC(session, 19); + if(method_buf == NULL) { + return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "out of memory"); + } + + if(type == LIBSSH2_EC_CURVE_NISTP256) + memcpy(method_buf, "ecdsa-sha2-nistp256", 19); + else if(type == LIBSSH2_EC_CURVE_NISTP384) + memcpy(method_buf, "ecdsa-sha2-nistp384", 19); + else if(type == LIBSSH2_EC_CURVE_NISTP521) + memcpy(method_buf, "ecdsa-sha2-nistp521", 19); + else { + _libssh2_debug(session, + LIBSSH2_TRACE_ERROR, + "Unsupported EC private key type"); + rc = -1; + goto clean_exit; + } + + /* get length */ + octal_len = EC_POINT_point2oct(group, public_key, + POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, bn_ctx); + if(octal_len > EC_MAX_POINT_LEN) { + rc = -1; + goto clean_exit; + } + + octal_value = malloc(octal_len); + if(octal_value == NULL) { + rc = -1; + goto clean_exit; + } + + /* convert to octal */ + if(EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, + octal_value, octal_len, bn_ctx) != octal_len) { + rc = -1; + goto clean_exit; + } + + /* Key form is: type_len(4) + type(19) + domain_len(4) + domain(8) + + pub_key_len(4) + pub_key(~65). */ + key_len = 4 + 19 + 4 + 8 + 4 + octal_len; + key = LIBSSH2_ALLOC(session, key_len); + if(key == NULL) { + rc = -1; + goto clean_exit; + } + + /* Process key encoding. */ + p = key; + + /* Key type */ + _libssh2_store_str(&p, (const char *)method_buf, 19); + + /* Name domain */ + _libssh2_store_str(&p, (const char *)method_buf + 11, 8); + + /* Public key */ + _libssh2_store_str(&p, (const char *)octal_value, octal_len); + + *method = method_buf; + *method_len = 19; + *pubkeydata = key; + *pubkeydata_len = key_len; + +clean_exit: + + if(ec != NULL) + EC_KEY_free(ec); + + if(bn_ctx != NULL) { + BN_CTX_free(bn_ctx); + } + + if(octal_value != NULL) + free(octal_value); + + if(rc == 0) + return 0; + + if(method_buf != NULL) + LIBSSH2_FREE(session, method_buf); + + return -1; +} + +static int +gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session, + libssh2_curve_type curve_type, + struct string_buf *decrypted, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + libssh2_ecdsa_ctx **ec_ctx) +{ + int rc = 0; + size_t curvelen, exponentlen, pointlen; + unsigned char *curve, *exponent, *point_buf; + EC_KEY *ec_key = NULL; + BIGNUM *bn_exponent; + + _libssh2_debug(session, + LIBSSH2_TRACE_AUTH, + "Computing ECDSA keys from private key data"); + + if(_libssh2_get_string(decrypted, &curve, &curvelen) || + curvelen == 0) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "ECDSA no curve"); + return -1; + } + + if(_libssh2_get_string(decrypted, &point_buf, &pointlen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "ECDSA no point"); + return -1; + } + + if(_libssh2_get_bignum_bytes(decrypted, &exponent, &exponentlen)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "ECDSA no exponent"); + return -1; + } + + if((rc = _libssh2_ecdsa_curve_name_with_octal_new(&ec_key, point_buf, + pointlen, curve_type)) != 0) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "ECDSA could not create key"); + goto fail; + } + + bn_exponent = BN_new(); + if(bn_exponent == NULL) { + rc = -1; + goto fail; + } + + BN_bin2bn(exponent, exponentlen, bn_exponent); + rc = (EC_KEY_set_private_key(ec_key, bn_exponent) != 1); + + if(rc == 0 && ec_key != NULL && pubkeydata != NULL && method != NULL) { + EVP_PKEY *pk = EVP_PKEY_new(); + EVP_PKEY_set1_EC_KEY(pk, ec_key); + + rc = gen_publickey_from_ec_evp(session, method, method_len, + pubkeydata, pubkeydata_len, + pk); + + if(pk) + EVP_PKEY_free(pk); + } + + if(ec_ctx != NULL) + *ec_ctx = ec_key; + else + EC_KEY_free(ec_key); + + return rc; + +fail: + + if(ec_key != NULL) + EC_KEY_free(ec_key); + + return _libssh2_error(session, + LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for private key data"); + + +} + +static int +_libssh2_ecdsa_new_openssh_private(libssh2_ecdsa_ctx ** ec_ctx, + LIBSSH2_SESSION * session, + const char *filename, + unsigned const char *passphrase) +{ + FILE *fp; + int rc; + unsigned char *buf = NULL; + libssh2_curve_type type; + struct string_buf *decrypted = NULL; + + if(session == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Session is required"); + return -1; + } + + _libssh2_init_if_needed(); + + fp = fopen(filename, "r"); + if(!fp) { + _libssh2_error(session, LIBSSH2_ERROR_FILE, + "Unable to open OpenSSH ECDSA private key file"); + return -1; + } + + rc = _libssh2_openssh_pem_parse(session, passphrase, fp, &decrypted); + fclose(fp); + if(rc) { + return rc; + } + + /* We have a new key file, now try and parse it using supported types */ + rc = _libssh2_get_string(decrypted, &buf, NULL); + + if(rc != 0 || buf == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Public key type in decrypted key data not found"); + return -1; + } + + rc = _libssh2_ecdsa_curve_type_from_name((const char *)buf, &type); + + if(rc == 0) { + rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type, + decrypted, NULL, 0, + NULL, 0, ec_ctx); + } + else { + rc = -1; + } + + if(decrypted) + _libssh2_string_buf_free(session, decrypted); + + return rc; +} + +int +_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx, + LIBSSH2_SESSION * session, + const char *filename, unsigned const char *passphrase) +{ + int rc; + + pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey; + (void) session; + + _libssh2_init_if_needed(); + + rc = read_private_key_from_file((void **) ec_ctx, read_ec, + filename, passphrase); + + if(rc) { + return _libssh2_ecdsa_new_openssh_private(ec_ctx, session, + filename, passphrase); + } + + return rc; +} + +/* + * _libssh2_ecdsa_create_key + * + * Creates a local private key based on input curve + * and returns octal value and octal length + * + */ + +int +_libssh2_ecdsa_create_key(LIBSSH2_SESSION *session, + _libssh2_ec_key **out_private_key, + unsigned char **out_public_key_octal, + size_t *out_public_key_octal_len, + libssh2_curve_type curve_type) +{ + int ret = 1; + size_t octal_len = 0; + unsigned char octal_value[EC_MAX_POINT_LEN]; + const EC_POINT *public_key = NULL; + EC_KEY *private_key = NULL; + const EC_GROUP *group = NULL; + + /* create key */ + BN_CTX *bn_ctx = BN_CTX_new(); + if(!bn_ctx) + return -1; + + private_key = EC_KEY_new_by_curve_name(curve_type); + group = EC_KEY_get0_group(private_key); + + EC_KEY_generate_key(private_key); + public_key = EC_KEY_get0_public_key(private_key); + + /* get length */ + octal_len = EC_POINT_point2oct(group, public_key, + POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, bn_ctx); + if(octal_len > EC_MAX_POINT_LEN) { + ret = -1; + goto clean_exit; + } + + /* convert to octal */ + if(EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, + octal_value, octal_len, bn_ctx) != octal_len) { + ret = -1; + goto clean_exit; + } + + if(out_private_key != NULL) + *out_private_key = private_key; + + if(out_public_key_octal) { + *out_public_key_octal = LIBSSH2_ALLOC(session, octal_len); + if(*out_public_key_octal == NULL) { + ret = -1; + goto clean_exit; + } + + memcpy(*out_public_key_octal, octal_value, octal_len); + } + + if(out_public_key_octal_len != NULL) + *out_public_key_octal_len = octal_len; + +clean_exit: + + if(bn_ctx) + BN_CTX_free(bn_ctx); + + return (ret == 1) ? 0 : -1; +} + +/* _libssh2_ecdh_gen_k + * + * Computes the shared secret K given a local private key, + * remote public key and length + */ + +int +_libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key, + const unsigned char *server_public_key, size_t server_public_key_len) +{ + int ret = 0; + int rc; + size_t secret_len; + unsigned char *secret = NULL; + const EC_GROUP *private_key_group; + EC_POINT *server_public_key_point; + + BN_CTX *bn_ctx = BN_CTX_new(); + + if(!bn_ctx) + return -1; + + if(k == NULL) + return -1; + + private_key_group = EC_KEY_get0_group(private_key); + + server_public_key_point = EC_POINT_new(private_key_group); + if(server_public_key_point == NULL) + return -1; + + rc = EC_POINT_oct2point(private_key_group, server_public_key_point, + server_public_key, server_public_key_len, bn_ctx); + if(rc != 1) { + ret = -1; + goto clean_exit; + } + + secret_len = (EC_GROUP_get_degree(private_key_group) + 7) / 8; + secret = malloc(secret_len); + if(!secret) { + ret = -1; + goto clean_exit; + } + + secret_len = ECDH_compute_key(secret, secret_len, server_public_key_point, + private_key, NULL); + + if(secret_len <= 0 || secret_len > EC_MAX_POINT_LEN) { + ret = -1; + goto clean_exit; + } + + BN_bin2bn(secret, secret_len, *k); + +clean_exit: + + if(server_public_key_point != NULL) + EC_POINT_free(server_public_key_point); + + if(bn_ctx != NULL) + BN_CTX_free(bn_ctx); + + if(secret != NULL) + free(secret); + + return ret; +} + + +#endif /* LIBSSH2_ECDSA */ + +#if LIBSSH2_ED25519 + +int +_libssh2_ed25519_sign(libssh2_ed25519_ctx *ctx, LIBSSH2_SESSION *session, + uint8_t **out_sig, size_t *out_sig_len, + const uint8_t *message, size_t message_len) +{ + int rc = -1; + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); + size_t sig_len = 0; + unsigned char *sig = NULL; + + if(md_ctx != NULL) { + if(EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, ctx->private_key) != 1) + goto clean_exit; + if(EVP_DigestSign(md_ctx, NULL, &sig_len, message, message_len) != 1) + goto clean_exit; + + if(sig_len != LIBSSH2_ED25519_SIG_LEN) + goto clean_exit; + + sig = LIBSSH2_CALLOC(session, sig_len); + if(sig == NULL) + goto clean_exit; + + rc = EVP_DigestSign(md_ctx, sig, &sig_len, message, message_len); + } + + if(rc == 1) { + *out_sig = sig; + *out_sig_len = sig_len; + } + else { + *out_sig_len = 0; + *out_sig = NULL; + LIBSSH2_FREE(session, sig); + } + +clean_exit: + + if(md_ctx) + EVP_MD_CTX_free(md_ctx); + + return (rc == 1 ? 0 : -1); +} + +int +_libssh2_curve25519_gen_k(_libssh2_bn **k, + uint8_t private_key[LIBSSH2_ED25519_KEY_LEN], + uint8_t server_public_key[LIBSSH2_ED25519_KEY_LEN]) +{ + int rc = -1; + unsigned char out_shared_key[LIBSSH2_ED25519_KEY_LEN]; + EVP_PKEY *peer_key = NULL, *server_key = NULL; + EVP_PKEY_CTX *server_key_ctx = NULL; + BN_CTX *bn_ctx = NULL; + size_t out_len = 0; + + if(k == NULL || *k == NULL) + return -1; + + bn_ctx = BN_CTX_new(); + if(bn_ctx == NULL) + return -1; + + peer_key = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, + server_public_key, + LIBSSH2_ED25519_KEY_LEN); + + server_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, + private_key, + LIBSSH2_ED25519_KEY_LEN); + + if(peer_key == NULL || server_key == NULL) { + goto cleanExit; + } + + server_key_ctx = EVP_PKEY_CTX_new(server_key, NULL); + if(server_key_ctx == NULL) { + goto cleanExit; + } + + rc = EVP_PKEY_derive_init(server_key_ctx); + if(rc <= 0) goto cleanExit; + + rc = EVP_PKEY_derive_set_peer(server_key_ctx, peer_key); + if(rc <= 0) goto cleanExit; + + rc = EVP_PKEY_derive(server_key_ctx, NULL, &out_len); + if(rc <= 0) goto cleanExit; + + if(out_len != LIBSSH2_ED25519_KEY_LEN) { + rc = -1; + goto cleanExit; + } + + rc = EVP_PKEY_derive(server_key_ctx, out_shared_key, &out_len); + + if(rc == 1 && out_len == LIBSSH2_ED25519_KEY_LEN) { + BN_bin2bn(out_shared_key, LIBSSH2_ED25519_KEY_LEN, *k); + } + else { + rc = -1; + } + +cleanExit: + + if(server_key_ctx) + EVP_PKEY_CTX_free(server_key_ctx); + if(peer_key) + EVP_PKEY_free(peer_key); + if(server_key) + EVP_PKEY_free(server_key); + if(bn_ctx != NULL) + BN_CTX_free(bn_ctx); + + return (rc == 1) ? 0 : -1; +} + + +int +_libssh2_ed25519_verify(libssh2_ed25519_ctx *ctx, const uint8_t *s, + size_t s_len, const uint8_t *m, size_t m_len) +{ + int ret = -1; + + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); + if(NULL == md_ctx) + return -1; + + ret = EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, ctx->public_key); + if(ret != 1) + goto clean_exit; + + ret = EVP_DigestVerify(md_ctx, s, s_len, m, m_len); + + clean_exit: + + EVP_MD_CTX_free(md_ctx); + + return (ret == 1) ? 0 : -1; +} + +#endif /* LIBSSH2_ED25519 */ + +static int +_libssh2_pub_priv_openssh_keyfile(LIBSSH2_SESSION *session, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + const char *privatekey, + const char *passphrase) +{ + FILE *fp; + unsigned char *buf = NULL; + struct string_buf *decrypted = NULL; + int rc = 0; + + if(session == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Session is required"); + return -1; + } + + _libssh2_init_if_needed(); + + fp = fopen(privatekey, "r"); + if(!fp) { + _libssh2_error(session, LIBSSH2_ERROR_FILE, + "Unable to open private key file"); + return -1; + } + + rc = _libssh2_openssh_pem_parse(session, (const unsigned char *)passphrase, + fp, &decrypted); + fclose(fp); + if(rc) { + _libssh2_error(session, LIBSSH2_ERROR_FILE, + "Not an OpenSSH key file"); + return rc; + } + + /* We have a new key file, now try and parse it using supported types */ + rc = _libssh2_get_string(decrypted, &buf, NULL); + + if(rc != 0 || buf == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Public key type in decrypted key data not found"); + return -1; + } + + rc = -1; + +#if LIBSSH2_ED25519 + if(strcmp("ssh-ed25519", (const char *)buf) == 0) { + rc = gen_publickey_from_ed25519_openssh_priv_data(session, decrypted, + method, method_len, + pubkeydata, + pubkeydata_len, + NULL); + } +#endif +#if LIBSSH2_RSA + if(strcmp("ssh-rsa", (const char *)buf) == 0) { + rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted, + method, method_len, + pubkeydata, + pubkeydata_len, + NULL); + } +#endif +#if LIBSSH2_DSA + if(strcmp("ssh-dss", (const char *)buf) == 0) { + rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted, + method, method_len, + pubkeydata, + pubkeydata_len, + NULL); + } +#endif +#if LIBSSH2_ECDSA + { + libssh2_curve_type type; + + if(_libssh2_ecdsa_curve_type_from_name((const char *)buf, + &type) == 0) { + rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type, + decrypted, + method, method_len, + pubkeydata, + pubkeydata_len, + NULL); + } + } +#endif + + if(decrypted) + _libssh2_string_buf_free(session, decrypted); + + if(rc != 0) { + _libssh2_error(session, LIBSSH2_ERROR_FILE, + "Unsupported OpenSSH key type"); + } + + return rc; +} + int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, unsigned char **method, @@ -1049,6 +2916,7 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, BIO* bp; EVP_PKEY* pk; int pktype; + int rc; _libssh2_debug(session, LIBSSH2_TRACE_AUTH, @@ -1056,31 +2924,35 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, privatekey); bp = BIO_new_file(privatekey, "r"); - if (bp == NULL) { + if(bp == NULL) { return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Unable to extract public key from private key " "file: Unable to open private key file"); } - if (!EVP_get_cipherbyname("des")) { - /* If this cipher isn't loaded it's a pretty good indication that none - * are. I have *NO DOUBT* that there's a better way to deal with this - * ($#&%#$(%$#( Someone buy me an OpenSSL manual and I'll read up on - * it. - */ - OpenSSL_add_all_ciphers(); - } + BIO_reset(bp); - pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void*)passphrase); + pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase); BIO_free(bp); - if (pk == NULL) { - return _libssh2_error(session, - LIBSSH2_ERROR_FILE, - "Unable to extract public key " - "from private key file: " - "Wrong passphrase or invalid/unrecognized " - "private key file format"); + if(pk == NULL) { + + /* Try OpenSSH format */ + rc = _libssh2_pub_priv_openssh_keyfile(session, + method, + method_len, + pubkeydata, pubkeydata_len, + privatekey, passphrase); + if(rc != 0) { + return _libssh2_error(session, + LIBSSH2_ERROR_FILE, + "Unable to extract public key " + "from private key file: " + "Wrong passphrase or invalid/unrecognized " + "private key file format"); + } + + return 0; } #ifdef HAVE_OPAQUE_STRUCTS @@ -1089,7 +2961,7 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, pktype = pk->type; #endif - switch (pktype) { + switch(pktype) { case EVP_PKEY_RSA : st = gen_publickey_from_rsa_evp( session, method, method_len, pubkeydata, pubkeydata_len, pk); @@ -1102,6 +2974,13 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, break; #endif /* LIBSSH_DSA */ +#if LIBSSH2_ECDSA + case EVP_PKEY_EC : + st = gen_publickey_from_ec_evp( + session, method, method_len, pubkeydata, pubkeydata_len, pk); + break; +#endif + default : st = _libssh2_error(session, LIBSSH2_ERROR_FILE, @@ -1115,6 +2994,129 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, return st; } +static int +_libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session, + void **key_ctx, + const char *key_type, + unsigned char **method, + size_t *method_len, + unsigned char **pubkeydata, + size_t *pubkeydata_len, + const char *privatekeydata, + size_t privatekeydata_len, + unsigned const char *passphrase) +{ + int rc; + unsigned char *buf = NULL; + struct string_buf *decrypted = NULL; + + if(key_ctx != NULL) + *key_ctx = NULL; + + if(session == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Session is required"); + return -1; + } + + if(key_type != NULL && (strlen(key_type) > 11 || strlen(key_type) < 7)) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "type is invalid"); + return -1; + } + + _libssh2_init_if_needed(); + + rc = _libssh2_openssh_pem_parse_memory(session, passphrase, + privatekeydata, + privatekeydata_len, &decrypted); + + if(rc) { + return rc; + } + + /* We have a new key file, now try and parse it using supported types */ + rc = _libssh2_get_string(decrypted, &buf, NULL); + + if(rc != 0 || buf == NULL) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Public key type in decrypted key data not found"); + return -1; + } + + rc = -1; + +#if LIBSSH2_ED25519 + if(strcmp("ssh-ed25519", (const char *)buf) == 0) { + if(key_type == NULL || strcmp("ssh-ed25519", key_type) == 0) { + rc = gen_publickey_from_ed25519_openssh_priv_data(session, + decrypted, + method, + method_len, + pubkeydata, + pubkeydata_len, + (libssh2_ed25519_ctx**)key_ctx); + } + } +#endif +#if LIBSSH2_RSA + if(strcmp("ssh-rsa", (const char *)buf) == 0) { + if(key_type == NULL || strcmp("ssh-rsa", key_type) == 0) { + rc = gen_publickey_from_rsa_openssh_priv_data(session, decrypted, + method, method_len, + pubkeydata, + pubkeydata_len, + (libssh2_rsa_ctx**)key_ctx); + } + } +#endif +#if LIBSSH2_DSA + if(strcmp("ssh-dss", (const char *)buf) == 0) { + if(key_type == NULL || strcmp("ssh-dss", key_type) == 0) { + rc = gen_publickey_from_dsa_openssh_priv_data(session, decrypted, + method, method_len, + pubkeydata, + pubkeydata_len, + (libssh2_dsa_ctx**)key_ctx); + } + } +#endif +#if LIBSSH2_ECDSA +{ + libssh2_curve_type type; + + if(_libssh2_ecdsa_curve_type_from_name((const char *)buf, &type) == 0) { + if(key_type == NULL || strcmp("ssh-ecdsa", key_type) == 0) { + rc = gen_publickey_from_ecdsa_openssh_priv_data(session, type, + decrypted, + method, method_len, + pubkeydata, + pubkeydata_len, + (libssh2_ecdsa_ctx**)key_ctx); + } + } +} +#endif + + if(decrypted) + _libssh2_string_buf_free(session, decrypted); + + return rc; +} + +int +read_openssh_private_key_from_memory(void **key_ctx, LIBSSH2_SESSION *session, + const char *key_type, + const char *filedata, + size_t filedata_len, + unsigned const char *passphrase) +{ + return _libssh2_pub_priv_openssh_keyfilememory(session, key_ctx, key_type, + NULL, NULL, NULL, NULL, + filedata, filedata_len, + passphrase); +} + int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, unsigned char **method, @@ -1135,28 +3137,34 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, "Computing public key from private key."); bp = BIO_new_mem_buf((char *)privatekeydata, privatekeydata_len); - if (!bp) { + if(!bp) { return -1; } - if (!EVP_get_cipherbyname("des")) { - /* If this cipher isn't loaded it's a pretty good indication that none - * are. I have *NO DOUBT* that there's a better way to deal with this - * ($#&%#$(%$#( Someone buy me an OpenSSL manual and I'll read up on - * it. - */ - OpenSSL_add_all_ciphers(); - } + BIO_reset(bp); - pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void*)passphrase); + pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase); BIO_free(bp); - if (pk == NULL) { - return _libssh2_error(session, - LIBSSH2_ERROR_FILE, - "Unable to extract public key " - "from private key file: " - "Wrong passphrase or invalid/unrecognized " - "private key file format"); + if(pk == NULL) { + /* Try OpenSSH format */ + st = _libssh2_pub_priv_openssh_keyfilememory(session, NULL, NULL, + method, + method_len, + pubkeydata, + pubkeydata_len, + privatekeydata, + privatekeydata_len, + (unsigned const char *)passphrase); + if(st != 0) { + return _libssh2_error(session, + LIBSSH2_ERROR_FILE, + "Unable to extract public key " + "from private key file: " + "Wrong passphrase or invalid/unrecognized " + "private key file format"); + } + + return 0; } #ifdef HAVE_OPAQUE_STRUCTS @@ -1165,7 +3173,7 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, pktype = pk->type; #endif - switch (pktype) { + switch(pktype) { case EVP_PKEY_RSA : st = gen_publickey_from_rsa_evp(session, method, method_len, pubkeydata, pubkeydata_len, pk); @@ -1176,6 +3184,12 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, pubkeydata, pubkeydata_len, pk); break; #endif /* LIBSSH_DSA */ +#if LIBSSH2_ECDSA + case EVP_PKEY_EC : + st = gen_publickey_from_ec_evp(session, method, method_len, + pubkeydata, pubkeydata_len, pk); + break; +#endif /* LIBSSH2_ECDSA */ default : st = _libssh2_error(session, LIBSSH2_ERROR_FILE, @@ -1189,4 +3203,38 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, return st; } +void +_libssh2_dh_init(_libssh2_dh_ctx *dhctx) +{ + *dhctx = BN_new(); /* Random from client */ +} + +int +_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, + _libssh2_bn *g, _libssh2_bn *p, int group_order, + _libssh2_bn_ctx *bnctx) +{ + /* Generate x and e */ + BN_rand(*dhctx, group_order * 8 - 1, 0, -1); + BN_mod_exp(public, g, *dhctx, p, bnctx); + return 0; +} + +int +_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p, + _libssh2_bn_ctx *bnctx) +{ + /* Compute the shared secret */ + BN_mod_exp(secret, f, *dhctx, p, bnctx); + return 0; +} + +void +_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx) +{ + BN_clear_free(*dhctx); + *dhctx = NULL; +} + #endif /* LIBSSH2_OPENSSL */ diff --git a/libssh2/src/openssl.h b/libssh2/src/openssl.h index 3ca71fa8a..15518e0a6 100644 --- a/libssh2/src/openssl.h +++ b/libssh2/src/openssl.h @@ -40,7 +40,9 @@ #include #include #include +#ifndef OPENSSL_NO_ENGINE #include +#endif #ifndef OPENSSL_NO_DSA #include #endif @@ -70,6 +72,20 @@ # define LIBSSH2_DSA 1 #endif +#ifdef OPENSSL_NO_ECDSA +# define LIBSSH2_ECDSA 0 +#else +# define LIBSSH2_ECDSA 1 +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10101000L && \ +!defined(LIBRESSL_VERSION_NUMBER) +# define LIBSSH2_ED25519 1 +#else +# define LIBSSH2_ED25519 0 +#endif + + #ifdef OPENSSL_NO_MD5 # define LIBSSH2_MD5 0 #else @@ -117,6 +133,8 @@ # define LIBSSH2_3DES 1 #endif +#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) + #define _libssh2_random(buf, len) RAND_bytes ((buf), (len)) #define libssh2_prepare_iovec(vec, len) /* Empty. */ @@ -160,13 +178,62 @@ int _libssh2_sha256_init(libssh2_sha256_ctx *ctx); EVP_MD_CTX_free(ctx); \ } while(0) #else -#define libssh2_sha256_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) +#define libssh2_sha256_update(ctx, data, len) \ + EVP_DigestUpdate(&(ctx), data, len) #define libssh2_sha256_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) #endif int _libssh2_sha256(const unsigned char *message, unsigned long len, unsigned char *out); #define libssh2_sha256(x,y,z) _libssh2_sha256(x,y,z) +#ifdef HAVE_OPAQUE_STRUCTS +#define libssh2_sha384_ctx EVP_MD_CTX * +#else +#define libssh2_sha384_ctx EVP_MD_CTX +#endif + +/* returns 0 in case of failure */ +int _libssh2_sha384_init(libssh2_sha384_ctx *ctx); +#define libssh2_sha384_init(x) _libssh2_sha384_init(x) +#ifdef HAVE_OPAQUE_STRUCTS +#define libssh2_sha384_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) +#define libssh2_sha384_final(ctx, out) do { \ + EVP_DigestFinal(ctx, out, NULL); \ + EVP_MD_CTX_free(ctx); \ + } while(0) +#else +#define libssh2_sha384_update(ctx, data, len) \ + EVP_DigestUpdate(&(ctx), data, len) +#define libssh2_sha384_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) +#endif +int _libssh2_sha384(const unsigned char *message, unsigned long len, + unsigned char *out); +#define libssh2_sha384(x,y,z) _libssh2_sha384(x,y,z) + +#ifdef HAVE_OPAQUE_STRUCTS +#define libssh2_sha512_ctx EVP_MD_CTX * +#else +#define libssh2_sha512_ctx EVP_MD_CTX +#endif + +/* returns 0 in case of failure */ +int _libssh2_sha512_init(libssh2_sha512_ctx *ctx); +#define libssh2_sha512_init(x) _libssh2_sha512_init(x) +#ifdef HAVE_OPAQUE_STRUCTS +#define libssh2_sha512_update(ctx, data, len) EVP_DigestUpdate(ctx, data, len) +#define libssh2_sha512_final(ctx, out) do { \ + EVP_DigestFinal(ctx, out, NULL); \ + EVP_MD_CTX_free(ctx); \ + } while(0) +#else +#define libssh2_sha512_update(ctx, data, len) \ + EVP_DigestUpdate(&(ctx), data, len) +#define libssh2_sha512_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) +#endif +int _libssh2_sha512(const unsigned char *message, unsigned long len, + unsigned char *out); +#define libssh2_sha512(x,y,z) _libssh2_sha512(x,y,z) + #ifdef HAVE_OPAQUE_STRUCTS #define libssh2_md5_ctx EVP_MD_CTX * #else @@ -226,12 +293,10 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx); #define libssh2_hmac_cleanup(ctx) HMAC_cleanup(ctx) #endif -#define libssh2_crypto_init() \ - OpenSSL_add_all_algorithms(); \ - ENGINE_load_builtin_engines(); \ - ENGINE_register_all_complete() - -#define libssh2_crypto_exit() +extern void _libssh2_openssl_crypto_init(void); +extern void _libssh2_openssl_crypto_exit(void); +#define libssh2_crypto_init() _libssh2_openssl_crypto_init() +#define libssh2_crypto_exit() _libssh2_openssl_crypto_exit() #define libssh2_rsa_ctx RSA @@ -239,9 +304,46 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx); #define libssh2_dsa_ctx DSA - #define _libssh2_dsa_free(dsactx) DSA_free(dsactx) +#ifdef LIBSSH2_ECDSA +#define libssh2_ecdsa_ctx EC_KEY +#define _libssh2_ecdsa_free(ecdsactx) EC_KEY_free(ecdsactx) +#define _libssh2_ec_key EC_KEY + +typedef enum { + LIBSSH2_EC_CURVE_NISTP256 = NID_X9_62_prime256v1, + LIBSSH2_EC_CURVE_NISTP384 = NID_secp384r1, + LIBSSH2_EC_CURVE_NISTP521 = NID_secp521r1 +} +libssh2_curve_type; +#else +#define _libssh2_ec_key void +#endif /* LIBSSH2_ECDSA */ + +#ifdef LIBSSH2_ED25519 + +typedef struct { + EVP_PKEY *public_key; + EVP_PKEY *private_key; +} libssh2_curve25519_keys; + +#define libssh2_ed25519_ctx libssh2_curve25519_keys +#define libssh2_x25519_ctx libssh2_curve25519_keys + +#define _libssh2_ed25519_new_ctx() calloc(1, sizeof(libssh2_ed25519_ctx)) +#define _libssh2_ed25519_free(ctx) do { \ + if(ctx) { \ + if(ctx->public_key) EVP_PKEY_free(ctx->public_key); \ + if(ctx->private_key) EVP_PKEY_free(ctx->private_key); \ + free(ctx); \ + } \ +} while(0) + +#define _libssh2_x25519_free(ctx) _libssh2_ed25519_free(ctx) + +#endif /* ED25519 */ + #define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void) #ifdef HAVE_OPAQUE_STRUCTS #define _libssh2_cipher_ctx EVP_CIPHER_CTX * @@ -267,7 +369,7 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx); #define _libssh2_cipher_3des EVP_des_ede3_cbc #ifdef HAVE_OPAQUE_STRUCTS -#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_reset(*(ctx)) +#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_free(*(ctx)) #else #define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx) #endif @@ -278,8 +380,6 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx); #define _libssh2_bn_ctx_free(bnctx) BN_CTX_free(bnctx) #define _libssh2_bn_init() BN_new() #define _libssh2_bn_init_from_bin() _libssh2_bn_init() -#define _libssh2_bn_rand(bn, bits, top, bottom) BN_rand(bn, bits, top, bottom) -#define _libssh2_bn_mod_exp(r, a, p, m, ctx) BN_mod_exp(r, a, p, m, ctx) #define _libssh2_bn_set_word(bn, val) BN_set_word(bn, val) #define _libssh2_bn_from_bin(bn, len, val) BN_bin2bn(val, len, bn) #define _libssh2_bn_to_bin(bn, val) BN_bn2bin(bn, val) @@ -287,7 +387,23 @@ int _libssh2_md5_init(libssh2_md5_ctx *ctx); #define _libssh2_bn_bits(bn) BN_num_bits(bn) #define _libssh2_bn_free(bn) BN_clear_free(bn) +#define _libssh2_dh_ctx BIGNUM * +#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx) +#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \ + _libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) +#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \ + _libssh2_dh_secret(dhctx, secret, f, p, bnctx) +#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx) +extern void _libssh2_dh_init(_libssh2_dh_ctx *dhctx); +extern int _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, + _libssh2_bn *g, _libssh2_bn *p, + int group_order, + _libssh2_bn_ctx *bnctx); +extern int _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p, + _libssh2_bn_ctx *bnctx); +extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx); + const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void); const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void); const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void); - diff --git a/libssh2/src/os400qc3.c b/libssh2/src/os400qc3.c deleted file mode 100644 index f8e46aba9..000000000 --- a/libssh2/src/os400qc3.c +++ /dev/null @@ -1,2513 +0,0 @@ -/* - * Copyright (C) 2015 Patrick Monnerat, D+H - * All rights reserved. - * - * Redistribution and use in source and binary forms, - * with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * Neither the name of the copyright holder nor the names - * of any other contributors may be used to endorse or - * promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - */ - -#include "libssh2_priv.h" - -#ifdef LIBSSH2_OS400QC3 /* compile only if we build with OS/400 QC3 library */ - -#ifdef HAVE_STDLIB_H -#include -#endif - -#include -#include -#include -#include - -#include - - -#ifdef OS400_DEBUG -/* In debug mode, all system library errors cause an exception. */ -#define set_EC_length(ec, length) ((ec).Bytes_Provided = \ - (ec).Bytes_Available = 0) -#else -#define set_EC_length(ec, length) ((ec).Bytes_Provided = (length)) -#endif - - -/* Ensure va_list operations are not on an array. */ -typedef struct { - va_list list; -} valiststr; - - -typedef int (*loadkeyproc)(LIBSSH2_SESSION *session, - const unsigned char *data, unsigned int datalen, - const unsigned char *passphrase, void *loadkeydata); - -/* Public key extraction data. */ -typedef struct { - const char * method; - const unsigned char * data; - unsigned int length; -} loadpubkeydata; - - -/* Support for ASN.1 elements. */ - -typedef struct { - char * header; /* Pointer to header byte. */ - char * beg; /* Pointer to element data. */ - char * end; /* Pointer to 1st byte after element. */ - unsigned char class; /* ASN.1 element class. */ - unsigned char tag; /* ASN.1 element tag. */ - unsigned char constructed; /* Element is constructed. */ -} asn1Element; - -#define ASN1_INTEGER 2 -#define ASN1_BIT_STRING 3 -#define ASN1_OCTET_STRING 4 -#define ASN1_NULL 5 -#define ASN1_OBJ_ID 6 -#define ASN1_SEQ 16 - -#define ASN1_CONSTRUCTED 0x20 - -/* rsaEncryption OID: 1.2.840.113549.1.1.1 */ -static unsigned char OID_rsaEncryption[] = - {9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 1, 1, 1}; -static int sshrsapubkey(LIBSSH2_SESSION *session, char **sshpubkey, - asn1Element *params, asn1Element *key, - const char *method); - -#if LIBSSH2_DSA != 0 -/* dsaEncryption OID: 1.2.840.10040.4.1 */ -static unsigned char OID_dsaEncryption[] = - {7, 40 + 2, 0x86, 0x48, 0xCE, 0x38, 4, 1}; -static int sshdsapubkey(LIBSSH2_SESSION *session, char **sshpubkey, - asn1Element *params, asn1Element *key, - const char *method); -#endif - - -/* PKCS#5 support. */ - -typedef struct pkcs5params pkcs5params; -struct pkcs5params { - int cipher; /* Encryption cipher. */ - int blocksize; /* Cipher block size. */ - char mode; /* Block encryption mode. */ - char padopt; /* Pad option. */ - char padchar; /* Pad character. */ - int (*kdf)(LIBSSH2_SESSION *session, char **dk, - const unsigned char * passphrase, pkcs5params *pkcs5); - int hash; /* KDF hash algorithm. */ - size_t hashlen; /* KDF hash digest length. */ - char * salt; /* Salt. */ - size_t saltlen; /* Salt length. */ - char * iv; /* Initialization vector. */ - size_t ivlen; /* Initialization vector length. */ - int itercount; /* KDF iteration count. */ - int dklen; /* Derived key length (#bytes). */ - int effkeysize; /* RC2 effective key size (#bits) or 0. */ -}; - -typedef struct pkcs5algo pkcs5algo; -struct pkcs5algo { - const unsigned char * oid; - int (*parse)(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param); - int cipher; /* Encryption cipher. */ - size_t blocksize; /* Cipher block size. */ - char mode; /* Block encryption mode. */ - char padopt; /* Pad option. */ - char padchar; /* Pad character. */ - size_t keylen; /* Key length (#bytes). */ - int hash; /* Hash algorithm. */ - size_t hashlen; /* Hash digest length. */ - size_t saltlen; /* Salt length. */ - size_t ivlen; /* Initialisation vector length. */ - int effkeysize; /* RC2 effective key size (#bits) or 0. */ -}; - -/* id-PBES2 OID: 1.2.840.113549.1.5.13 */ -static const unsigned char OID_id_PBES2[] = { - 9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0D -}; -static int parse_pbes2(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param); -static const pkcs5algo PBES2 = { - OID_id_PBES2, parse_pbes2, 0, 0, '\0', '\0', '\0', 0, - 0, 0, 0, 0, 0 -}; - -/* id-PBKDF2 OID: 1.2.840.113549.1.5.12 */ -static const unsigned char OID_id_PBKDF2[] = { - 9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C -}; -static int parse_pbkdf2(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param); -static const pkcs5algo PBKDF2 = { - OID_id_PBKDF2, parse_pbkdf2, 0, 0, '\0', '\0', '\0', - SHA_DIGEST_LENGTH, Qc3_SHA1, SHA_DIGEST_LENGTH, 8, 8, 0 -}; - -/* id-hmacWithSHA1 OID: 1.2.840.113549.2.7 */ -static const unsigned char OID_id_hmacWithSHA1[] = { - 8, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x07 -}; -static int parse_hmacWithSHA1(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param); -static const pkcs5algo hmacWithSHA1 = { - OID_id_hmacWithSHA1, parse_hmacWithSHA1, 0, 0, '\0', '\0', '\0', - SHA_DIGEST_LENGTH, Qc3_SHA1, SHA_DIGEST_LENGTH, 8, 8, 0 -}; - -/* desCBC OID: 1.3.14.3.2.7 */ -static const unsigned char OID_desCBC[] = {5, 40 + 3, 0x0E, 0x03, 0x02, 0x07}; -static int parse_iv(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param); -static const pkcs5algo desCBC = { - OID_desCBC, parse_iv, Qc3_DES, 8, Qc3_CBC, Qc3_Pad_Counter, - '\0', 8, 0, 0, 8, 8, 0 -}; - -/* des-EDE3-CBC OID: 1.2.840.113549.3.7 */ -static const unsigned char OID_des_EDE3_CBC[] = { - 8, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07 -}; -static const pkcs5algo des_EDE3_CBC = { - OID_des_EDE3_CBC, parse_iv, Qc3_TDES, 8, Qc3_CBC, Qc3_Pad_Counter, - '\0', 24, 0, 0, 8, 8, 0 -}; - -/* rc2CBC OID: 1.2.840.113549.3.2 */ -static const unsigned char OID_rc2CBC[] = { - 8, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x02 -}; -static int parse_rc2(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param); -static const pkcs5algo rc2CBC = { - OID_rc2CBC, parse_rc2, Qc3_RC2, 8, Qc3_CBC, Qc3_Pad_Counter, - '\0', 0, 0, 0, 8, 0, 32 -}; - -/* pbeWithMD5AndDES-CBC OID: 1.2.840.113549.1.5.3 */ -static const unsigned char OID_pbeWithMD5AndDES_CBC[] = { - 9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x03 -}; -static int parse_pbes1(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param); -static const pkcs5algo pbeWithMD5AndDES_CBC = { - OID_pbeWithMD5AndDES_CBC, parse_pbes1, Qc3_DES, 8, Qc3_CBC, - Qc3_Pad_Counter, '\0', 8, Qc3_MD5, MD5_DIGEST_LENGTH, 8, 0, 0 -}; - -/* pbeWithMD5AndRC2-CBC OID: 1.2.840.113549.1.5.6 */ -static const unsigned char OID_pbeWithMD5AndRC2_CBC[] = { - 9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x06 -}; -static const pkcs5algo pbeWithMD5AndRC2_CBC = { - OID_pbeWithMD5AndRC2_CBC, parse_pbes1, Qc3_RC2, 8, Qc3_CBC, - Qc3_Pad_Counter, '\0', 0, Qc3_MD5, MD5_DIGEST_LENGTH, 8, 0, 64 -}; - -/* pbeWithSHA1AndDES-CBC OID: 1.2.840.113549.1.5.10 */ -static const unsigned char OID_pbeWithSHA1AndDES_CBC[] = { - 9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0A -}; -static const pkcs5algo pbeWithSHA1AndDES_CBC = { - OID_pbeWithSHA1AndDES_CBC, parse_pbes1, Qc3_DES, 8, Qc3_CBC, - Qc3_Pad_Counter, '\0', 8, Qc3_SHA1, SHA_DIGEST_LENGTH, 8, 0, 0 -}; - -/* pbeWithSHA1AndRC2-CBC OID: 1.2.840.113549.1.5.11 */ -static const unsigned char OID_pbeWithSHA1AndRC2_CBC[] = { - 9, 40 + 2, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0B -}; -static const pkcs5algo pbeWithSHA1AndRC2_CBC = { - OID_pbeWithSHA1AndRC2_CBC, parse_pbes1, Qc3_RC2, 8, Qc3_CBC, - Qc3_Pad_Counter, '\0', 0, Qc3_SHA1, SHA_DIGEST_LENGTH, 8, 0, 64 -}; - -/* rc5-CBC-PAD OID: 1.2.840.113549.3.9: RC5 not implemented in Qc3. */ -/* pbeWithMD2AndDES-CBC OID: 1.2.840.113549.1.5.1: MD2 not implemented. */ -/* pbeWithMD2AndRC2-CBC OID: 1.2.840.113549.1.5.4: MD2 not implemented. */ - -static const pkcs5algo * pbestable[] = { - &pbeWithMD5AndDES_CBC, - &pbeWithMD5AndRC2_CBC, - &pbeWithSHA1AndDES_CBC, - &pbeWithSHA1AndRC2_CBC, - &PBES2, - NULL -}; - -static const pkcs5algo * pbkdf2table[] = { - &PBKDF2, - NULL -}; - -static const pkcs5algo * pbes2enctable[] = { - &desCBC, - &des_EDE3_CBC, - &rc2CBC, - NULL -}; - -static const pkcs5algo * kdf2prftable[] = { - &hmacWithSHA1, - NULL -}; - - -/* Public key extraction support. */ -static struct { - unsigned char * oid; - int (*sshpubkey)(LIBSSH2_SESSION *session, char **pubkey, - asn1Element *params, asn1Element *key, - const char *method); - const char * method; -} pka[] = { -#if LIBSSH2_RSA != 0 - { OID_rsaEncryption, sshrsapubkey, "ssh-rsa" }, -#endif -#if LIBSSH2_DSA != 0 - { OID_dsaEncryption, sshdsapubkey, "ssh-dss" }, -#endif - { NULL, NULL, NULL } -}; - -/* Define ASCII strings. */ -static const char beginencprivkeyhdr[] = - "-----BEGIN ENCRYPTED PRIVATE KEY-----"; -static const char endencprivkeyhdr[] = "-----END ENCRYPTED PRIVATE KEY-----"; -static const char beginprivkeyhdr[] = "-----BEGIN PRIVATE KEY-----"; -static const char endprivkeyhdr[] = "-----END PRIVATE KEY-----"; -static const char beginrsaprivkeyhdr[] = "-----BEGIN RSA PRIVATE KEY-----"; -static const char endrsaprivkeyhdr[] = "-----END RSA PRIVATE KEY-----"; -static const char fopenrmode[] = "r"; -static const char fopenrbmode[] = "rb"; - - -/* The rest of character literals in this module are in EBCDIC. */ -#pragma convert(37) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static Qc3_Format_KEYD0100_T nulltoken = {""}; - -static int zero = 0; -static int rsaprivate[] = { Qc3_RSA_Private }; -static char anycsp[] = { Qc3_Any_CSP }; -static char binstring[] = { Qc3_Bin_String }; -static char berstring[] = { Qc3_BER_String }; -static char qc3clear[] = { Qc3_Clear }; - -static const Qus_EC_t ecnull = {0}; /* Error causes an exception. */ - -static asn1Element lastbytebitcount = { - (char *) &zero, NULL, (char *) &zero + 1 -}; - - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: ASN.1 support. - * - *******************************************************************/ - -static char * -getASN1Element(asn1Element *elem, char *beg, char *end) -{ - unsigned char b; - unsigned long len; - asn1Element lelem; - - /* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg' - * ending at `end'. - * Returns a pointer in source string after the parsed element, or NULL - * if an error occurs. - */ - - if (beg >= end || !*beg) - return NULL; - - /* Process header byte. */ - elem->header = beg; - b = (unsigned char) *beg++; - elem->constructed = (b & 0x20) != 0; - elem->class = (b >> 6) & 3; - b &= 0x1F; - if (b == 0x1F) - return NULL; /* Long tag values not supported here. */ - elem->tag = b; - - /* Process length. */ - if (beg >= end) - return NULL; - b = (unsigned char) *beg++; - if (!(b & 0x80)) - len = b; - else if (!(b &= 0x7F)) { - /* Unspecified length. Since we have all the data, we can determine the - * effective length by skipping element until an end element is - * found. - */ - if (!elem->constructed) - return NULL; - elem->beg = beg; - while (beg < end && *beg) { - beg = getASN1Element(&lelem, beg, end); - if (!beg) - return NULL; - } - if (beg >= end) - return NULL; - elem->end = beg; - return beg + 1; - } else if (beg + b > end) - return NULL; /* Does not fit in source. */ - else { - /* Get long length. */ - len = 0; - do { - if (len & 0xFF000000L) - return NULL; /* Lengths > 32 bits are not supported. */ - len = (len << 8) | (unsigned char) *beg++; - } while (--b); - } - if ((unsigned long) (end - beg) < len) - return NULL; /* Element data does not fit in source. */ - elem->beg = beg; - elem->end = beg + len; - return elem->end; -} - -static asn1Element * -asn1_new(unsigned int type, unsigned int length) -{ - asn1Element *e; - unsigned int hdrl = 2; - unsigned int i; - unsigned char *buf; - - e = (asn1Element *) malloc(sizeof *e); - - if (e) { - if (length >= 0x80) - for (i = length; i; i >>= 8) - hdrl++; - - buf = (unsigned char *) malloc(hdrl + length); - - if (buf) { - e->header = buf; - e->beg = buf + hdrl; - e->end = e->beg + length; - e->class = (type >> 6) & 0x03; - e->tag = type & 0x1F; - e->constructed = (type >> 5) & 0x01; - e->header[0] = type; - - if (length < 0x80) - e->header[1] = length; - else { - e->header[1] = (hdrl - 2) | 0x80; - do { - e->header[--hdrl] = length; - length >>= 8; - } while (length); - } - } else { - free((char *) e); - e = NULL; - } - } - - return e; -} - -static asn1Element * -asn1_new_from_bytes(const unsigned char *data, unsigned int length) -{ - asn1Element *e; - asn1Element te; - - getASN1Element(&te, - (unsigned char *) data, (unsigned char *) data + length); - e = asn1_new(te.tag, te.end - te.beg); - - if (e) - memcpy(e->header, data, e->end - e->header); - - return e; -} - -static void -asn1delete(asn1Element *e) -{ - if (e) { - if (e->header) - free((char *) e->header); - free((char *) e); - } -} - -static asn1Element * -asn1uint(_libssh2_bn *bn) -{ - asn1Element *e; - int bits; - int length; - unsigned char * p; - - if (!bn) - return NULL; - - bits = _libssh2_bn_bits(bn); - length = (bits + 8) >> 3; - e = asn1_new(ASN1_INTEGER, length); - - if (e) { - p = e->beg; - if (!(bits & 0x07)) - *p++ = 0; - _libssh2_bn_to_bin(bn, p); - } - - return e; -} - -static asn1Element * -asn1containerv(unsigned int type, valiststr args) -{ - valiststr va; - asn1Element *e; - asn1Element *p; - unsigned char *bp; - unsigned int length = 0; - - memcpy((char *) &va, (char *) &args, sizeof args); - while ((p = va_arg(va.list, asn1Element *))) - length += p->end - p->header; - va_end(va.list); - e = asn1_new(type, length); - if (e) { - bp = e->beg; - while ((p = va_arg(args.list, asn1Element *))) { - memcpy(bp, p->header, p->end - p->header); - bp += p->end - p->header; - } - } - return e; -} - -/* VARARGS1 */ -static asn1Element * -asn1container(unsigned int type, ...) -{ - valiststr va; - asn1Element *e; - - va_start(va.list, type); - e = asn1containerv(type, va); - va_end(va.list); - return e; -} - -static asn1Element * -asn1bytes(unsigned int type, const unsigned char *bytes, unsigned int length) -{ - asn1Element *e; - - e = asn1_new(type, length); - if (e && length) - memcpy(e->beg, bytes, length); - return e; -} - -static asn1Element * -rsapublickey(_libssh2_bn *e, _libssh2_bn *m) -{ - asn1Element *publicexponent; - asn1Element *modulus; - asn1Element *rsapubkey; - - /* Build a PKCS#1 RSAPublicKey. */ - - modulus = asn1uint(m); - publicexponent = asn1uint(e); - rsapubkey = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED, - modulus, publicexponent, NULL); - asn1delete(modulus); - asn1delete(publicexponent); - - if (!modulus || !publicexponent) { - asn1delete(rsapubkey); - rsapubkey = NULL; - } - - return rsapubkey; -} - -static asn1Element * -rsaprivatekey(_libssh2_bn *e, _libssh2_bn *m, _libssh2_bn *d, - _libssh2_bn *p, _libssh2_bn *q, - _libssh2_bn *exp1, _libssh2_bn *exp2, _libssh2_bn *coeff) -{ - asn1Element *version; - asn1Element *modulus; - asn1Element *publicexponent; - asn1Element *privateexponent; - asn1Element *prime1; - asn1Element *prime2; - asn1Element *exponent1; - asn1Element *exponent2; - asn1Element *coefficient; - asn1Element *rsaprivkey; - - /* Build a PKCS#1 RSAPrivateKey. */ - version = asn1bytes(ASN1_INTEGER, "\0", 1); - modulus = asn1uint(m); - publicexponent = asn1uint(e); - privateexponent = asn1uint(d); - prime1 = asn1uint(p); - prime2 = asn1uint(q); - exponent1 = asn1uint(exp1); - exponent2 = asn1uint(exp2); - coefficient = asn1uint(coeff); - rsaprivkey = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED, version, modulus, - publicexponent, privateexponent, prime1, prime2, - exponent1, exponent2, coefficient, NULL); - asn1delete(version); - asn1delete(modulus); - asn1delete(publicexponent); - asn1delete(privateexponent); - asn1delete(prime1); - asn1delete(prime2); - asn1delete(exponent1); - asn1delete(exponent2); - asn1delete(coefficient); - - if (!version || !modulus || !publicexponent || !privateexponent || - !prime1 || !prime2 || !exponent1 || !exponent2 || !coefficient) { - asn1delete(rsaprivkey); - rsaprivkey = NULL; - } - - return rsaprivkey; -} - -static asn1Element * -subjectpublickeyinfo(asn1Element *pubkey, const unsigned char *algo, - asn1Element *parameters) -{ - asn1Element *subjpubkey; - asn1Element *algorithm; - asn1Element *algorithmid; - asn1Element *subjpubkeyinfo; - unsigned int algosize = *algo++; - - algorithm = asn1bytes(ASN1_OBJ_ID, algo, algosize); - algorithmid = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED, - algorithm, parameters, NULL); - subjpubkey = asn1container(ASN1_BIT_STRING, &lastbytebitcount, - pubkey, NULL); - subjpubkeyinfo = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED, - algorithmid, subjpubkey, NULL); - asn1delete(algorithm); - asn1delete(algorithmid); - asn1delete(subjpubkey); - if (!algorithm || !algorithmid || !subjpubkey) { - asn1delete(subjpubkeyinfo); - subjpubkeyinfo = NULL; - } - return subjpubkeyinfo; -} - -static asn1Element * -rsasubjectpublickeyinfo(asn1Element *pubkey) -{ - asn1Element *parameters; - asn1Element *subjpubkeyinfo; - - parameters = asn1bytes(ASN1_NULL, NULL, 0); - subjpubkeyinfo = subjectpublickeyinfo(pubkey, - OID_rsaEncryption, parameters); - asn1delete(parameters); - if (!parameters) { - asn1delete(subjpubkeyinfo); - subjpubkeyinfo = NULL; - } - return subjpubkeyinfo; -} - -static asn1Element * -privatekeyinfo(asn1Element *privkey, const unsigned char *algo, - asn1Element *parameters) -{ - asn1Element *version; - asn1Element *privatekey; - asn1Element *algorithm; - asn1Element *privatekeyalgorithm; - asn1Element *privkeyinfo; - unsigned int algosize = *algo++; - - /* Build a PKCS#8 PrivateKeyInfo. */ - version = asn1bytes(ASN1_INTEGER, "\0", 1); - algorithm = asn1bytes(ASN1_OBJ_ID, algo, algosize); - privatekeyalgorithm = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED, - algorithm, parameters, NULL); - privatekey = asn1container(ASN1_OCTET_STRING, privkey, NULL); - privkeyinfo = asn1container(ASN1_SEQ | ASN1_CONSTRUCTED, version, - privatekeyalgorithm, privatekey, NULL); - asn1delete(version); - asn1delete(algorithm); - asn1delete(privatekeyalgorithm); - if (!version || !algorithm || !privatekeyalgorithm) { - asn1delete(privkeyinfo); - privkeyinfo = NULL; - } - return privkeyinfo; -} - -static asn1Element * -rsaprivatekeyinfo(asn1Element *privkey) -{ - asn1Element *parameters; - asn1Element *privkeyinfo; - - parameters = asn1bytes(ASN1_NULL, NULL, 0); - privkeyinfo = privatekeyinfo(privkey, OID_rsaEncryption, parameters); - asn1delete(parameters); - if (!parameters) { - asn1delete(privkeyinfo); - privkeyinfo = NULL; - } - return privkeyinfo; -} - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: big numbers support. - * - *******************************************************************/ - - -_libssh2_bn * -_libssh2_bn_init(void) -{ - _libssh2_bn *bignum; - - bignum = (_libssh2_bn *) malloc(sizeof *bignum); - if (bignum) { - bignum->bignum = NULL; - bignum->length = 0; - } - - return bignum; -} - -void -_libssh2_bn_free(_libssh2_bn *bn) -{ - if (bn) { - if (bn->bignum) { -#ifdef LIBSSH2_CLEAR_MEMORY - if (bn->length) - memset((char *) bn->bignum, 0, bn->length); -#endif - free(bn->bignum); - } - - free((char *) bn); - } -} - -static int -_libssh2_bn_resize(_libssh2_bn *bn, size_t newlen) -{ - unsigned char *bignum; - - if (!bn) - return -1; - if (newlen == bn->length) - return 0; - - if (!bn->bignum) - bignum = (unsigned char *) malloc(newlen); - else { -#ifdef LIBSSH2_CLEAR_MEMORY - if (newlen < bn->length) - memset((char *) bn->bignum + newlen, 0, bn->length - newlen); -#endif - if (!newlen) { - free((char *) bn->bignum); - bn->bignum = NULL; - bn->length = 0; - return 0; - } - bignum = (unsigned char *) realloc((char *) bn->bignum, newlen); - } - - if (!bignum) - return -1; - - if (newlen > bn->length) - memset((char *) bignum + bn->length, 0, newlen - bn->length); - - bn->bignum = bignum; - bn->length = newlen; - return 0; -} - -unsigned long -_libssh2_bn_bits(_libssh2_bn *bn) -{ - unsigned int i; - unsigned char b; - - if (bn && bn->bignum) { - for (i = bn->length; i--;) - if ((b = bn->bignum[i])) { - i *= 8; - do { - i++; - } while (b >>= 1); - return i; - } - } - - return 0; -} - -int -_libssh2_bn_from_bin(_libssh2_bn *bn, int len, const unsigned char *val) -{ - int i; - - if (!bn || (len && !val)) - return -1; - - for (; len && !*val; len--) - val++; - - if (_libssh2_bn_resize(bn, len)) - return -1; - - for (i = len; i--;) - bn->bignum[i] = *val++; - - return 0; -} - -int -_libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val) -{ - val = htonl(val); - return _libssh2_bn_from_bin(bn, sizeof val, (unsigned char *) &val); -} - -int -_libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val) -{ - int i; - - if (!bn || !val) - return -1; - - for (i = bn->length; i--;) - *val++ = bn->bignum[i]; - - return 0; -} - -static int -_libssh2_bn_from_bn(_libssh2_bn *to, _libssh2_bn *from) -{ - int i; - - if (!to || !from) - return -1; - - if (_libssh2_bn_resize(to, from->length)) - return -1; - - for (i = to->length; i--;) - to->bignum[i] = from->bignum[i]; - - return 0; -} - -void -_libssh2_random(unsigned char *buf, int len) -{ - Qc3GenPRNs(buf, len, - Qc3PRN_TYPE_NORMAL, Qc3PRN_NO_PARITY, (char *) &ecnull); -} - -int -_libssh2_bn_rand(_libssh2_bn *bn, int bits, int top, int bottom) -{ - int len; - int i; - - if (!bn || bits <= 0) - return -1; - len = (bits + 7) >> 3; - if (_libssh2_bn_resize(bn, len)) - return -1; - _libssh2_random(bn->bignum, len); - i = ((bits - 1) & 07) + 1; - bn->bignum[len - 1] &= (1 << i) - 1; - switch (top) { - case 1: - if (bits > 1) - if (i > 1) - bn->bignum[len - 1] |= 1 << (i - 2); - else - bn->bignum[len - 2] |= 0x80; - /* Fall into. */ - case 0: - bn->bignum[len - 1] |= 1 << (i - 1); - break; - } - if (bottom) - *bn->bignum |= 0x01; - return 0; -} - -static int -_libssh2_bn_lshift(_libssh2_bn *bn) -{ - int i; - int c = 0; - - if (!bn) - return -1; - - if (_libssh2_bn_resize(bn, (_libssh2_bn_bits(bn) + 8) >> 3)) - return -1; - - for (i = 0; i < bn->length; i++) { - if (bn->bignum[i] & 0x80) - c |= 0x02; - bn->bignum[i] = (bn->bignum[i] << 1) | (c & 0x01); - c >>= 1; - } - - return 0; -} - -static int -_libssh2_bn_rshift(_libssh2_bn *bn) -{ - int i; - int c = 0; - - if (!bn) - return -1; - - for (i = bn->length; i--;) { - if (bn->bignum[i] & 0x01) - c |= 0x100; - bn->bignum[i] = (bn->bignum[i] >> 1) | (c & 0x80); - c >>= 1; - } - - if (_libssh2_bn_resize(bn, (_libssh2_bn_bits(bn) + 7) >> 3)) - return -1; - - return 0; -} - -static void -_libssh2_bn_swap(_libssh2_bn *bn1, _libssh2_bn *bn2) -{ - _libssh2_bn t = *bn1; - - *bn1 = *bn2; - *bn2 = t; -} - -static int -_libssh2_bn_subtract(_libssh2_bn *d, _libssh2_bn *bn1, _libssh2_bn *bn2) -{ - int c = 0; - int i; - - if (bn1->length < bn2->length) - return -1; - - if (_libssh2_bn_resize(d, bn1->length)) - return -1; - - for (i = 0; i < bn2->length; i++) { - c += (int) bn1->bignum[i] - (int) bn2->bignum[i]; - d->bignum[i] = c; - c = c < 0? -1: 0; - } - - for (; c && i < bn1->length; i++) { - c += (int) bn1->bignum[i]; - d->bignum[i] = c; - c = c < 0? -1: 0; - } - - if (_libssh2_bn_resize(d, (_libssh2_bn_bits(d) + 7) >> 3)) - return -1; - - return c; -} - -int -_libssh2_os400qc3_bn_mod_exp(_libssh2_bn *r, _libssh2_bn *a, _libssh2_bn *p, - _libssh2_bn *m) -{ - _libssh2_bn *mp; - _libssh2_bn *rp; - asn1Element *rsapubkey; - asn1Element *subjpubkeyinfo; - unsigned char *av; - unsigned char *rv; - char *keydbuf; - Qc3_Format_ALGD0400_T algd; - Qc3_Format_KEYD0200_T *keyd; - Qus_EC_t errcode; - int sc; - int outlen; - int ret = -1; - - /* There is no support for this function in the Qc3 crypto-library. - Since a RSA encryption performs this function, we can emulate it - by creating an RSA public key in ASN.1 SubjectPublicKeyInfo format - from p (exponent) and m (modulus) and encrypt a with this key. The - encryption output is the function result. - Problem: the Qc3EncryptData procedure only succeeds if the data bit - count is less than the modulus bit count. To satisfy this condition, - we multiply the modulus by a power of two and adjust the result - accordingly. */ - - if (!r || !a || !p) - return ret; - - mp = _libssh2_bn_init(); - if (!mp) - return ret; - if (_libssh2_bn_from_bn(mp, m)) { - _libssh2_bn_free(mp); - return ret; - } - for (sc = 0; _libssh2_bn_bits(mp) <= 8 * a->length; sc++) - if (_libssh2_bn_lshift(mp)) { - _libssh2_bn_free(mp); - return ret; - } - - rsapubkey = rsapublickey(p, mp); - subjpubkeyinfo = rsasubjectpublickeyinfo(rsapubkey); - asn1delete(rsapubkey); - - if (!rsapubkey || !subjpubkeyinfo) { - asn1delete(rsapubkey); - asn1delete(subjpubkeyinfo); - _libssh2_bn_free(mp); - return ret; - } - - av = (unsigned char *) alloca(a->length); - rv = (unsigned char *) alloca(mp->length); - keydbuf = alloca(sizeof *keyd + - subjpubkeyinfo->end - subjpubkeyinfo->header); - - if (av && rv && keydbuf) { - _libssh2_bn_to_bin(a, av); - algd.Public_Key_Alg = Qc3_RSA; - algd.PKA_Block_Format = Qc3_Zero_Pad; - memset(algd.Reserved, 0, sizeof algd.Reserved); - algd.Signing_Hash_Alg = 0; - keyd = (Qc3_Format_KEYD0200_T *) keydbuf; - keyd->Key_Type = Qc3_RSA_Public; - keyd->Key_String_Len = subjpubkeyinfo->end - subjpubkeyinfo->header; - keyd->Key_Format = Qc3_BER_String; - memset(keyd->Reserved, 0, sizeof keyd->Reserved); - memcpy(keydbuf + sizeof *keyd, subjpubkeyinfo->header, - keyd->Key_String_Len); - set_EC_length(errcode, sizeof errcode); - Qc3EncryptData(av, (int *) &a->length, Qc3_Data, (char *) &algd, - Qc3_Alg_Public_Key, keydbuf, Qc3_Key_Parms, anycsp, - NULL, rv, (int *) &mp->length, &outlen, &errcode); - if (!errcode.Bytes_Available) { - _libssh2_bn_from_bin(r, outlen, rv); - if (!sc) - ret = 0; - else { - rp = _libssh2_bn_init(); - if (rp) { - do { - _libssh2_bn_rshift(mp); - if (!_libssh2_bn_subtract(rp, r, mp)) - _libssh2_bn_swap(r, rp); - } while (--sc); - _libssh2_bn_free(rp); - ret = 0; - } - } - } - } - asn1delete(subjpubkeyinfo); - _libssh2_bn_free(mp); - return ret; -} - - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: crypto context support. - * - *******************************************************************/ - -static _libssh2_os400qc3_crypto_ctx * -libssh2_init_crypto_ctx(_libssh2_os400qc3_crypto_ctx *ctx) -{ - if (!ctx) - ctx = (_libssh2_os400qc3_crypto_ctx *) malloc(sizeof *ctx); - - if (ctx) { - memset((char *) ctx, 0, sizeof *ctx); - ctx->hash.Final_Op_Flag = Qc3_Continue; - } - - return ctx; -} - -static int -null_token(const char *token) -{ - return !memcmp(token, nulltoken.Key_Context_Token, - sizeof nulltoken.Key_Context_Token); -} - -void -_libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x) -{ - if (!x) - return; - if (!null_token(x->hash.Alg_Context_Token)) { - Qc3DestroyAlgorithmContext(x->hash.Alg_Context_Token, (char *) &ecnull); - memset(x->hash.Alg_Context_Token, 0, sizeof x->hash.Alg_Context_Token); - } - if (!null_token(x->key.Key_Context_Token)) { - Qc3DestroyKeyContext(x->key.Key_Context_Token, (char *) &ecnull); - memset(x->key.Key_Context_Token, 0, sizeof x->key.Key_Context_Token); - } - if (x->kek) { - _libssh2_os400qc3_crypto_dtor(x->kek); - free((char *) x->kek); - x->kek = NULL; - } -} - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: hash algorithms support. - * - *******************************************************************/ - -int -libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, unsigned int algorithm) -{ - Qc3_Format_ALGD0500_T algd; - Qus_EC_t errcode; - - if (!x) - return 0; - - memset((char *) x, 0, sizeof *x); - x->Final_Op_Flag = Qc3_Continue; - algd.Hash_Alg = algorithm; - set_EC_length(errcode, sizeof errcode); - Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Hash, - x->Alg_Context_Token, &errcode); - return errcode.Bytes_Available? 0: 1; -} - -void -libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx, - unsigned char *data, int len) -{ - char dummy[64]; - - ctx->Final_Op_Flag = Qc3_Continue; - Qc3CalculateHash((char *) data, &len, Qc3_Data, (char *) ctx, - Qc3_Alg_Token, anycsp, NULL, dummy, (char *) &ecnull); -} - -void -libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx, unsigned char *out) -{ - char data; - - ctx->Final_Op_Flag = Qc3_Final; - Qc3CalculateHash(&data, &zero, Qc3_Data, (char *) ctx, Qc3_Alg_Token, - anycsp, NULL, (char *) out, (char *) &ecnull); - Qc3DestroyAlgorithmContext(ctx->Alg_Context_Token, (char *) &ecnull); - memset(ctx->Alg_Context_Token, 0, sizeof ctx->Alg_Context_Token); -} - -int -libssh2_os400qc3_hash(const unsigned char *message, unsigned long len, - unsigned char *out, unsigned int algo) -{ - Qc3_Format_ALGD0100_T ctx; - - if (!libssh2_os400qc3_hash_init(&ctx, algo)) - return 1; - - libssh2_os400qc3_hash_update(&ctx, (unsigned char *) message, len); - libssh2_os400qc3_hash_final(&ctx, out); - return 0; -} - -void -libssh2_os400qc3_hmac_init(_libssh2_os400qc3_crypto_ctx *ctx, - int algo, size_t minkeylen, void *key, int keylen) -{ - if (keylen < minkeylen) { - char *lkey = alloca(minkeylen); - - /* Pad key with zeroes if too short. */ - if (!lkey) - return; - memcpy(lkey, (char *) key, keylen); - memset(lkey + keylen, 0, minkeylen - keylen); - key = (void *) lkey; - keylen = minkeylen; - } - libssh2_os400qc3_hash_init(&ctx->hash, algo); - Qc3CreateKeyContext((char *) key, &keylen, binstring, &algo, qc3clear, - NULL, NULL, ctx->key.Key_Context_Token, - (char *) &ecnull); -} - -void -libssh2_os400qc3_hmac_update(_libssh2_os400qc3_crypto_ctx *ctx, - unsigned char *data, int len) -{ - char dummy[64]; - - ctx->hash.Final_Op_Flag = Qc3_Continue; - Qc3CalculateHMAC((char *) data, &len, Qc3_Data, (char *) &ctx->hash, - Qc3_Alg_Token, ctx->key.Key_Context_Token, Qc3_Key_Token, - anycsp, NULL, dummy, (char *) &ecnull); -} - -void -libssh2_os400qc3_hmac_final(_libssh2_os400qc3_crypto_ctx *ctx, - unsigned char *out) -{ - char data; - - ctx->hash.Final_Op_Flag = Qc3_Final; - Qc3CalculateHMAC((char *) data, &zero, Qc3_Data, (char *) &ctx->hash, - Qc3_Alg_Token, ctx->key.Key_Context_Token, Qc3_Key_Token, - anycsp, NULL, (char *) out, (char *) &ecnull); -} - - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: cipher algorithms support. - * - *******************************************************************/ - -int -_libssh2_cipher_init(_libssh2_cipher_ctx *h, _libssh2_cipher_type(algo), - unsigned char *iv, unsigned char *secret, int encrypt) -{ - Qc3_Format_ALGD0200_T algd; - Qus_EC_t errcode; - - (void) encrypt; - - if (!h) - return -1; - - libssh2_init_crypto_ctx(h); - algd.Block_Cipher_Alg = algo.algo; - algd.Block_Length = algo.size; - algd.Mode = algo.mode; - algd.Pad_Option = Qc3_No_Pad; - algd.Pad_Character = 0; - algd.Reserved = 0; - algd.MAC_Length = 0; - algd.Effective_Key_Size = 0; - memset(algd.Init_Vector, 0 , sizeof algd.Init_Vector); - if (algo.mode != Qc3_ECB && algo.size) - memcpy(algd.Init_Vector, iv, algo.size); - set_EC_length(errcode, sizeof errcode); - Qc3CreateAlgorithmContext((char *) &algd, algo.fmt, - h->hash.Alg_Context_Token, &errcode); - if (errcode.Bytes_Available) - return -1; - Qc3CreateKeyContext((char *) secret, &algo.keylen, binstring, - &algo.algo, qc3clear, NULL, NULL, - h->key.Key_Context_Token, (char *) &errcode); - if (errcode.Bytes_Available) { - _libssh2_os400qc3_crypto_dtor(h); - return -1; - } - - return 0; -} - -int -_libssh2_cipher_crypt(_libssh2_cipher_ctx *ctx, - _libssh2_cipher_type(algo), - int encrypt, unsigned char *block, size_t blocksize) -{ - Qus_EC_t errcode; - int outlen; - int blksize = blocksize; - - (void) algo; - - set_EC_length(errcode, sizeof errcode); - if (encrypt) - Qc3EncryptData((char *) block, &blksize, Qc3_Data, - ctx->hash.Alg_Context_Token, Qc3_Alg_Token, - ctx->key.Key_Context_Token, Qc3_Key_Token, anycsp, NULL, - (char *) block, &blksize, &outlen, (char *) &errcode); - else - Qc3DecryptData((char *) block, &blksize, - ctx->hash.Alg_Context_Token, Qc3_Alg_Token, - ctx->key.Key_Context_Token, Qc3_Key_Token, anycsp, NULL, - (char *) block, &blksize, &outlen, (char *) &errcode); - - return errcode.Bytes_Available? -1: 0; -} - - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: RSA support. - * - *******************************************************************/ - -int -_libssh2_rsa_new(libssh2_rsa_ctx **rsa, - const unsigned char *edata, unsigned long elen, - const unsigned char *ndata, unsigned long nlen, - const unsigned char *ddata, unsigned long dlen, - const unsigned char *pdata, unsigned long plen, - const unsigned char *qdata, unsigned long qlen, - const unsigned char *e1data, unsigned long e1len, - const unsigned char *e2data, unsigned long e2len, - const unsigned char *coeffdata, unsigned long coefflen) -{ - libssh2_rsa_ctx *ctx; - _libssh2_bn *e = _libssh2_bn_init_from_bin(); - _libssh2_bn *n = _libssh2_bn_init_from_bin(); - _libssh2_bn *d = NULL; - _libssh2_bn *p = NULL; - _libssh2_bn *q = NULL; - _libssh2_bn *e1 = NULL; - _libssh2_bn *e2 = NULL; - _libssh2_bn *coeff = NULL; - asn1Element *key = NULL; - asn1Element *structkey = NULL; - Qc3_Format_ALGD0400_T algd; - Qus_EC_t errcode; - int keytype; - int ret = 0; - int i; - - ctx = libssh2_init_crypto_ctx(NULL); - if (!ctx) - ret = -1; - if (!ret) { - _libssh2_bn_from_bin(e, elen, edata); - _libssh2_bn_from_bin(n, nlen, ndata); - if (!e || !n) - ret = -1; - } - if (!ret && ddata) { - /* Private key. */ - d = _libssh2_bn_init_from_bin(); - _libssh2_bn_from_bin(d, dlen, ddata); - p = _libssh2_bn_init_from_bin(); - _libssh2_bn_from_bin(p, plen, pdata); - q = _libssh2_bn_init_from_bin(); - _libssh2_bn_from_bin(q, qlen, qdata); - e1 = _libssh2_bn_init_from_bin(); - _libssh2_bn_from_bin(e1, e1len, e1data); - e2 = _libssh2_bn_init_from_bin(); - _libssh2_bn_from_bin(e2, e2len, e2data); - coeff = _libssh2_bn_init_from_bin(); - _libssh2_bn_from_bin(coeff, coefflen, coeffdata); - if (!d || !p || !q ||!e1 || !e2 || !coeff) - ret = -1; - - if (!ret) { - /* Build a PKCS#8 private key. */ - key = rsaprivatekey(e, n, d, p, q, e1, e2, coeff); - structkey = rsaprivatekeyinfo(key); - } - keytype = Qc3_RSA_Private; - } else if (!ret) { - key = rsapublickey(e, n); - structkey = rsasubjectpublickeyinfo(key); - keytype = Qc3_RSA_Public; - } - if (!key || !structkey) - ret = -1; - - set_EC_length(errcode, sizeof errcode); - - if (!ret) { - /* Create the algorithm context. */ - algd.Public_Key_Alg = Qc3_RSA; - algd.PKA_Block_Format = Qc3_PKCS1_01; - memset(algd.Reserved, 0, sizeof algd.Reserved); - algd.Signing_Hash_Alg = Qc3_SHA1; - Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key, - ctx->hash.Alg_Context_Token, &errcode); - if (errcode.Bytes_Available) - ret = -1; - ctx->hash.Final_Op_Flag = Qc3_Continue; - } - - /* Create the key context. */ - if (!ret) { - i = structkey->end - structkey->header; - Qc3CreateKeyContext(structkey->header, &i, berstring, &keytype, - qc3clear, NULL, NULL, ctx->key.Key_Context_Token, - (char *) &errcode); - if (errcode.Bytes_Available) - ret = -1; - } - - _libssh2_bn_free(e); - _libssh2_bn_free(n); - _libssh2_bn_free(d); - _libssh2_bn_free(p); - _libssh2_bn_free(q); - _libssh2_bn_free(e1); - _libssh2_bn_free(e2); - _libssh2_bn_free(coeff); - asn1delete(key); - asn1delete(structkey); - if (ret && ctx) { - _libssh2_rsa_free(ctx); - ctx = NULL; - } - *rsa = ctx; - return ret; -} - - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: PKCS#5 supplement. - * - *******************************************************************/ - -static int -oidcmp(const asn1Element *e, const unsigned char *oid) -{ - int i = e->end - e->beg - *oid++; - - if (*e->header != ASN1_OBJ_ID) - return -2; - if (!i) - i = memcmp(e->beg, oid, oid[-1]); - return i; -} - -static int -asn1getword(asn1Element *e, unsigned long *v) -{ - unsigned long a; - const unsigned char *cp; - - if (*e->header != ASN1_INTEGER) - return -1; - for (cp = e->beg; cp < e->end && !*cp; cp++) - ; - if (e->end - cp > sizeof a) - return -1; - for (a = 0; cp < e->end; cp++) - a = (a << 8) | *cp; - *v = a; - return 0; -} - -static int -pbkdf1(LIBSSH2_SESSION *session, char **dk, const unsigned char * passphrase, - pkcs5params *pkcs5) -{ - int i; - Qc3_Format_ALGD0100_T hctx; - int len = pkcs5->saltlen; - char *data = (char *) pkcs5->salt; - - *dk = NULL; - if (pkcs5->dklen > pkcs5->hashlen) - return -1; - - /* Allocate the derived key buffer. */ - if (!(*dk = LIBSSH2_ALLOC(session, pkcs5->hashlen))) - return -1; - - /* Initial hash. */ - libssh2_os400qc3_hash_init(&hctx, pkcs5->hash); - libssh2_os400qc3_hash_update(&hctx, (unsigned char *) passphrase, - strlen(passphrase)); - hctx.Final_Op_Flag = Qc3_Final; - Qc3CalculateHash((char *) pkcs5->salt, &len, Qc3_Data, (char *) &hctx, - Qc3_Alg_Token, anycsp, NULL, *dk, (char *) &ecnull); - - /* Iterate. */ - len = pkcs5->hashlen; - for (i = 1; i < pkcs5->itercount; i++) - Qc3CalculateHash((char *) *dk, &len, Qc3_Data, (char *) &hctx, - Qc3_Alg_Token, anycsp, NULL, *dk, (char *) &ecnull); - - /* Special stuff for PBES1: split derived key into 8-byte key and 8-byte - initialization vector. */ - pkcs5->dklen = 8; - pkcs5->ivlen = 8; - pkcs5->iv = *dk + 8; - - /* Clean-up and exit. */ - Qc3DestroyAlgorithmContext(hctx.Alg_Context_Token, (char *) &ecnull); - return 0; -} - -static int -pbkdf2(LIBSSH2_SESSION *session, char **dk, const unsigned char * passphrase, - pkcs5params *pkcs5) -{ - size_t i; - size_t k; - int j; - int l; - uint32_t ni; - unsigned long long t; - char *mac; - char *buf; - _libssh2_os400qc3_crypto_ctx hctx; - - *dk = NULL; - t = ((unsigned long long) pkcs5->dklen + pkcs5->hashlen - 1) / - pkcs5->hashlen; - if (t > 0xFFFFFFFF) - return -1; - mac = alloca(pkcs5->hashlen); - if (!mac) - return -1; - - /* Allocate the derived key buffer. */ - l = t; - if (!(buf = LIBSSH2_ALLOC(session, l * pkcs5->hashlen))) - return -1; - *dk = buf; - - /* Create an HMAC context for our computations. */ - libssh2_os400qc3_hmac_init(&hctx, pkcs5->hash, pkcs5->hashlen, - (void *) passphrase, strlen(passphrase)); - - /* Process each hLen-size blocks. */ - for (i = 1; i <= l; i++) { - ni = htonl(i); - libssh2_os400qc3_hmac_update(&hctx, pkcs5->salt, pkcs5->saltlen); - libssh2_os400qc3_hmac_update(&hctx, (char *) &ni, sizeof ni); - libssh2_os400qc3_hmac_final(&hctx, mac); - memcpy(buf, mac, pkcs5->hashlen); - for (j = 1; j < pkcs5->itercount; j++) { - libssh2_os400qc3_hmac_update(&hctx, mac, pkcs5->hashlen); - libssh2_os400qc3_hmac_final(&hctx, mac); - for (k = 0; k < pkcs5->hashlen; k++) - buf[k] ^= mac[k]; - } - buf += pkcs5->hashlen; - } - - /* Computation done. Release HMAC context. */ - _libssh2_os400qc3_crypto_dtor(&hctx); - return 0; -} - -static int -parse_pkcs5_algorithm(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - asn1Element *algid, pkcs5algo **algotable) -{ - asn1Element oid; - asn1Element param; - char *cp; - - cp = getASN1Element(&oid, algid->beg, algid->end); - if (!cp || *oid.header != ASN1_OBJ_ID) - return -1; - param.header = NULL; - if (cp < algid->end) - cp = getASN1Element(¶m, cp, algid->end); - if (cp != algid->end) - return -1; - for (; *algotable; algotable++) - if (!oidcmp(&oid, (*algotable)->oid)) - return (*(*algotable)->parse)(session, pkcs5, *algotable, - param.header? ¶m: NULL); - return -1; -} - -static int -parse_pbes2(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param) -{ - asn1Element keyDerivationFunc; - asn1Element encryptionScheme; - char *cp; - - if (!param || *param->header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - cp = getASN1Element(&keyDerivationFunc, param->beg, param->end); - if (!cp || *keyDerivationFunc.header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - if (getASN1Element(&encryptionScheme, cp, param->end) != param->end || - *encryptionScheme.header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - if (parse_pkcs5_algorithm(session, pkcs5, &encryptionScheme, pbes2enctable)) - return -1; - if (parse_pkcs5_algorithm(session, pkcs5, &keyDerivationFunc, pbkdf2table)) - return -1; - return 0; -} - -static int -parse_pbkdf2(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param) -{ - asn1Element salt; - asn1Element iterationCount; - asn1Element keyLength; - asn1Element prf; - unsigned long itercount; - char *cp; - - if (!param || *param->header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - cp = getASN1Element(&salt, param->beg, param->end); - /* otherSource not supported. */ - if (!cp || *salt.header != ASN1_OCTET_STRING) - return -1; - cp = getASN1Element(&iterationCount, cp, param->end); - if (!cp || *iterationCount.header != ASN1_INTEGER) - return -1; - keyLength.header = prf.header = NULL; - if (cp < param->end) { - cp = getASN1Element(&prf, cp, param->end); - if (!cp) - return -1; - if (*prf.header == ASN1_INTEGER) { - keyLength = prf; - prf.header = NULL; - if (cp < param->end) - cp = getASN1Element(&prf, cp, param->end); - } - if (cp != param->end) - return -1; - } - pkcs5->hash = algo->hash; - pkcs5->hashlen = algo->hashlen; - if (prf.header) { - if (*prf.header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - if (parse_pkcs5_algorithm(session, pkcs5, &prf, kdf2prftable)) - return -1; - } - pkcs5->saltlen = salt.end - salt.beg; - pkcs5->salt = salt.beg; - if (asn1getword(&iterationCount, &itercount) || - !itercount || itercount > 100000) - return -1; - pkcs5->itercount = itercount; - pkcs5->kdf = pbkdf2; - return 0; -} - -static int -parse_hmacWithSHA1(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param) -{ - if (!param || *param->header != ASN1_NULL) - return -1; - pkcs5->hash = algo->hash; - pkcs5->hashlen = algo->hashlen; - return 0; -} - -static int -parse_iv(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param) -{ - if (!param || *param->header != ASN1_OCTET_STRING || - param->end - param->beg != algo->ivlen) - return -1; - pkcs5->cipher = algo->cipher; - pkcs5->blocksize = algo->blocksize; - pkcs5->mode = algo->mode; - pkcs5->padopt = algo->padopt; - pkcs5->padchar = algo->padchar; - pkcs5->dklen = algo->keylen; - pkcs5->ivlen = algo->ivlen; - pkcs5->iv = param->beg; - return 0; -} - -static int -parse_rc2(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param) -{ - asn1Element iv; - unsigned long effkeysize; - char *cp; - - if (!param || *param->header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - cp = getASN1Element(&iv, param->beg, param->end); - if (!cp) - return -1; - effkeysize = algo->effkeysize; - if (*iv.header == ASN1_INTEGER) { - if (asn1getword(&iv, &effkeysize) || effkeysize > 1024) - return -1; - - cp = getASN1Element(&iv, cp, param->end); - if (effkeysize < 256) - switch (effkeysize) { - case 160: - effkeysize = 40; - case 120: - effkeysize = 64; - case 58: - effkeysize = 128; - break; - default: - return -1; - } - } - if (effkeysize > 1024 || cp != param->end || - *iv.header != ASN1_OCTET_STRING || iv.end - iv.beg != algo->ivlen) - return -1; - pkcs5->cipher = algo->cipher; - pkcs5->blocksize = algo->blocksize; - pkcs5->mode = algo->mode; - pkcs5->padopt = algo->padopt; - pkcs5->padchar = algo->padchar; - pkcs5->ivlen = algo->ivlen; - pkcs5->iv = iv.beg; - pkcs5->effkeysize = effkeysize; - pkcs5->dklen = (effkeysize + 8 - 1) / 8; - return 0; -} - -static int -parse_pbes1(LIBSSH2_SESSION *session, pkcs5params *pkcs5, - pkcs5algo *algo, asn1Element *param) -{ - asn1Element salt; - asn1Element iterationCount; - unsigned long itercount; - char *cp; - - if (!param || *param->header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - - cp = getASN1Element(&salt, param->beg, param->end); - if (!cp || *salt.header != ASN1_OCTET_STRING || - salt.end - salt.beg != algo->saltlen) - return -1; - if (getASN1Element(&iterationCount, cp, param->end) != param->end || - *iterationCount.header != ASN1_INTEGER) - return -1; - if (asn1getword(&iterationCount, &itercount) || - !itercount || itercount > 100000) - return -1; - pkcs5->cipher = algo->cipher; - pkcs5->blocksize = algo->blocksize; - pkcs5->mode = algo->mode; - pkcs5->padopt = algo->padopt; - pkcs5->padchar = algo->padchar; - pkcs5->hash = algo->hash; - pkcs5->hashlen = algo->hashlen; - pkcs5->dklen = 16; - pkcs5->saltlen = algo->saltlen; - pkcs5->effkeysize = algo->effkeysize; - pkcs5->salt = salt.beg; - pkcs5->kdf = pbkdf1; - pkcs5->itercount = itercount; - return 0; -} - -static int -pkcs8kek(LIBSSH2_SESSION *session, _libssh2_os400qc3_crypto_ctx **ctx, - const unsigned char *data, unsigned int datalen, - const unsigned char *passphrase, asn1Element *privkeyinfo) -{ - asn1Element encprivkeyinfo; - asn1Element pkcs5alg; - pkcs5params pkcs5; - size_t pplen; - char *cp; - unsigned long t; - int i; - char *dk = NULL; - Qc3_Format_ALGD0200_T algd; - Qus_EC_t errcode; - - /* Determine if the PKCS#8 data is encrypted and, if so, set-up a - key encryption key and algorithm in context. - Return 1 if encrypted, 0, if not, -1 if error. */ - - *ctx = NULL; - privkeyinfo->beg = (char *) data; - privkeyinfo->end = privkeyinfo->beg + datalen; - - /* If no passphrase is given, it cannot be an encrypted key. */ - if (!passphrase || !*passphrase) - return 0; - - /* Parse PKCS#8 data, checking if ASN.1 format is PrivateKeyInfo or - EncryptedPrivateKeyInfo. */ - if (getASN1Element(&encprivkeyinfo, privkeyinfo->beg, privkeyinfo->end) != - (char *) data + datalen || - *encprivkeyinfo.header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - cp = getASN1Element(&pkcs5alg, encprivkeyinfo.beg, encprivkeyinfo.end); - if (!cp) - return -1; - - switch (*pkcs5alg.header) { - case ASN1_INTEGER: /* Version. */ - return 0; /* This is a PrivateKeyInfo --> not encrypted. */ - case ASN1_SEQ | ASN1_CONSTRUCTED: /* AlgorithIdentifier. */ - break; /* This is an EncryptedPrivateKeyInfo --> encrypted. */ - default: - return -1; /* Unrecognized: error. */ - } - - /* Get the encrypted key data. */ - if (getASN1Element(privkeyinfo, cp, encprivkeyinfo.end) != - encprivkeyinfo.end || *privkeyinfo->header != ASN1_OCTET_STRING) - return -1; - - /* PKCS#5: parse the PBES AlgorithmIdentifier and recursively get all - encryption parameters. */ - memset((char *) &pkcs5, 0, sizeof pkcs5); - if (parse_pkcs5_algorithm(session, &pkcs5, &pkcs5alg, pbestable)) - return -1; - - /* Compute the derived key. */ - if ((*pkcs5.kdf)(session, &dk, passphrase, &pkcs5)) - return -1; - - /* Prepare the algorithm descriptor. */ - memset((char *) &algd, 0, sizeof algd); - algd.Block_Cipher_Alg = pkcs5.cipher; - algd.Block_Length = pkcs5.blocksize; - algd.Mode = pkcs5.mode; - algd.Pad_Option = pkcs5.padopt; - algd.Pad_Character = pkcs5.padchar; - algd.Effective_Key_Size = pkcs5.effkeysize; - memcpy(algd.Init_Vector, pkcs5.iv, pkcs5.ivlen); - - /* Create the key and algorithm context tokens. */ - *ctx = libssh2_init_crypto_ctx(NULL); - if (!*ctx) { - LIBSSH2_FREE(session, dk); - return -1; - } - libssh2_init_crypto_ctx(*ctx); - set_EC_length(errcode, sizeof errcode); - Qc3CreateKeyContext(dk, &pkcs5.dklen, binstring, &algd.Block_Cipher_Alg, - qc3clear, NULL, NULL, (*ctx)->key.Key_Context_Token, - (char *) &errcode); - LIBSSH2_FREE(session, dk); - if (errcode.Bytes_Available) { - free((char *) *ctx); - *ctx = NULL; - return -1; - } - - Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Block_Cipher, - (*ctx)->hash.Alg_Context_Token, &errcode); - if (errcode.Bytes_Available) { - Qc3DestroyKeyContext((*ctx)->key.Key_Context_Token, (char *) &ecnull); - free((char *) *ctx); - *ctx = NULL; - return -1; - } - return 1; /* Tell it's encrypted. */ -} - -static int -rsapkcs8privkey(LIBSSH2_SESSION *session, - const unsigned char *data, unsigned int datalen, - const unsigned char *passphrase, void *loadkeydata) -{ - libssh2_rsa_ctx *ctx = (libssh2_rsa_ctx *) loadkeydata; - char keyform = Qc3_Clear; - char *kek = NULL; - char *kea = NULL; - _libssh2_os400qc3_crypto_ctx *kekctx; - asn1Element pki; - int pkilen; - Qus_EC_t errcode; - - switch (pkcs8kek(session, &kekctx, data, datalen, passphrase, &pki)) { - case 1: - keyform = Qc3_Encrypted; - kek = kekctx->key.Key_Context_Token; - kea = kekctx->hash.Alg_Context_Token; - case 0: - break; - default: - return -1; - } - - set_EC_length(errcode, sizeof errcode); - pkilen = pki.end - pki.beg; - Qc3CreateKeyContext((unsigned char *) pki.beg, &pkilen, berstring, - rsaprivate, &keyform, kek, kea, - ctx->key.Key_Context_Token, (char *) &errcode); - if (errcode.Bytes_Available) { - if (kekctx) - _libssh2_os400qc3_crypto_dtor(kekctx); - return -1; - } - ctx->kek = kekctx; - return 0; -} - -static char * -storewithlength(char *p, const char *data, int length) -{ - _libssh2_htonu32(p, length); - if (length) - memcpy(p + 4, data, length); - return p + 4 + length; -} - -static int -sshrsapubkey(LIBSSH2_SESSION *session, char **sshpubkey, - asn1Element *params, asn1Element *key, const char *method) -{ - int methlen = strlen(method); - asn1Element keyseq; - asn1Element m; - asn1Element e; - int len; - char *cp; - - if (getASN1Element(&keyseq, key->beg + 1, key->end) != key->end || - *keyseq.header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - if (!getASN1Element(&m, keyseq.beg, keyseq.end) || - *m.header != ASN1_INTEGER) - return -1; - if (getASN1Element(&e, m.end, keyseq.end) != keyseq.end || - *e.header != ASN1_INTEGER) - return -1; - len = 4 + methlen + 4 + (e.end - e.beg) + 4 + (m.end - m.beg); - cp = LIBSSH2_ALLOC(session, len); - if (!cp) - return -1; - *sshpubkey = cp; - cp = storewithlength(cp, method, methlen); - cp = storewithlength(cp, e.beg, e.end - e.beg); - cp = storewithlength(cp, m.beg, m.end - m.beg); - return len; -} - -static int -rsapkcs8pubkey(LIBSSH2_SESSION *session, - const unsigned char *data, unsigned int datalen, - const unsigned char *passphrase, void *loadkeydata) -{ - loadpubkeydata *p = (loadpubkeydata *) loadkeydata; - char *buf; - int len; - char *cp; - int i; - char keyform = Qc3_Clear; - char *kek = NULL; - char *kea = NULL; - _libssh2_os400qc3_crypto_ctx *kekctx; - asn1Element subjpubkeyinfo; - asn1Element algorithmid; - asn1Element algorithm; - asn1Element subjpubkey; - asn1Element parameters; - asn1Element pki; - int pkilen; - Qus_EC_t errcode; - - if (!(buf = alloca(datalen))) - return -1; - - switch (pkcs8kek(session, &kekctx, data, datalen, passphrase, &pki)) { - case 1: - keyform = Qc3_Encrypted; - kek = kekctx->key.Key_Context_Token; - kea = kekctx->hash.Alg_Context_Token; - case 0: - break; - default: - return -1; - } - - set_EC_length(errcode, sizeof errcode); - pkilen = pki.end - pki.beg; - Qc3ExtractPublicKey(pki.beg, &pkilen, berstring, &keyform, - kek, kea, buf, (int *) &datalen, &len, &errcode); - _libssh2_os400qc3_crypto_dtor(kekctx); - if (errcode.Bytes_Available) - return -1; - /* Get the algorithm OID and key data from SubjectPublicKeyInfo. */ - if (getASN1Element(&subjpubkeyinfo, buf, buf + len) != buf + len || - *subjpubkeyinfo.header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - cp = getASN1Element(&algorithmid, subjpubkeyinfo.beg, subjpubkeyinfo.end); - if (!cp || *algorithmid.header != (ASN1_SEQ | ASN1_CONSTRUCTED)) - return -1; - if (!getASN1Element(&algorithm, algorithmid.beg, algorithmid.end) || - *algorithm.header != ASN1_OBJ_ID) - return -1; - if (getASN1Element(&subjpubkey, cp, subjpubkeyinfo.end) != - subjpubkeyinfo.end || *subjpubkey.header != ASN1_BIT_STRING) - return -1; - /* Check for supported algorithm. */ - for (i = 0; pka[i].oid; i++) - if (!oidcmp(&algorithm, pka[i].oid)) { - len = (*pka[i].sshpubkey)(session, &p->data, &algorithmid, - &subjpubkey, pka[i].method); - if (len < 0) - return -1; - p->length = len; - p->method = pka[i].method; - return 0; - } - return -1; /* Algorithm not supported. */ -} - -static int -pkcs1topkcs8(LIBSSH2_SESSION *session, - const unsigned char **data8, unsigned int *datalen8, - const unsigned char *data1, unsigned int datalen1) -{ - asn1Element *prvk; - asn1Element *pkcs8; - unsigned char *data; - - *data8 = NULL; - *datalen8 = 0; - if (datalen1 < 2) - return -1; - prvk = asn1_new_from_bytes(data1, datalen1); - if (!prvk) - return -1; - pkcs8 = rsaprivatekeyinfo(prvk); - asn1delete(prvk); - if (!prvk) { - asn1delete(pkcs8); - pkcs8 = NULL; - } - if (!pkcs8) - return -1; - data = (unsigned char *) LIBSSH2_ALLOC(session, pkcs8->end - pkcs8->header); - if (!data) { - asn1delete(pkcs8); - return -1; - } - *data8 = data; - *datalen8 = pkcs8->end - pkcs8->header; - memcpy((char *) data, (char *) pkcs8->header, *datalen8); - asn1delete(pkcs8); - return 0; -} - -static int -rsapkcs1privkey(LIBSSH2_SESSION *session, - const unsigned char *data, unsigned int datalen, - const unsigned char *passphrase, void *loadkeydata) -{ - const unsigned char *data8; - unsigned int datalen8; - int ret; - - if (pkcs1topkcs8(session, &data8, &datalen8, data, datalen)) - return -1; - ret = rsapkcs8privkey(session, data8, datalen8, passphrase, loadkeydata); - LIBSSH2_FREE(session, (char *) data8); - return ret; -} - -static int -rsapkcs1pubkey(LIBSSH2_SESSION *session, - const unsigned char *data, unsigned int datalen, - const unsigned char *passphrase, void *loadkeydata) -{ - const unsigned char *data8; - unsigned int datalen8; - int ret; - - if (pkcs1topkcs8(session, &data8, &datalen8, data, datalen)) - return -1; - ret = rsapkcs8pubkey(session, data8, datalen8, passphrase, loadkeydata); - LIBSSH2_FREE(session, (char *) data8); - return ret; -} - -static int -try_pem_load(LIBSSH2_SESSION *session, FILE *fp, - const unsigned char *passphrase, - const char *header, const char *trailer, - loadkeyproc proc, void *loadkeydata) -{ - unsigned char *data = NULL; - unsigned int datalen = 0; - int c; - int ret; - - fseek(fp, 0L, SEEK_SET); - for (;;) { - ret = _libssh2_pem_parse(session, header, trailer, - fp, &data, &datalen); - - if (!ret) { - ret = (*proc)(session, data, datalen, passphrase, loadkeydata); - if (!ret) - return 0; - } - - if (data) { - LIBSSH2_FREE(session, data); - data = NULL; - } - c = getc(fp); - - if (c == EOF) - break; - - ungetc(c, fp); - } - - return -1; -} - -static int -load_rsa_private_file(LIBSSH2_SESSION *session, const char *filename, - unsigned const char *passphrase, - loadkeyproc proc1, loadkeyproc proc8, void *loadkeydata) -{ - FILE *fp = fopen(filename, fopenrmode); - unsigned char *data = NULL; - size_t datalen = 0; - int ret; - long filesize; - - if (!fp) - return -1; - - /* Try with "ENCRYPTED PRIVATE KEY" PEM armor. - --> PKCS#8 EncryptedPrivateKeyInfo */ - ret = try_pem_load(session, fp, passphrase, beginencprivkeyhdr, - endencprivkeyhdr, proc8, loadkeydata); - - /* Try with "PRIVATE KEY" PEM armor. - --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */ - if (ret) - ret = try_pem_load(session, fp, passphrase, beginprivkeyhdr, - endprivkeyhdr, proc8, loadkeydata); - - /* Try with "RSA PRIVATE KEY" PEM armor. - --> PKCS#1 RSAPrivateKey */ - if (ret) - ret = try_pem_load(session, fp, passphrase, beginrsaprivkeyhdr, - endrsaprivkeyhdr, proc1, loadkeydata); - fclose(fp); - - if (ret) { - /* Try DER encoding. */ - fp = fopen(filename, fopenrbmode); - fseek(fp, 0L, SEEK_END); - filesize = ftell(fp); - - if (filesize <= 32768) { /* Limit to a reasonable size. */ - datalen = filesize; - data = (unsigned char *) alloca(datalen); - if (data) { - fseek(fp, 0L, SEEK_SET); - fread(data, datalen, 1, fp); - - /* Try as PKCS#8 DER data. - --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */ - ret = (*proc8)(session, data, datalen, passphrase, - loadkeydata); - - /* Try as PKCS#1 DER data. - --> PKCS#1 RSAPrivateKey */ - if (ret) - ret = (*proc1)(session, data, datalen, passphrase, - loadkeydata); - } - } - fclose(fp); - } - - return ret; -} - -int -_libssh2_rsa_new_private(libssh2_rsa_ctx **rsa, LIBSSH2_SESSION *session, - const char *filename, unsigned const char *passphrase) -{ - libssh2_rsa_ctx *ctx = libssh2_init_crypto_ctx(NULL); - int ret; - Qc3_Format_ALGD0400_T algd; - Qus_EC_t errcode; - - if (!ctx) - return -1; - ret = load_rsa_private_file(session, filename, passphrase, - rsapkcs1privkey, rsapkcs8privkey, (void *) ctx); - if (!ret) { - /* Create the algorithm context. */ - algd.Public_Key_Alg = Qc3_RSA; - algd.PKA_Block_Format = Qc3_PKCS1_01; - memset(algd.Reserved, 0, sizeof algd.Reserved); - algd.Signing_Hash_Alg = Qc3_SHA1; - set_EC_length(errcode, sizeof errcode); - Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key, - ctx->hash.Alg_Context_Token, &errcode); - if (errcode.Bytes_Available) - ret = -1; - } - if (ret) { - _libssh2_os400qc3_crypto_dtor(ctx); - ctx = NULL; - } - *rsa = ctx; - return ret; -} - -int -_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, size_t *method_len, - unsigned char **pubkeydata, size_t *pubkeydata_len, - const char *privatekey, const char *passphrase) - -{ - loadpubkeydata p; - int ret; - - *method = NULL; - *method_len = 0; - *pubkeydata = NULL; - *pubkeydata_len = 0; - - ret = load_rsa_private_file(session, privatekey, passphrase, - rsapkcs1pubkey, rsapkcs8pubkey, (void *) &p); - if (!ret) { - *method_len = strlen(p.method); - if ((*method = LIBSSH2_ALLOC(session, *method_len))) - memcpy((char *) *method, p.method, *method_len); - else - ret = -1; - } - - if (ret) { - if (*method) - LIBSSH2_FREE(session, *method); - if (p.data) - LIBSSH2_FREE(session, (void *) p.data); - *method = NULL; - *method_len = 0; - } else { - *pubkeydata = (unsigned char *) p.data; - *pubkeydata_len = p.length; - } - - return ret; -} - -int -_libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, - LIBSSH2_SESSION *session, - const char *filedata, - size_t filedata_len, - unsigned const char *passphrase) -{ - libssh2_rsa_ctx *ctx = libssh2_init_crypto_ctx(NULL); - unsigned char *data = NULL; - unsigned int datalen = 0; - int ret; - Qc3_Format_ALGD0400_T algd; - Qus_EC_t errcode; - - if (!ctx) - return -1; - - /* Try with "ENCRYPTED PRIVATE KEY" PEM armor. - --> PKCS#8 EncryptedPrivateKeyInfo */ - ret = _libssh2_pem_parse_memory(session, - beginencprivkeyhdr, endencprivkeyhdr, - filedata, filedata_len, &data, &datalen); - - /* Try with "PRIVATE KEY" PEM armor. - --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */ - if (ret) - ret = _libssh2_pem_parse_memory(session, - beginprivkeyhdr, endprivkeyhdr, - filedata, filedata_len, - &data, &datalen); - - if (!ret) { - /* Process PKCS#8. */ - ret = rsapkcs8privkey(session, - data, datalen, passphrase, (void *) &ctx); - } else { - /* Try with "RSA PRIVATE KEY" PEM armor. - --> PKCS#1 RSAPrivateKey */ - ret = _libssh2_pem_parse_memory(session, - beginrsaprivkeyhdr, endrsaprivkeyhdr, - filedata, filedata_len, - &data, &datalen); - if (!ret) - ret = rsapkcs1privkey(session, - data, datalen, passphrase, (void *) &ctx); - } - - if (ret) { - /* Try as PKCS#8 DER data. - --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */ - ret = rsapkcs8privkey(session, filedata, filedata_len, - passphrase, (void *) &ctx); - - /* Try as PKCS#1 DER data. - --> PKCS#1 RSAPrivateKey */ - if (ret) - ret = rsapkcs1privkey(session, filedata, filedata_len, - passphrase, (void *) &ctx); - } - - if (data) - LIBSSH2_FREE(session, data); - - if (!ret) { - /* Create the algorithm context. */ - algd.Public_Key_Alg = Qc3_RSA; - algd.PKA_Block_Format = Qc3_PKCS1_01; - memset(algd.Reserved, 0, sizeof algd.Reserved); - algd.Signing_Hash_Alg = Qc3_SHA1; - set_EC_length(errcode, sizeof errcode); - Qc3CreateAlgorithmContext((char *) &algd, Qc3_Alg_Public_Key, - ctx->hash.Alg_Context_Token, &errcode); - if (errcode.Bytes_Available) - ret = -1; - } - - if (ret) { - _libssh2_os400qc3_crypto_dtor(ctx); - ctx = NULL; - } - - *rsa = ctx; - return ret; -} - -int -_libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, - unsigned char **method, size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekeydata, - size_t privatekeydata_len, - const char *passphrase) -{ - loadpubkeydata p; - unsigned char *data = NULL; - unsigned int datalen = 0; - const char *meth; - int ret; - - *method = NULL; - *method_len = 0; - *pubkeydata = NULL; - *pubkeydata_len = 0; - - /* Try with "ENCRYPTED PRIVATE KEY" PEM armor. - --> PKCS#8 EncryptedPrivateKeyInfo */ - ret = _libssh2_pem_parse_memory(session, - beginencprivkeyhdr, endencprivkeyhdr, - privatekeydata, privatekeydata_len, - &data, &datalen); - - /* Try with "PRIVATE KEY" PEM armor. - --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */ - if (ret) - ret = _libssh2_pem_parse_memory(session, - beginprivkeyhdr, endprivkeyhdr, - privatekeydata, privatekeydata_len, - &data, &datalen); - - if (!ret) { - /* Process PKCS#8. */ - ret = rsapkcs8pubkey(session, - data, datalen, passphrase, (void *) &p); - } else { - /* Try with "RSA PRIVATE KEY" PEM armor. - --> PKCS#1 RSAPrivateKey */ - ret = _libssh2_pem_parse_memory(session, - beginrsaprivkeyhdr, endrsaprivkeyhdr, - privatekeydata, privatekeydata_len, - &data, &datalen); - if (!ret) - ret = rsapkcs1pubkey(session, - data, datalen, passphrase, (void *) &p); - } - - if (ret) { - /* Try as PKCS#8 DER data. - --> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */ - ret = rsapkcs8pubkey(session, privatekeydata, privatekeydata_len, - passphrase, (void *) &p); - - /* Try as PKCS#1 DER data. - --> PKCS#1 RSAPrivateKey */ - if (ret) - ret = rsapkcs1pubkey(session, privatekeydata, privatekeydata_len, - passphrase, (void *) &p); - } - - if (data) - LIBSSH2_FREE(session, data); - - if (!ret) { - *method_len = strlen(p.method); - if ((*method = LIBSSH2_ALLOC(session, *method_len))) - memcpy((char *) *method, p.method, *method_len); - else - ret = -1; - } - if (ret) { - if (*method) - LIBSSH2_FREE(session, *method); - if (p.data) - LIBSSH2_FREE(session, (void *) p.data); - *method = NULL; - *method_len = 0; - } else { - *pubkeydata = (unsigned char *) p.data; - *pubkeydata_len = p.length; - } - - return ret; -} - -int -_libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa, - const unsigned char *sig, unsigned long sig_len, - const unsigned char *m, unsigned long m_len) -{ - Qus_EC_t errcode; - int slen = sig_len; - int mlen = m_len; - - set_EC_length(errcode, sizeof errcode); - Qc3VerifySignature((char *) sig, &slen, (char *) m, &mlen, Qc3_Data, - rsa->hash.Alg_Context_Token, Qc3_Alg_Token, - rsa->key.Key_Context_Token, Qc3_Key_Token, anycsp, - NULL, (char *) &errcode); - return errcode.Bytes_Available? -1: 0; -} - -int -_libssh2_os400qc3_rsa_sha1_signv(LIBSSH2_SESSION *session, - unsigned char **signature, - size_t *signature_len, - int veccount, - const struct iovec vector[], - libssh2_rsa_ctx *ctx) -{ - Qus_EC_t errcode; - int siglen; - unsigned char *sig; - char sigbuf[8192]; - int sigbufsize = sizeof sigbuf; - - ctx->hash.Final_Op_Flag = Qc3_Final; - set_EC_length(errcode, sizeof errcode); - Qc3CalculateSignature((char *) vector, &veccount, Qc3_Array, - (char *) &ctx->hash, Qc3_Alg_Token, - (char *) &ctx->key, Qc3_Key_Token, - anycsp, NULL, sigbuf, &sigbufsize, &siglen, - (char *) &errcode); - ctx->hash.Final_Op_Flag = Qc3_Continue; - if (errcode.Bytes_Available) - return -1; - sig = LIBSSH2_ALLOC(session, siglen); - if (!sig) - return -1; - memcpy((char *) sig, sigbuf, siglen); - *signature = sig; - *signature_len = siglen; - return 0; -} - -void -_libssh2_init_aes_ctr(void) -{ -} - -#endif /* LIBSSH2_OS400QC3 */ - -/* vim: set expandtab ts=4 sw=4: */ diff --git a/libssh2/src/os400qc3.h b/libssh2/src/os400qc3.h deleted file mode 100644 index dbaa581f6..000000000 --- a/libssh2/src/os400qc3.h +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2015 Patrick Monnerat, D+H - * 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. - */ - -#ifndef LIBSSH2_OS400QC3_H -#define LIBSSH2_OS400QC3_H - -#include -#include - -#include - - -/* Redefine character/string literals as always EBCDIC. */ -#undef Qc3_Alg_Token -#define Qc3_Alg_Token "\xC1\xD3\xC7\xC4\xF0\xF1\xF0\xF0" /* ALGD0100 */ -#undef Qc3_Alg_Block_Cipher -#define Qc3_Alg_Block_Cipher "\xC1\xD3\xC7\xC4\xF0\xF2\xF0\xF0" /* ALGD0200 */ -#undef Qc3_Alg_Block_CipherAuth -#define Qc3_Alg_Block_CipherAuth \ - "\xC1\xD3\xC7\xC4\xF0\xF2\xF1\xF0" /* ALGD0210 */ -#undef Qc3_Alg_Stream_Cipher -#define Qc3_Alg_Stream_Cipher \ - "\xC1\xD3\xC7\xC4\xF0\xF3\xF0\xF0" /* ALGD0300 */ -#undef Qc3_Alg_Public_Key -#define Qc3_Alg_Public_Key "\xC1\xD3\xC7\xC4\xF0\xF4\xF0\xF0" /* ALGD0400 */ -#undef Qc3_Alg_Hash -#define Qc3_Alg_Hash "\xC1\xD3\xC7\xC4\xF0\xF5\xF0\xF0" /* ALGD0500 */ -#undef Qc3_Data -#define Qc3_Data "\xC4\xC1\xE3\xC1\xF0\xF1\xF0\xF0" /* DATA0100 */ -#undef Qc3_Array -#define Qc3_Array "\xC4\xC1\xE3\xC1\xF0\xF2\xF0\xF0" /* DATA0200 */ -#undef Qc3_Key_Token -#define Qc3_Key_Token "\xD2\xC5\xE8\xC4\xF0\xF1\xF0\xF0" /* KEYD0100 */ -#undef Qc3_Key_Parms -#define Qc3_Key_Parms "\xD2\xC5\xE8\xC4\xF0\xF2\xF0\xF0" /* KEYD0200 */ -#undef Qc3_Key_KSLabel -#define Qc3_Key_KSLabel "\xD2\xC5\xE8\xC4\xF0\xF4\xF0\xF0" /* KEYD0400 */ -#undef Qc3_Key_PKCS5 -#define Qc3_Key_PKCS5 "\xD2\xC5\xE8\xC4\xF0\xF5\xF0\xF0" /* KEYD0500 */ -#undef Qc3_Key_PEMCert -#define Qc3_Key_PEMCert "\xD2\xC5\xE8\xC4\xF0\xF6\xF0\xF0" /* KEYD0600 */ -#undef Qc3_Key_CSLabel -#define Qc3_Key_CSLabel "\xD2\xC5\xE8\xC4\xF0\xF7\xF0\xF0" /* KEYD0700 */ -#undef Qc3_Key_CSDN -#define Qc3_Key_CSDN "\xD2\xC5\xE8\xC4\xF0\xF8\xF0\xF0" /* KEYD0800 */ -#undef Qc3_Key_AppID -#define Qc3_Key_AppID "\xD2\xC5\xE8\xC4\xF0\xF9\xF0\xF0" /* KEYD0900 */ - -#undef Qc3_ECB -#define Qc3_ECB '\xF0' /* '0' */ -#undef Qc3_CBC -#define Qc3_CBC '\xF1' /* '1' */ -#undef Qc3_OFB -#define Qc3_OFB '\xF2' /* '2' */ -#undef Qc3_CFB1Bit -#define Qc3_CFB1Bit '\xF3' /* '3' */ -#undef Qc3_CFB8Bit -#define Qc3_CFB8Bit '\xF4' /* '4' */ -#undef Qc3_CFB64Bit -#define Qc3_CFB64Bit '\xF5' /* '5' */ -#undef Qc3_CUSP -#define Qc3_CUSP '\xF6' /* '6' */ -#undef Qc3_CTR -#define Qc3_CTR '\xF7' /* '7' */ -#undef Qc3_CCM -#define Qc3_CCM '\xF8' /* '8' */ -#undef Qc3_No_Pad -#define Qc3_No_Pad '\xF0' /* '0' */ -#undef Qc3_Pad_Char -#define Qc3_Pad_Char '\xF1' /* '1' */ -#undef Qc3_Pad_Counter -#define Qc3_Pad_Counter '\xF2' /* '2' */ -#undef Qc3_PKCS1_00 -#define Qc3_PKCS1_00 '\xF0' /* '0' */ -#undef Qc3_PKCS1_01 -#define Qc3_PKCS1_01 '\xF1' /* '1' */ -#undef Qc3_PKCS1_02 -#define Qc3_PKCS1_02 '\xF2' /* '2' */ -#undef Qc3_ISO9796 -#define Qc3_ISO9796 '\xF3' /* '3' */ -#undef Qc3_Zero_Pad -#define Qc3_Zero_Pad '\xF4' /* '4' */ -#undef Qc3_ANSI_X931 -#define Qc3_ANSI_X931 '\xF5' /* '5' */ -#undef Qc3_OAEP -#define Qc3_OAEP '\xF6' /* '6' */ -#undef Qc3_Bin_String -#define Qc3_Bin_String '\xF0' /* '0' */ -#undef Qc3_BER_String -#define Qc3_BER_String '\xF1' /* '1' */ -#undef Qc3_MK_Struct -#define Qc3_MK_Struct '\xF3' /* '3' */ -#undef Qc3_KSLabel_Struct -#define Qc3_KSLabel_Struct '\xF4' /* '4' */ -#undef Qc3_PKCS5_Struct -#define Qc3_PKCS5_Struct '\xF5' /* '5' */ -#undef Qc3_PEMCert_String -#define Qc3_PEMCert_String '\xF6' /* '6' */ -#undef Qc3_CSLabel_String -#define Qc3_CSLabel_String '\xF7' /* '7' */ -#undef Qc3_CSDN_String -#define Qc3_CSDN_String '\xF8' /* '8' */ -#undef Qc3_Clear -#define Qc3_Clear '\xF0' /* '0' */ -#undef Qc3_Encrypted -#define Qc3_Encrypted '\xF1' /* '1' */ -#undef Qc3_MK_Encrypted -#define Qc3_MK_Encrypted '\xF2' /* '2' */ -#undef Qc3_Any_CSP -#define Qc3_Any_CSP '\xF0' /* '0' */ -#undef Qc3_Sfw_CSP -#define Qc3_Sfw_CSP '\xF1' /* '1' */ -#undef Qc3_Hdw_CSP -#define Qc3_Hdw_CSP '\xF2' /* '2' */ -#undef Qc3_Continue -#define Qc3_Continue '\xF0' /* '0' */ -#undef Qc3_Final -#define Qc3_Final '\xF1' /* '1' */ -#undef Qc3_MK_New -#define Qc3_MK_New '\xF0' /* '0' */ -#undef Qc3_MK_Current -#define Qc3_MK_Current '\xF1' /* '1' */ -#undef Qc3_MK_Old -#define Qc3_MK_Old '\xF2' /* '2' */ -#undef Qc3_MK_Pending -#define Qc3_MK_Pending '\xF3' /* '3' */ - - -/* Define which features are supported. */ -#define LIBSSH2_MD5 1 -#define LIBSSH2_HMAC_RIPEMD 0 -#define LIBSSH2_HMAC_SHA256 1 -#define LIBSSH2_HMAC_SHA512 1 - -#define LIBSSH2_AES 1 -#define LIBSSH2_AES_CTR 1 -#define LIBSSH2_BLOWFISH 0 -#define LIBSSH2_RC4 1 -#define LIBSSH2_CAST 0 -#define LIBSSH2_3DES 1 - -#define LIBSSH2_RSA 1 -#define LIBSSH2_DSA 0 - -#define MD5_DIGEST_LENGTH 16 -#define SHA_DIGEST_LENGTH 20 -#define SHA256_DIGEST_LENGTH 32 -#define SHA512_DIGEST_LENGTH 64 - - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: global handles structures. - * - *******************************************************************/ - -/* HMAC & private key algorithms support structure. */ -typedef struct _libssh2_os400qc3_crypto_ctx _libssh2_os400qc3_crypto_ctx; -struct _libssh2_os400qc3_crypto_ctx { - Qc3_Format_ALGD0100_T hash; /* Hash algorithm. */ - Qc3_Format_KEYD0100_T key; /* Key. */ - _libssh2_os400qc3_crypto_ctx * kek; /* Key encryption. */ -}; - -typedef struct { /* Big number. */ - unsigned char * bignum; /* Number bits, little-endian. */ - unsigned int length; /* Length of bignum (# bytes). */ -} _libssh2_bn; - -typedef struct { /* Algorithm description. */ - char * fmt; /* Format of Qc3 structure. */ - int algo; /* Algorithm identifier. */ - unsigned char size; /* Block length. */ - unsigned char mode; /* Block mode. */ - int keylen; /* Key length. */ -} _libssh2_os400qc3_cipher_t; - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: Define global types/codes. - * - *******************************************************************/ - -#define libssh2_crypto_init() -#define libssh2_crypto_exit() - -#define libssh2_sha1_ctx Qc3_Format_ALGD0100_T -#define libssh2_sha256_ctx Qc3_Format_ALGD0100_T -#define libssh2_md5_ctx Qc3_Format_ALGD0100_T -#define libssh2_hmac_ctx _libssh2_os400qc3_crypto_ctx -#define _libssh2_cipher_ctx _libssh2_os400qc3_crypto_ctx - -#define libssh2_sha1_init(x) libssh2_os400qc3_hash_init(x, Qc3_SHA1) -#define libssh2_sha1_update(ctx, data, len) \ - libssh2_os400qc3_hash_update(&(ctx), data, len) -#define libssh2_sha1_final(ctx, out) \ - libssh2_os400qc3_hash_final(&(ctx), out) -#define libssh2_sha256_init(x) libssh2_os400qc3_hash_init(x, Qc3_SHA256) -#define libssh2_sha256_update(ctx, data, len) \ - libssh2_os400qc3_hash_update(&(ctx), data, len) -#define libssh2_sha256_final(ctx, out) \ - libssh2_os400qc3_hash_final(&(ctx), out) -#define libssh2_sha256(message, len, out) \ - libssh2_os400qc3_hash(message, len, out, \ - Qc3_SHA256) -#define libssh2_md5_init(x) libssh2_os400qc3_hash_init(x, Qc3_MD5) -#define libssh2_md5_update(ctx, data, len) \ - libssh2_os400qc3_hash_update(&(ctx), data, len) -#define libssh2_md5_final(ctx, out) \ - libssh2_os400qc3_hash_final(&(ctx), out) -#define libssh2_hmac_ctx_init(ctx) \ - memset((char *) &(ctx), 0, \ - sizeof(libssh2_hmac_ctx)) -#define libssh2_hmac_md5_init(ctx, key, keylen) \ - libssh2_os400qc3_hmac_init(ctx, Qc3_MD5, \ - MD5_DIGEST_LENGTH, \ - key, keylen) -#define libssh2_hmac_sha1_init(ctx, key, keylen) \ - libssh2_os400qc3_hmac_init(ctx, Qc3_SHA1, \ - SHA_DIGEST_LENGTH, \ - key, keylen) -#define libssh2_hmac_sha256_init(ctx, key, keylen) \ - libssh2_os400qc3_hmac_init(ctx, Qc3_SHA256, \ - SHA256_DIGEST_LENGTH, \ - key, keylen) -#define libssh2_hmac_sha512_init(ctx, key, keylen) \ - libssh2_os400qc3_hmac_init(ctx, Qc3_SHA512, \ - SHA512_DIGEST_LENGTH, \ - key, keylen) -#define libssh2_hmac_update(ctx, data, datalen) \ - libssh2_os400qc3_hmac_update(&(ctx), \ - data, datalen) -#define libssh2_hmac_final(ctx, data) \ - libssh2_os400qc3_hmac_final(&(ctx), data) -#define libssh2_hmac_cleanup(ctx) \ - _libssh2_os400qc3_crypto_dtor(ctx) - - -#define _libssh2_bn_ctx int /* Not used. */ - -#define _libssh2_bn_ctx_new() 0 -#define _libssh2_bn_ctx_free(bnctx) ((void) 0) - -#define _libssh2_bn_init_from_bin() _libssh2_bn_init() -#define _libssh2_bn_mod_exp(r, a, p, m, ctx) \ - _libssh2_os400qc3_bn_mod_exp(r, a, p, m) -#define _libssh2_bn_bytes(bn) ((bn)->length) - -#define _libssh2_cipher_type(name) _libssh2_os400qc3_cipher_t name -#define _libssh2_cipher_aes128 {Qc3_Alg_Block_Cipher, Qc3_AES, 16, \ - Qc3_CBC, 16} -#define _libssh2_cipher_aes192 {Qc3_Alg_Block_Cipher, Qc3_AES, 24, \ - Qc3_CBC, 24} -#define _libssh2_cipher_aes256 {Qc3_Alg_Block_Cipher, Qc3_AES, 32, \ - Qc3_CBC, 32} -#define _libssh2_cipher_aes128ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 16, \ - Qc3_CTR, 16} -#define _libssh2_cipher_aes192ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 24, \ - Qc3_CTR, 24} -#define _libssh2_cipher_aes256ctr {Qc3_Alg_Block_Cipher, Qc3_AES, 32, \ - Qc3_CTR, 32} -#define _libssh2_cipher_3des {Qc3_Alg_Block_Cipher, Qc3_TDES, 0, \ - Qc3_CBC, 24} -#define _libssh2_cipher_arcfour {Qc3_Alg_Stream_Cipher, Qc3_RC4, 0, 0, 16} - -#define _libssh2_cipher_dtor(ctx) _libssh2_os400qc3_crypto_dtor(ctx) - -#define libssh2_rsa_ctx _libssh2_os400qc3_crypto_ctx -#define _libssh2_rsa_free(ctx) (_libssh2_os400qc3_crypto_dtor(ctx), \ - free((char *) ctx)) -#define libssh2_prepare_iovec(vec, len) memset((char *) (vec), 0, \ - (len) * sizeof(struct iovec)) -#define _libssh2_rsa_sha1_signv(session, sig, siglen, count, vector, ctx) \ - _libssh2_os400qc3_rsa_sha1_signv(session, sig, siglen, \ - count, vector, ctx) - - -/******************************************************************* - * - * OS/400 QC3 crypto-library backend: Support procedure prototypes. - * - *******************************************************************/ - -extern _libssh2_bn * _libssh2_bn_init(void); -extern void _libssh2_bn_free(_libssh2_bn *bn); -extern unsigned long _libssh2_bn_bits(_libssh2_bn *bn); -extern int _libssh2_bn_from_bin(_libssh2_bn *bn, int len, - const unsigned char *v); -extern int _libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val); -extern int _libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val); -extern void _libssh2_random(unsigned char *buf, int len); -extern int _libssh2_bn_rand(_libssh2_bn *bn, int bits, - int top, int bottom); -extern int _libssh2_os400qc3_bn_mod_exp(_libssh2_bn *r, _libssh2_bn *a, - _libssh2_bn *p, _libssh2_bn *m); -extern void _libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x); -extern int libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, - unsigned int algo); -extern void libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx, - unsigned char *data, int len); -extern void libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx, - unsigned char *out); -extern int libssh2_os400qc3_hash(const unsigned char *message, - unsigned long len, unsigned char *out, - unsigned int algo); -extern void libssh2_os400qc3_hmac_init(_libssh2_os400qc3_crypto_ctx *x, - int algo, size_t minkeylen, - void *key, int keylen); -extern void libssh2_os400qc3_hmac_update(_libssh2_os400qc3_crypto_ctx *ctx, - const unsigned char *data, - int len); -extern void libssh2_os400qc3_hmac_final(_libssh2_os400qc3_crypto_ctx *ctx, - unsigned char *out); -extern int _libssh2_os400qc3_rsa_sha1_signv(LIBSSH2_SESSION *session, - unsigned char **signature, - size_t *signature_len, - int veccount, - const struct iovec vector[], - libssh2_rsa_ctx *ctx); - -#endif - -/* vim: set expandtab ts=4 sw=4: */ diff --git a/libssh2/src/packet.c b/libssh2/src/packet.c index c950b5dcf..38ab62944 100644 --- a/libssh2/src/packet.c +++ b/libssh2/src/packet.c @@ -87,7 +87,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, (void) datalen; - if (listen_state->state == libssh2_NB_state_idle) { + if(listen_state->state == libssh2_NB_state_idle) { unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5; listen_state->sender_channel = _libssh2_ntohu32(s); s += 4; @@ -118,9 +118,9 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, listen_state->state = libssh2_NB_state_allocated; } - if (listen_state->state != libssh2_NB_state_sent) { - while (listn) { - if ((listn->port == (int) listen_state->port) && + if(listen_state->state != libssh2_NB_state_sent) { + while(listn) { + if((listn->port == (int) listen_state->port) && (strlen(listn->host) == listen_state->host_len) && (memcmp (listn->host, listen_state->host, listen_state->host_len) == 0)) { @@ -128,8 +128,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, LIBSSH2_CHANNEL *channel = NULL; listen_state->channel = NULL; - if (listen_state->state == libssh2_NB_state_allocated) { - if (listn->queue_maxsize && + if(listen_state->state == libssh2_NB_state_allocated) { + if(listn->queue_maxsize && (listn->queue_maxsize <= listn->queue_size)) { /* Queue is full */ failure_code = SSH_OPEN_RESOURCE_SHORTAGE; @@ -140,7 +140,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, } channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL)); - if (!channel) { + if(!channel) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a channel for " "new connection"); @@ -156,7 +156,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, channel-> channel_type_len + 1); - if (!channel->channel_type) { + if(!channel->channel_type) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a channel for new" " connection"); @@ -203,12 +203,12 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, listen_state->state = libssh2_NB_state_created; } - if (listen_state->state == libssh2_NB_state_created) { + if(listen_state->state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, listen_state->packet, 17, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; - else if (rc) { + else if(rc) { listen_state->state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send channel " @@ -216,7 +216,7 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, } /* Link the channel into the end of the queue list */ - if (listen_state->channel) { + if(listen_state->channel) { _libssh2_list_add(&listn->queue, &listen_state->channel->node); listn->queue_size++; @@ -243,9 +243,10 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, rc = _libssh2_transport_send(session, listen_state->packet, packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { listen_state->state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send open failure"); @@ -273,7 +274,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, (void) datalen; - if (x11open_state->state == libssh2_NB_state_idle) { + if(x11open_state->state == libssh2_NB_state_idle) { unsigned char *s = data + (sizeof("x11") - 1) + 5; x11open_state->sender_channel = _libssh2_ntohu32(s); s += 4; @@ -295,10 +296,10 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, x11open_state->state = libssh2_NB_state_allocated; } - if (session->x11) { - if (x11open_state->state == libssh2_NB_state_allocated) { + if(session->x11) { + if(x11open_state->state == libssh2_NB_state_allocated) { channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL)); - if (!channel) { + if(!channel) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "allocate a channel for new connection"); failure_code = SSH_OPEN_RESOURCE_SHORTAGE; @@ -310,7 +311,7 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1); - if (!channel->channel_type) { + if(!channel->channel_type) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "allocate a channel for new connection"); LIBSSH2_FREE(session, channel); @@ -350,12 +351,13 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, x11open_state->state = libssh2_NB_state_created; } - if (x11open_state->state == libssh2_NB_state_created) { + if(x11open_state->state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, x11open_state->packet, 17, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { x11open_state->state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open " @@ -389,9 +391,10 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, rc = _libssh2_transport_send(session, x11open_state->packet, packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { x11open_state->state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send open failure"); } @@ -416,10 +419,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, size_t datalen, int macstate) { int rc = 0; - char *message=NULL; - char *language=NULL; - size_t message_len=0; - size_t language_len=0; + char *message = NULL; + char *language = NULL; + size_t message_len = 0; + size_t language_len = 0; LIBSSH2_CHANNEL *channelp = NULL; size_t data_head = 0; unsigned char msg = data[0]; @@ -430,7 +433,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, "Packet type %d received, length=%d", (int) msg, (int) datalen); - if ((macstate == LIBSSH2_MAC_INVALID) && + if((macstate == LIBSSH2_MAC_INVALID) && (!session->macerror || LIBSSH2_MACERROR(session, (char *) data, datalen))) { /* Bad MAC input, but no callback set or non-zero return from the @@ -456,9 +459,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, break; } - if (session->packAdd_state == libssh2_NB_state_allocated) { + if(session->packAdd_state == libssh2_NB_state_allocated) { /* A couple exceptions to the packet adding rule: */ - switch (msg) { + switch(msg) { /* byte SSH_MSG_DISCONNECT @@ -478,7 +481,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, /* 9 = packet_type(1) + reason(4) + message_len(4) */ message = (char *) data + 9; - language_len = _libssh2_ntohu32(data + 9 + message_len); + language_len = + _libssh2_ntohu32(data + 9 + message_len); language = (char *) data + 9 + message_len + 4; if(language_len > (datalen-13-message_len)) { @@ -489,9 +493,9 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, } else /* bad size, clear it */ - message_len=0; + message_len = 0; } - if (session->ssh_msg_disconnect) { + if(session->ssh_msg_disconnect) { LIBSSH2_DISCONNECT(session, reason, message, message_len, language, language_len); } @@ -511,11 +515,12 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, */ case SSH_MSG_IGNORE: - if (datalen >= 2) { - if (session->ssh_msg_ignore) { + if(datalen >= 2) { + if(session->ssh_msg_ignore) { LIBSSH2_IGNORE(session, (char *) data + 1, datalen - 1); } - } else if (session->ssh_msg_ignore) { + } + else if(session->ssh_msg_ignore) { LIBSSH2_IGNORE(session, "", 0); } LIBSSH2_FREE(session, data); @@ -531,7 +536,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, case SSH_MSG_DEBUG: if(datalen >= 2) { - int always_display= data[1]; + int always_display = data[1]; if(datalen >= 6) { message_len = _libssh2_ntohu32(data + 2); @@ -539,14 +544,15 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, if(message_len <= (datalen - 10)) { /* 6 = packet_type(1) + display(1) + message_len(4) */ message = (char *) data + 6; - language_len = _libssh2_ntohu32(data + 6 + message_len); + language_len = _libssh2_ntohu32(data + 6 + + message_len); if(language_len <= (datalen - 10 - message_len)) language = (char *) data + 10 + message_len; } } - if (session->ssh_msg_debug) { + if(session->ssh_msg_debug) { LIBSSH2_DEBUG(session, always_display, message, message_len, language, language_len); } @@ -570,8 +576,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, case SSH_MSG_GLOBAL_REQUEST: if(datalen >= 5) { - uint32_t len =0; - unsigned char want_reply=0; + uint32_t len = 0; + unsigned char want_reply = 0; len = _libssh2_ntohu32(data + 1); if(datalen >= (6 + len)) { want_reply = data[5 + len]; @@ -582,13 +588,13 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, } - if (want_reply) { + if(want_reply) { static const unsigned char packet = SSH_MSG_REQUEST_FAILURE; libssh2_packet_add_jump_point5: session->packAdd_state = libssh2_NB_state_jump5; rc = _libssh2_transport_send(session, &packet, 1, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; } } @@ -624,7 +630,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); - if (!channelp) { + if(!channelp) { _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, "Packet received for unknown channel"); LIBSSH2_FREE(session, data); @@ -634,7 +640,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, #ifdef LIBSSH2DEBUG { uint32_t stream_id = 0; - if (msg == SSH_MSG_CHANNEL_EXTENDED_DATA) + if(msg == SSH_MSG_CHANNEL_EXTENDED_DATA) stream_id = _libssh2_ntohu32(data + 5); _libssh2_debug(session, LIBSSH2_TRACE_CONN, @@ -645,7 +651,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, stream_id); } #endif - if ((channelp->remote.extended_data_ignore_mode == + if((channelp->remote.extended_data_ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) && (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)) { /* Pretend we didn't receive this */ @@ -654,14 +660,15 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Ignoring extended data and refunding %d bytes", (int) (datalen - 13)); - if (channelp->read_avail + datalen - data_head >= + if(channelp->read_avail + datalen - data_head >= channelp->remote.window_size) datalen = channelp->remote.window_size - channelp->read_avail + data_head; channelp->remote.window_size -= datalen - data_head; _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "shrinking window size by %lu bytes to %lu, read_avail %lu", + "shrinking window size by %lu bytes to %lu, " + "read_avail %lu", datalen - data_head, channelp->remote.window_size, channelp->read_avail); @@ -675,7 +682,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, packAdd_channelp, datalen - 13, 1, NULL); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; session->packAdd_state = libssh2_NB_state_idle; @@ -686,7 +693,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, * REMEMBER! remote means remote as source of data, * NOT remote window! */ - if (channelp->remote.packet_size < (datalen - data_head)) { + if(channelp->remote.packet_size < (datalen - data_head)) { /* * Spec says we MAY ignore bytes sent beyond * packet_size @@ -697,7 +704,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, " to receive, truncating"); datalen = channelp->remote.packet_size + data_head; } - if (channelp->remote.window_size <= channelp->read_avail) { + if(channelp->remote.window_size <= channelp->read_avail) { /* * Spec says we MAY ignore bytes sent beyond * window_size @@ -713,7 +720,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, /* Reset EOF status */ channelp->remote.eof = 0; - if (channelp->read_avail + datalen - data_head > + if(channelp->read_avail + datalen - data_head > channelp->remote.window_size) { _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, @@ -746,7 +753,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, channelp = _libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); - if (!channelp) + if(!channelp) /* We may have freed already, just quietly ignore this... */ ; else { @@ -783,7 +790,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, "Channel %d received request type %.*s (wr %X)", channel, len, data + 9, want_reply); - if (len == sizeof("exit-status") - 1 + if(len == sizeof("exit-status") - 1 && (sizeof("exit-status") - 1 + 9) <= datalen && !memcmp("exit-status", data + 9, sizeof("exit-status") - 1)) { @@ -793,7 +800,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, channelp = _libssh2_channel_locate(session, channel); - if (channelp && (sizeof("exit-status") + 13) <= datalen) { + if(channelp && (sizeof("exit-status") + 13) <= datalen) { channelp->exit_status = _libssh2_ntohu32(data + 9 + sizeof("exit-status")); _libssh2_debug(session, LIBSSH2_TRACE_CONN, @@ -805,7 +812,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, } } - else if (len == sizeof("exit-signal") - 1 + else if(len == sizeof("exit-signal") - 1 && (sizeof("exit-signal") - 1 + 9) <= datalen && !memcmp("exit-signal", data + 9, sizeof("exit-signal") - 1)) { @@ -813,7 +820,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, if(datalen >= 20) channelp = _libssh2_channel_locate(session, channel); - if (channelp && (sizeof("exit-signal") + 13) <= datalen) { + if(channelp && (sizeof("exit-signal") + 13) <= datalen) { /* set signal name (without SIG prefix) */ uint32_t namelen = _libssh2_ntohu32(data + 9 + sizeof("exit-signal")); @@ -826,10 +833,11 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, channelp->exit_signal = NULL; } - if (!channelp->exit_signal) + if(!channelp->exit_signal) rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "memory for signal name"); - else if ((sizeof("exit-signal") + 13 + namelen <= datalen)) { + else if((sizeof("exit-signal") + 13 + namelen <= + datalen)) { memcpy(channelp->exit_signal, data + 13 + sizeof("exit-signal"), namelen); channelp->exit_signal[namelen] = '\0'; @@ -845,14 +853,14 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, } - if (want_reply) { + if(want_reply) { unsigned char packet[5]; libssh2_packet_add_jump_point4: session->packAdd_state = libssh2_NB_state_jump4; packet[0] = SSH_MSG_CHANNEL_FAILURE; - memcpy(&packet[1], data+1, 4); + memcpy(&packet[1], data + 1, 4); rc = _libssh2_transport_send(session, packet, 5, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; } } @@ -870,7 +878,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, channelp = _libssh2_channel_locate(session, _libssh2_ntohu32(data + 1)); - if (!channelp) { + if(!channelp) { /* We may have freed already, just quietly ignore this... */ LIBSSH2_FREE(session, data); session->packAdd_state = libssh2_NB_state_idle; @@ -899,7 +907,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, case SSH_MSG_CHANNEL_OPEN: if(datalen < 17) ; - else if ((datalen >= (sizeof("forwarded-tcpip") + 4)) && + else if((datalen >= (sizeof("forwarded-tcpip") + 4)) && ((sizeof("forwarded-tcpip") - 1) == _libssh2_ntohu32(data + 1)) && @@ -915,7 +923,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, rc = packet_queue_listener(session, data, datalen, &session->packAdd_Qlstn_state); } - else if ((datalen >= (sizeof("x11") + 4)) && + else if((datalen >= (sizeof("x11") + 4)) && ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) && (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) { @@ -928,7 +936,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, rc = packet_x11_open(session, data, datalen, &session->packAdd_x11open_state); } - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; LIBSSH2_FREE(session, data); @@ -970,10 +978,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, session->packAdd_state = libssh2_NB_state_sent; } - if (session->packAdd_state == libssh2_NB_state_sent) { + if(session->packAdd_state == libssh2_NB_state_sent) { LIBSSH2_PACKET *packetp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); - if (!packetp) { + if(!packetp) { _libssh2_debug(session, LIBSSH2_ERROR_ALLOC, "memory for packet"); LIBSSH2_FREE(session, data); @@ -989,10 +997,10 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, session->packAdd_state = libssh2_NB_state_sent1; } - if ((msg == SSH_MSG_KEXINIT && + if((msg == SSH_MSG_KEXINIT && !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) || (session->packAdd_state == libssh2_NB_state_sent2)) { - if (session->packAdd_state == libssh2_NB_state_sent1) { + if(session->packAdd_state == libssh2_NB_state_sent1) { /* * Remote wants new keys * Well, it's already in the brigade, @@ -1021,7 +1029,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, * send NEWKEYS yet, otherwise remote will drop us like a rock */ rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; } @@ -1046,8 +1054,8 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Looking for packet of type: %d", (int) packet_type); - while (packet) { - if (packet->data[0] == packet_type + while(packet) { + if(packet->data[0] == packet_type && (packet->data_len >= (match_ofs + match_len)) && (!match_buf || (memcmp(packet->data + match_ofs, match_buf, @@ -1084,7 +1092,7 @@ _libssh2_packet_askv(LIBSSH2_SESSION * session, int i, packet_types_len = strlen((char *) packet_types); for(i = 0; i < packet_types_len; i++) { - if (0 == _libssh2_packet_ask(session, packet_types[i], data, + if(0 == _libssh2_packet_ask(session, packet_types[i], data, data_len, match_ofs, match_buf, match_len)) { return 0; @@ -1111,8 +1119,8 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type, size_t match_len, packet_require_state_t *state) { - if (state->start == 0) { - if (_libssh2_packet_ask(session, packet_type, data, data_len, + if(state->start == 0) { + if(_libssh2_packet_ask(session, packet_type, data, data_len, match_ofs, match_buf, match_len) == 0) { /* A packet was available in the packet brigade */ @@ -1122,26 +1130,28 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type, state->start = time(NULL); } - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { + while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) { int ret = _libssh2_transport_read(session); - if (ret == LIBSSH2_ERROR_EAGAIN) + if(ret == LIBSSH2_ERROR_EAGAIN) return ret; - else if (ret < 0) { + else if(ret < 0) { state->start = 0; /* an error which is not just because of blocking */ return ret; - } else if (ret == packet_type) { + } + else if(ret == packet_type) { /* Be lazy, let packet_ask pull it out of the brigade */ ret = _libssh2_packet_ask(session, packet_type, data, data_len, match_ofs, match_buf, match_len); state->start = 0; return ret; - } else if (ret == 0) { + } + else if(ret == 0) { /* nothing available, wait until data arrives or we time out */ long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - state->start); - if (left <= 0) { + if(left <= 0) { state->start = 0; return LIBSSH2_ERROR_TIMEOUT; } @@ -1169,13 +1179,13 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session, unsigned char i, all_packets[255]; int ret; - if (*state == libssh2_NB_state_idle) { + if(*state == libssh2_NB_state_idle) { for(i = 1; i < 255; i++) { all_packets[i - 1] = i; } all_packets[254] = 0; - if (_libssh2_packet_askv(session, all_packets, &data, &data_len, 0, + if(_libssh2_packet_askv(session, all_packets, &data, &data_len, 0, NULL, 0) == 0) { i = data[0]; /* A packet was available in the packet brigade, burn it */ @@ -1188,20 +1198,22 @@ _libssh2_packet_burn(LIBSSH2_SESSION * session, *state = libssh2_NB_state_created; } - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { + while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) { ret = _libssh2_transport_read(session); - if (ret == LIBSSH2_ERROR_EAGAIN) { + if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; - } else if (ret < 0) { + } + else if(ret < 0) { *state = libssh2_NB_state_idle; return ret; - } else if (ret == 0) { + } + else if(ret == 0) { /* FIXME: this might busyloop */ continue; } /* Be lazy, let packet_ask pull it out of the brigade */ - if (0 == + if(0 == _libssh2_packet_ask(session, (unsigned char)ret, &data, &data_len, 0, NULL, 0)) { /* Smoke 'em if you got 'em */ @@ -1231,37 +1243,37 @@ _libssh2_packet_requirev(LIBSSH2_SESSION *session, const unsigned char *match_buf, size_t match_len, packet_requirev_state_t * state) { - if (_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs, + if(_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs, match_buf, match_len) == 0) { /* One of the packets listed was available in the packet brigade */ state->start = 0; return 0; } - if (state->start == 0) { + if(state->start == 0) { state->start = time(NULL); } - while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) { + while(session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) { int ret = _libssh2_transport_read(session); - if ((ret < 0) && (ret != LIBSSH2_ERROR_EAGAIN)) { + if((ret < 0) && (ret != LIBSSH2_ERROR_EAGAIN)) { state->start = 0; return ret; } - if (ret <= 0) { + if(ret <= 0) { long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - state->start); - if (left <= 0) { + if(left <= 0) { state->start = 0; return LIBSSH2_ERROR_TIMEOUT; } - else if (ret == LIBSSH2_ERROR_EAGAIN) { + else if(ret == LIBSSH2_ERROR_EAGAIN) { return ret; } } - if (strchr((char *) packet_types, ret)) { + if(strchr((char *) packet_types, ret)) { /* Be lazy, let packet_ask pull it out of the brigade */ return _libssh2_packet_askv(session, packet_types, data, data_len, match_ofs, match_buf, diff --git a/libssh2/src/pem.c b/libssh2/src/pem.c index 9f51bba3b..53f58c2ef 100644 --- a/libssh2/src/pem.c +++ b/libssh2/src/pem.c @@ -43,23 +43,23 @@ readline(char *line, int line_size, FILE * fp) { size_t len; - if (!line) { + if(!line) { return -1; } - if (!fgets(line, line_size, fp)) { + if(!fgets(line, line_size, fp)) { return -1; } - if (*line) { + if(*line) { len = strlen(line); - if (len > 0 && line[len - 1] == '\n') { + if(len > 0 && line[len - 1] == '\n') { line[len - 1] = '\0'; } } - if (*line) { + if(*line) { len = strlen(line); - if (len > 0 && line[len - 1] == '\r') { + if(len > 0 && line[len - 1] == '\r') { line[len - 1] = '\0'; } } @@ -76,14 +76,14 @@ readline_memory(char *line, size_t line_size, off = *filedata_offset; - for (len = 0; off + len < filedata_len && len < line_size; len++) { - if (filedata[off + len] == '\n' || + for(len = 0; off + len < filedata_len && len < line_size - 1; len++) { + if(filedata[off + len] == '\n' || filedata[off + len] == '\r') { break; } } - if (len) { + if(len) { memcpy(line, filedata + off, len); *filedata_offset += len; } @@ -96,36 +96,86 @@ readline_memory(char *line, size_t line_size, #define LINE_SIZE 128 +static const char *crypt_annotation = "Proc-Type: 4,ENCRYPTED"; + +static unsigned char hex_decode(char digit) +{ + return (digit >= 'A') ? 0xA + (digit - 'A') : (digit - '0'); +} + int _libssh2_pem_parse(LIBSSH2_SESSION * session, const char *headerbegin, const char *headerend, + const unsigned char *passphrase, FILE * fp, unsigned char **data, unsigned int *datalen) { char line[LINE_SIZE]; + unsigned char iv[LINE_SIZE]; char *b64data = NULL; unsigned int b64datalen = 0; int ret; + const LIBSSH2_CRYPT_METHOD *method = NULL; do { *line = '\0'; - if (readline(line, LINE_SIZE, fp)) { + if(readline(line, LINE_SIZE, fp)) { return -1; } } - while (strcmp(line, headerbegin) != 0); + while(strcmp(line, headerbegin) != 0); - *line = '\0'; + if(readline(line, LINE_SIZE, fp)) { + return -1; + } + + if(passphrase && + memcmp(line, crypt_annotation, strlen(crypt_annotation)) == 0) { + const LIBSSH2_CRYPT_METHOD **all_methods, *cur_method; + int i; + + if(readline(line, LINE_SIZE, fp)) { + ret = -1; + goto out; + } + + all_methods = libssh2_crypt_methods(); + while((cur_method = *all_methods++)) { + if(*cur_method->pem_annotation && + memcmp(line, cur_method->pem_annotation, + strlen(cur_method->pem_annotation)) == 0) { + method = cur_method; + memcpy(iv, line + strlen(method->pem_annotation) + 1, + 2*method->iv_len); + } + } + + /* None of the available crypt methods were able to decrypt the key */ + if(method == NULL) + return -1; + + /* Decode IV from hex */ + for(i = 0; i < method->iv_len; ++i) { + iv[i] = hex_decode(iv[2*i]) << 4; + iv[i] |= hex_decode(iv[2*i + 1]); + } + + /* skip to the next line */ + if(readline(line, LINE_SIZE, fp)) { + ret = -1; + goto out; + } + } do { - if (*line) { + if(*line) { char *tmp; size_t linelen; linelen = strlen(line); tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen); - if (!tmp) { + if(!tmp) { ret = -1; goto out; } @@ -136,25 +186,102 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, *line = '\0'; - if (readline(line, LINE_SIZE, fp)) { + if(readline(line, LINE_SIZE, fp)) { ret = -1; goto out; } - } while (strcmp(line, headerend) != 0); + } while(strcmp(line, headerend) != 0); - if (!b64data) { + if(!b64data) { return -1; } - if (libssh2_base64_decode(session, (char**) data, datalen, + if(libssh2_base64_decode(session, (char **) data, datalen, b64data, b64datalen)) { ret = -1; goto out; } + if(method) { + /* Set up decryption */ + int free_iv = 0, free_secret = 0, len_decrypted = 0, padding = 0; + int blocksize = method->blocksize; + void *abstract; + unsigned char secret[2*MD5_DIGEST_LENGTH]; + libssh2_md5_ctx fingerprint_ctx; + + /* Perform key derivation (PBKDF1/MD5) */ + if(!libssh2_md5_init(&fingerprint_ctx)) { + ret = -1; + goto out; + } + libssh2_md5_update(fingerprint_ctx, passphrase, + strlen((char *)passphrase)); + libssh2_md5_update(fingerprint_ctx, iv, 8); + libssh2_md5_final(fingerprint_ctx, secret); + if(method->secret_len > MD5_DIGEST_LENGTH) { + if(!libssh2_md5_init(&fingerprint_ctx)) { + ret = -1; + goto out; + } + libssh2_md5_update(fingerprint_ctx, secret, MD5_DIGEST_LENGTH); + libssh2_md5_update(fingerprint_ctx, passphrase, + strlen((char *)passphrase)); + libssh2_md5_update(fingerprint_ctx, iv, 8); + libssh2_md5_final(fingerprint_ctx, secret + MD5_DIGEST_LENGTH); + } + + /* Initialize the decryption */ + if(method->init(session, method, iv, &free_iv, secret, + &free_secret, 0, &abstract)) { + _libssh2_explicit_zero((char *)secret, sizeof(secret)); + LIBSSH2_FREE(session, data); + ret = -1; + goto out; + } + + if(free_secret) { + _libssh2_explicit_zero((char *)secret, sizeof(secret)); + } + + /* Do the actual decryption */ + if((*datalen % blocksize) != 0) { + _libssh2_explicit_zero((char *)secret, sizeof(secret)); + method->dtor(session, &abstract); + _libssh2_explicit_zero(*data, *datalen); + LIBSSH2_FREE(session, *data); + ret = -1; + goto out; + } + + while(len_decrypted <= (int)*datalen - blocksize) { + if(method->crypt(session, *data + len_decrypted, blocksize, + &abstract)) { + ret = LIBSSH2_ERROR_DECRYPT; + _libssh2_explicit_zero((char *)secret, sizeof(secret)); + method->dtor(session, &abstract); + _libssh2_explicit_zero(*data, *datalen); + LIBSSH2_FREE(session, *data); + goto out; + } + + len_decrypted += blocksize; + } + + /* Account for padding */ + padding = (*data)[*datalen - 1]; + memset(&(*data)[*datalen-padding], 0, padding); + *datalen -= padding; + + /* Clean up */ + _libssh2_explicit_zero((char *)secret, sizeof(secret)); + method->dtor(session, &abstract); + } + ret = 0; out: - if (b64data) { + if(b64data) { + _libssh2_explicit_zero(b64data, b64datalen); LIBSSH2_FREE(session, b64data); } return ret; @@ -176,22 +303,22 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session, do { *line = '\0'; - if (readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { + if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { return -1; } } - while (strcmp(line, headerbegin) != 0); + while(strcmp(line, headerbegin) != 0); *line = '\0'; do { - if (*line) { + if(*line) { char *tmp; size_t linelen; linelen = strlen(line); tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen); - if (!tmp) { + if(!tmp) { ret = -1; goto out; } @@ -202,17 +329,17 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session, *line = '\0'; - if (readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { + if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { ret = -1; goto out; } - } while (strcmp(line, headerend) != 0); + } while(strcmp(line, headerend) != 0); - if (!b64data) { + if(!b64data) { return -1; } - if (libssh2_base64_decode(session, (char**) data, datalen, + if(libssh2_base64_decode(session, (char **) data, datalen, b64data, b64datalen)) { ret = -1; goto out; @@ -220,12 +347,462 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session, ret = 0; out: - if (b64data) { + if(b64data) { + _libssh2_explicit_zero(b64data, b64datalen); LIBSSH2_FREE(session, b64data); } return ret; } +/* OpenSSH formatted keys */ +#define AUTH_MAGIC "openssh-key-v1" +#define OPENSSH_HEADER_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----" +#define OPENSSH_HEADER_END "-----END OPENSSH PRIVATE KEY-----" + +static int +_libssh2_openssh_pem_parse_data(LIBSSH2_SESSION * session, + const unsigned char *passphrase, + const char *b64data, size_t b64datalen, + struct string_buf **decrypted_buf) +{ + const LIBSSH2_CRYPT_METHOD *method = NULL; + struct string_buf decoded, decrypted, kdf_buf; + unsigned char *ciphername = NULL; + unsigned char *kdfname = NULL; + unsigned char *kdf = NULL; + unsigned char *buf = NULL; + unsigned char *salt = NULL; + uint32_t nkeys, check1, check2; + uint32_t rounds = 0; + unsigned char *key = NULL; + unsigned char *key_part = NULL; + unsigned char *iv_part = NULL; + unsigned char *f = NULL; + unsigned int f_len = 0; + int ret = 0, keylen = 0, ivlen = 0, total_len = 0; + size_t kdf_len = 0, tmp_len = 0, salt_len = 0; + + if(decrypted_buf) + *decrypted_buf = NULL; + + /* decode file */ + if(libssh2_base64_decode(session, (char **)&f, &f_len, + b64data, b64datalen)) { + ret = -1; + goto out; + } + + /* Parse the file */ + decoded.data = (unsigned char *)f; + decoded.dataptr = (unsigned char *)f; + decoded.len = f_len; + + if(decoded.len < strlen(AUTH_MAGIC)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, "key too short"); + goto out; + } + + if(strncmp((char *) decoded.dataptr, AUTH_MAGIC, + strlen(AUTH_MAGIC)) != 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "key auth magic mismatch"); + goto out; + } + + decoded.dataptr += strlen(AUTH_MAGIC) + 1; + + if(_libssh2_get_string(&decoded, &ciphername, &tmp_len) || + tmp_len == 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "ciphername is missing"); + goto out; + } + + if(_libssh2_get_string(&decoded, &kdfname, &tmp_len) || + tmp_len == 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "kdfname is missing"); + goto out; + } + + if(_libssh2_get_string(&decoded, &kdf, &kdf_len)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "kdf is missing"); + goto out; + } + else { + kdf_buf.data = kdf; + kdf_buf.dataptr = kdf; + kdf_buf.len = kdf_len; + } + + if((passphrase == NULL || strlen((const char *)passphrase) == 0) && + strcmp((const char *)ciphername, "none") != 0) { + /* passphrase required */ + ret = LIBSSH2_ERROR_KEYFILE_AUTH_FAILED; + goto out; + } + + if(strcmp((const char *)kdfname, "none") != 0 && + strcmp((const char *)kdfname, "bcrypt") != 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "unknown cipher"); + goto out; + } + + if(!strcmp((const char *)kdfname, "none") && + strcmp((const char *)ciphername, "none") != 0) { + ret =_libssh2_error(session, LIBSSH2_ERROR_PROTO, + "invalid format"); + goto out; + } + + if(_libssh2_get_u32(&decoded, &nkeys) != 0 || nkeys != 1) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Multiple keys are unsupported"); + goto out; + } + + /* unencrypted public key */ + + if(_libssh2_get_string(&decoded, &buf, &tmp_len) || tmp_len == 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Invalid private key; " + "expect embedded public key"); + goto out; + } + + if(_libssh2_get_string(&decoded, &buf, &tmp_len) || tmp_len == 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Private key data not found"); + goto out; + } + + /* decode encrypted private key */ + decrypted.data = decrypted.dataptr = buf; + decrypted.len = tmp_len; + + if(ciphername && strcmp((const char *)ciphername, "none") != 0) { + const LIBSSH2_CRYPT_METHOD **all_methods, *cur_method; + + all_methods = libssh2_crypt_methods(); + while((cur_method = *all_methods++)) { + if(*cur_method->name && + memcmp(ciphername, cur_method->name, + strlen(cur_method->name)) == 0) { + method = cur_method; + } + } + + /* None of the available crypt methods were able to decrypt the key */ + + if(method == NULL) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "No supported cipher found"); + goto out; + } + } + + if(method) { + int free_iv = 0, free_secret = 0, len_decrypted = 0; + int blocksize; + void *abstract = NULL; + + keylen = method->secret_len; + ivlen = method->iv_len; + total_len = keylen + ivlen; + + key = LIBSSH2_CALLOC(session, total_len); + if(key == NULL) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Could not alloc key"); + goto out; + } + + if(strcmp((const char *)kdfname, "bcrypt") == 0 && + passphrase != NULL) { + if((_libssh2_get_string(&kdf_buf, &salt, &salt_len)) || + (_libssh2_get_u32(&kdf_buf, &rounds) != 0) ) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "kdf contains unexpected values"); + LIBSSH2_FREE(session, key); + goto out; + } + + if(_libssh2_bcrypt_pbkdf((const char *)passphrase, + strlen((const char *)passphrase), + salt, salt_len, key, + keylen + ivlen, rounds) < 0) { + ret = _libssh2_error(session, LIBSSH2_ERROR_DECRYPT, + "invalid format"); + LIBSSH2_FREE(session, key); + goto out; + } + } + else { + ret = _libssh2_error(session, LIBSSH2_ERROR_KEYFILE_AUTH_FAILED, + "bcrypted without passphrase"); + LIBSSH2_FREE(session, key); + goto out; + } + + /* Set up decryption */ + blocksize = method->blocksize; + + key_part = LIBSSH2_CALLOC(session, keylen); + if(key_part == NULL) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Could not alloc key part"); + goto out; + } + + iv_part = LIBSSH2_CALLOC(session, ivlen); + if(iv_part == NULL) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Could not alloc iv part"); + goto out; + } + + memcpy(key_part, key, keylen); + memcpy(iv_part, key + keylen, ivlen); + + /* Initialize the decryption */ + if(method->init(session, method, iv_part, &free_iv, key_part, + &free_secret, 0, &abstract)) { + ret = LIBSSH2_ERROR_DECRYPT; + goto out; + } + + /* Do the actual decryption */ + if((decrypted.len % blocksize) != 0) { + method->dtor(session, &abstract); + ret = LIBSSH2_ERROR_DECRYPT; + goto out; + } + + while((size_t)len_decrypted <= decrypted.len - blocksize) { + if(method->crypt(session, decrypted.data + len_decrypted, + blocksize, + &abstract)) { + ret = LIBSSH2_ERROR_DECRYPT; + method->dtor(session, &abstract); + goto out; + } + + len_decrypted += blocksize; + } + + /* No padding */ + + method->dtor(session, &abstract); + } + + /* Check random bytes match */ + + if(_libssh2_get_u32(&decrypted, &check1) != 0 || + _libssh2_get_u32(&decrypted, &check2) != 0 || + check1 != check2) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Private key unpack failed (correct password?)"); + ret = LIBSSH2_ERROR_KEYFILE_AUTH_FAILED; + goto out; + } + + if(decrypted_buf != NULL) { + /* copy data to out-going buffer */ + struct string_buf *out_buf = _libssh2_string_buf_new(session); + if(!out_buf) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for " + "decrypted struct"); + goto out; + } + + out_buf->data = LIBSSH2_CALLOC(session, decrypted.len); + if(out_buf->data == NULL) { + ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Unable to allocate memory for " + "decrypted struct"); + _libssh2_string_buf_free(session, out_buf); + goto out; + } + memcpy(out_buf->data, decrypted.data, decrypted.len); + out_buf->dataptr = out_buf->data + + (decrypted.dataptr - decrypted.data); + out_buf->len = decrypted.len; + + *decrypted_buf = out_buf; + } + +out: + + /* Clean up */ + if(key) { + _libssh2_explicit_zero(key, total_len); + LIBSSH2_FREE(session, key); + } + if(key_part) { + _libssh2_explicit_zero(key_part, keylen); + LIBSSH2_FREE(session, key_part); + } + if(iv_part) { + _libssh2_explicit_zero(iv_part, ivlen); + LIBSSH2_FREE(session, iv_part); + } + if(f) { + _libssh2_explicit_zero(f, f_len); + LIBSSH2_FREE(session, f); + } + + return ret; +} + +int +_libssh2_openssh_pem_parse(LIBSSH2_SESSION * session, + const unsigned char *passphrase, + FILE * fp, struct string_buf **decrypted_buf) +{ + char line[LINE_SIZE]; + char *b64data = NULL; + unsigned int b64datalen = 0; + int ret = 0; + + /* read file */ + + do { + *line = '\0'; + + if(readline(line, LINE_SIZE, fp)) { + return -1; + } + } + while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); + + if(readline(line, LINE_SIZE, fp)) { + return -1; + } + + do { + if(*line) { + char *tmp; + size_t linelen; + + linelen = strlen(line); + tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen); + if(!tmp) { + ret = -1; + goto out; + } + memcpy(tmp + b64datalen, line, linelen); + b64data = tmp; + b64datalen += linelen; + } + + *line = '\0'; + + if(readline(line, LINE_SIZE, fp)) { + ret = -1; + goto out; + } + } while(strcmp(line, OPENSSH_HEADER_END) != 0); + + if(!b64data) { + return -1; + } + + ret = _libssh2_openssh_pem_parse_data(session, + passphrase, + (const char *)b64data, + (size_t)b64datalen, + decrypted_buf); + + if(b64data) { + _libssh2_explicit_zero(b64data, b64datalen); + LIBSSH2_FREE(session, b64data); + } + +out: + + return ret; +} + +int +_libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session, + const unsigned char *passphrase, + const char *filedata, size_t filedata_len, + struct string_buf **decrypted_buf) +{ + char line[LINE_SIZE]; + char *b64data = NULL; + unsigned int b64datalen = 0; + size_t off = 0; + int ret; + + if(filedata == NULL || filedata_len <= 0) { + return -1; + } + + do { + + *line = '\0'; + + if(off >= filedata_len) { + return -1; + } + + if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { + return -1; + } + } + while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); + + *line = '\0'; + + do { + if (*line) { + char *tmp; + size_t linelen; + + linelen = strlen(line); + tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen); + if(!tmp) { + ret = -1; + goto out; + } + memcpy(tmp + b64datalen, line, linelen); + b64data = tmp; + b64datalen += linelen; + } + + *line = '\0'; + + if(off >= filedata_len) { + ret = -1; + goto out; + } + + if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { + ret = -1; + goto out; + } + } while(strcmp(line, OPENSSH_HEADER_END) != 0); + + if(!b64data) { + return -1; + } + + ret = _libssh2_openssh_pem_parse_data(session, passphrase, b64data, + b64datalen, decrypted_buf); + +out: + if(b64data) { + _libssh2_explicit_zero(b64data, b64datalen); + LIBSSH2_FREE(session, b64data); + } + return ret; + +} + static int read_asn1_length(const unsigned char *data, unsigned int datalen, unsigned int *len) @@ -233,27 +810,28 @@ read_asn1_length(const unsigned char *data, unsigned int lenlen; int nextpos; - if (datalen < 1) { + if(datalen < 1) { return -1; } *len = data[0]; - if (*len >= 0x80) { + if(*len >= 0x80) { lenlen = *len & 0x7F; *len = data[1]; - if (1 + lenlen > datalen) { + if(1 + lenlen > datalen) { return -1; } - if (lenlen > 1) { + if(lenlen > 1) { *len <<= 8; *len |= data[2]; } - } else { + } + else { lenlen = 0; } nextpos = 1 + lenlen; - if (lenlen > 2 || 1 + lenlen + *len > datalen) { + if(lenlen > 2 || 1 + lenlen + *len > datalen) { return -1; } @@ -266,11 +844,11 @@ _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen) unsigned int len; int lenlen; - if (*datalen < 1) { + if(*datalen < 1) { return -1; } - if ((*data)[0] != '\x30') { + if((*data)[0] != '\x30') { return -1; } @@ -278,7 +856,7 @@ _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen) (*datalen)--; lenlen = read_asn1_length(*data, *datalen, &len); - if (lenlen < 0 || lenlen + len != *datalen) { + if(lenlen < 0 || lenlen + len != *datalen) { return -1; } @@ -295,11 +873,11 @@ _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen, unsigned int len; int lenlen; - if (*datalen < 1) { + if(*datalen < 1) { return -1; } - if ((*data)[0] != '\x02') { + if((*data)[0] != '\x02') { return -1; } @@ -307,7 +885,7 @@ _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen, (*datalen)--; lenlen = read_asn1_length(*data, *datalen, &len); - if (lenlen < 0 || lenlen + len > *datalen) { + if(lenlen < 0 || lenlen + len > *datalen) { return -1; } diff --git a/libssh2/src/publickey.c b/libssh2/src/publickey.c index bfee0a842..f26c6327d 100644 --- a/libssh2/src/publickey.c +++ b/libssh2/src/publickey.c @@ -60,7 +60,7 @@ static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_response_codes[] = {LIBSSH2_PUBLICKEY_RESPONSE_STATUS, "status", sizeof("status") - 1}, {LIBSSH2_PUBLICKEY_RESPONSE_VERSION, "version", sizeof("version") - 1}, {LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY, "publickey", - sizeof("publickey") - 1} , + sizeof("publickey") - 1}, {0, NULL, 0} }; @@ -78,13 +78,13 @@ static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_response_codes[] = #define LIBSSH2_PUBLICKEY_STATUS_CODE_MAX 8 static const LIBSSH2_PUBLICKEY_CODE_LIST publickey_status_codes[] = { - {LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1} , + {LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1}, {LIBSSH2_PUBLICKEY_ACCESS_DENIED, "access denied", sizeof("access denied") - 1}, {LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED, "storage exceeded", - sizeof("storage exceeded") - 1} , + sizeof("storage exceeded") - 1}, {LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED, "version not supported", - sizeof("version not supported") - 1} , + sizeof("version not supported") - 1}, {LIBSSH2_PUBLICKEY_KEY_NOT_FOUND, "key not found", sizeof("key not found") - 1}, {LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED, "key not supported", @@ -110,13 +110,14 @@ publickey_status_error(const LIBSSH2_PUBLICKEY *pkey, const char *msg; /* GENERAL_FAILURE got remapped between version 1 and 2 */ - if (status == 6 && pkey && pkey->version == 1) { + if(status == 6 && pkey && pkey->version == 1) { status = 7; } - if (status < 0 || status > LIBSSH2_PUBLICKEY_STATUS_CODE_MAX) { + if(status < 0 || status > LIBSSH2_PUBLICKEY_STATUS_CODE_MAX) { msg = "unknown"; - } else { + } + else { msg = publickey_status_codes[status].name; } @@ -139,11 +140,12 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey, *data = NULL; /* default to nothing returned */ *data_len = 0; - if (pkey->receive_state == libssh2_NB_state_idle) { + if(pkey->receive_state == libssh2_NB_state_idle) { rc = _libssh2_channel_read(channel, 0, (char *) buffer, 4); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc != 4) { + } + else if(rc != 4) { return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid response from publickey subsystem"); } @@ -151,7 +153,7 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey, pkey->receive_packet_len = _libssh2_ntohu32(buffer); pkey->receive_packet = LIBSSH2_ALLOC(session, pkey->receive_packet_len); - if (!pkey->receive_packet) { + if(!pkey->receive_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate publickey response " "buffer"); @@ -160,12 +162,13 @@ publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey, pkey->receive_state = libssh2_NB_state_sent; } - if (pkey->receive_state == libssh2_NB_state_sent) { + if(pkey->receive_state == libssh2_NB_state_sent) { rc = _libssh2_channel_read(channel, 0, (char *) pkey->receive_packet, pkey->receive_packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc != (int)pkey->receive_packet_len) { + } + else if(rc != (int)pkey->receive_packet_len) { LIBSSH2_FREE(session, pkey->receive_packet); pkey->receive_packet = NULL; pkey->receive_state = libssh2_NB_state_idle; @@ -195,20 +198,20 @@ publickey_response_id(unsigned char **pdata, size_t data_len) unsigned char *data = *pdata; const LIBSSH2_PUBLICKEY_CODE_LIST *codes = publickey_response_codes; - if (data_len < 4) { + if(data_len < 4) { /* Malformed response */ return -1; } response_len = _libssh2_ntohu32(data); data += 4; data_len -= 4; - if (data_len < response_len) { + if(data_len < response_len) { /* Malformed response */ return -1; } - while (codes->name) { - if ((unsigned long)codes->name_len == response_len && + while(codes->name) { + if((unsigned long)codes->name_len == response_len && strncmp(codes->name, (char *) data, response_len) == 0) { *pdata = data + response_len; return codes->code; @@ -231,28 +234,41 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey) size_t data_len; int response; - while (1) { + while(1) { int rc = publickey_packet_receive(pkey, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from " "publickey subsystem"); } + if(data_len < 4) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Publickey response too small"); + } + s = data; response = publickey_response_id(&s, data_len); - switch (response) { + switch(response) { case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: /* Error, or processing complete */ { - unsigned long status = _libssh2_ntohu32(s); + unsigned long status = 0; + + if(data_len < 8) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Publickey response too small"); + } + + status = _libssh2_ntohu32(s); LIBSSH2_FREE(session, data); - if (status == LIBSSH2_PUBLICKEY_SUCCESS) + if(status == LIBSSH2_PUBLICKEY_SUCCESS) return 0; publickey_status_error(pkey, session, status); @@ -260,7 +276,7 @@ publickey_response_success(LIBSSH2_PUBLICKEY * pkey) } default: LIBSSH2_FREE(session, data); - if (response < 0) { + if(response < 0) { return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid publickey subsystem response"); @@ -289,7 +305,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) int response; int rc; - if (session->pkeyInit_state == libssh2_NB_state_idle) { + if(session->pkeyInit_state == libssh2_NB_state_idle) { session->pkeyInit_data = NULL; session->pkeyInit_pkey = NULL; session->pkeyInit_channel = NULL; @@ -300,7 +316,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) session->pkeyInit_state = libssh2_NB_state_allocated; } - if (session->pkeyInit_state == libssh2_NB_state_allocated) { + if(session->pkeyInit_state == libssh2_NB_state_allocated) { session->pkeyInit_channel = _libssh2_channel_open(session, "session", @@ -308,8 +324,8 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); - if (!session->pkeyInit_channel) { - if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) + if(!session->pkeyInit_channel) { + if(libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) /* The error state is already set, so leave it */ return NULL; _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, @@ -320,17 +336,18 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) session->pkeyInit_state = libssh2_NB_state_sent; } - if (session->pkeyInit_state == libssh2_NB_state_sent) { + if(session->pkeyInit_state == libssh2_NB_state_sent) { rc = _libssh2_channel_process_startup(session->pkeyInit_channel, "subsystem", sizeof("subsystem") - 1, "publickey", sizeof("publickey") - 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting publickey subsystem"); return NULL; - } else if (rc) { + } + else if(rc) { _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Unable to request publickey subsystem"); goto err_exit; @@ -339,11 +356,11 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) session->pkeyInit_state = libssh2_NB_state_sent1; } - if (session->pkeyInit_state == libssh2_NB_state_sent1) { + if(session->pkeyInit_state == libssh2_NB_state_sent1) { unsigned char *s; rc = _libssh2_channel_extended_data(session->pkeyInit_channel, - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); - if (rc == LIBSSH2_ERROR_EAGAIN) { + LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting publickey subsystem"); return NULL; @@ -351,7 +368,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) session->pkeyInit_pkey = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_PUBLICKEY)); - if (!session->pkeyInit_pkey) { + if(!session->pkeyInit_pkey) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a new publickey structure"); goto err_exit; @@ -377,15 +394,16 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) session->pkeyInit_state = libssh2_NB_state_sent2; } - if (session->pkeyInit_state == libssh2_NB_state_sent2) { + if(session->pkeyInit_state == libssh2_NB_state_sent2) { rc = _libssh2_channel_write(session->pkeyInit_channel, 0, session->pkeyInit_buffer, 19 - session->pkeyInit_buffer_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending publickey version packet"); return NULL; - } else if (rc < 0) { + } + else if(rc < 0) { _libssh2_error(session, rc, "Unable to send publickey version packet"); goto err_exit; @@ -400,18 +418,19 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) session->pkeyInit_state = libssh2_NB_state_sent3; } - if (session->pkeyInit_state == libssh2_NB_state_sent3) { - while (1) { + if(session->pkeyInit_state == libssh2_NB_state_sent3) { + while(1) { unsigned char *s; rc = publickey_packet_receive(session->pkeyInit_pkey, &session->pkeyInit_data, &session->pkeyInit_data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response from " "publickey subsystem"); return NULL; - } else if (rc) { + } + else if(rc) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from " "publickey subsystem"); @@ -419,31 +438,62 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) } s = session->pkeyInit_data; - if ((response = + if((response = publickey_response_id(&s, session->pkeyInit_data_len)) < 0) { _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Invalid publickey subsystem response code"); goto err_exit; } - switch (response) { + if(session->pkeyInit_data_len < 4) { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Public key init data too small"); + goto err_exit; + } + + switch(response) { case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: /* Error */ { unsigned long status, descr_len, lang_len; - status = _libssh2_ntohu32(s); - s += 4; - descr_len = _libssh2_ntohu32(s); - s += 4; - /* description starts here */ - s += descr_len; - lang_len = _libssh2_ntohu32(s); - s += 4; - /* lang starts here */ - s += lang_len; + if(session->pkeyInit_data_len >= 8) { + status = _libssh2_ntohu32(s); + s += 4; + descr_len = _libssh2_ntohu32(s); + s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Public key init data too small"); + goto err_exit; + } - if (s > + if(s + descr_len + 4 <= + session->pkeyInit_data + session->pkeyInit_data_len) { + /* description starts here */ + s += descr_len; + lang_len = _libssh2_ntohu32(s); + s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Public key init data too small"); + goto err_exit; + } + + if(s + lang_len <= + session->pkeyInit_data + session->pkeyInit_data_len) { + /* lang starts here */ + s += lang_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Public key init data too small"); + goto err_exit; + } + + if(s > session->pkeyInit_data + session->pkeyInit_data_len) { _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, @@ -459,10 +509,11 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) case LIBSSH2_PUBLICKEY_RESPONSE_VERSION: /* What we want */ session->pkeyInit_pkey->version = _libssh2_ntohu32(s); - if (session->pkeyInit_pkey->version > + if(session->pkeyInit_pkey->version > LIBSSH2_PUBLICKEY_VERSION) { _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Truncate remote publickey version from %lu", + "Truncate remote publickey version " + "from %lu", session->pkeyInit_pkey->version); session->pkeyInit_pkey->version = LIBSSH2_PUBLICKEY_VERSION; @@ -489,19 +540,19 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) /* Never reached except by direct goto */ err_exit: session->pkeyInit_state = libssh2_NB_state_sent4; - if (session->pkeyInit_channel) { + if(session->pkeyInit_channel) { rc = _libssh2_channel_close(session->pkeyInit_channel); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block closing channel"); return NULL; } } - if (session->pkeyInit_pkey) { + if(session->pkeyInit_pkey) { LIBSSH2_FREE(session, session->pkeyInit_pkey); session->pkeyInit_pkey = NULL; } - if (session->pkeyInit_data) { + if(session->pkeyInit_data) { LIBSSH2_FREE(session, session->pkeyInit_data); session->pkeyInit_data = NULL; } @@ -553,16 +604,16 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, channel = pkey->channel; session = channel->session; - if (pkey->add_state == libssh2_NB_state_idle) { + if(pkey->add_state == libssh2_NB_state_idle) { pkey->add_packet = NULL; _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, "Adding %s publickey", name); - if (pkey->version == 1) { + if(pkey->version == 1) { for(i = 0; i < num_attrs; i++) { /* Search for a comment attribute */ - if (attrs[i].name_len == (sizeof("comment") - 1) && + if(attrs[i].name_len == (sizeof("comment") - 1) && strncmp(attrs[i].name, "comment", sizeof("comment") - 1) == 0) { comment = (unsigned char *) attrs[i].value; @@ -571,7 +622,8 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, } } packet_len += 4 + comment_len; - } else { + } + else { packet_len += 5; /* overwrite(1) + attribute_count(4) */ for(i = 0; i < num_attrs; i++) { packet_len += 9 + attrs[i].name_len + attrs[i].value_len; @@ -580,7 +632,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, } pkey->add_packet = LIBSSH2_ALLOC(session, packet_len); - if (!pkey->add_packet) { + if(!pkey->add_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "publickey \"add\" packet"); @@ -593,10 +645,10 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, pkey->add_s += 4; memcpy(pkey->add_s, "add", sizeof("add") - 1); pkey->add_s += sizeof("add") - 1; - if (pkey->version == 1) { + if(pkey->version == 1) { _libssh2_htonu32(pkey->add_s, comment_len); pkey->add_s += 4; - if (comment) { + if(comment) { memcpy(pkey->add_s, comment, comment_len); pkey->add_s += comment_len; } @@ -609,7 +661,8 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, pkey->add_s += 4; memcpy(pkey->add_s, blob, blob_len); pkey->add_s += blob_len; - } else { + } + else { /* Version == 2 */ _libssh2_htonu32(pkey->add_s, name_len); @@ -644,12 +697,13 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, pkey->add_state = libssh2_NB_state_created; } - if (pkey->add_state == libssh2_NB_state_created) { + if(pkey->add_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, pkey->add_packet, (pkey->add_s - pkey->add_packet)); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if ((pkey->add_s - pkey->add_packet) != rc) { + } + else if((pkey->add_s - pkey->add_packet) != rc) { LIBSSH2_FREE(session, pkey->add_packet); pkey->add_packet = NULL; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, @@ -662,7 +716,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, } rc = publickey_response_success(pkey); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } @@ -693,11 +747,11 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey, channel = pkey->channel; session = channel->session; - if (pkey->remove_state == libssh2_NB_state_idle) { + if(pkey->remove_state == libssh2_NB_state_idle) { pkey->remove_packet = NULL; pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len); - if (!pkey->remove_packet) { + if(!pkey->remove_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "publickey \"remove\" packet"); @@ -727,12 +781,13 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey, pkey->remove_state = libssh2_NB_state_created; } - if (pkey->remove_state == libssh2_NB_state_created) { + if(pkey->remove_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, pkey->remove_packet, (pkey->remove_s - pkey->remove_packet)); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if ((pkey->remove_s - pkey->remove_packet) != rc) { + } + else if((pkey->remove_s - pkey->remove_packet) != rc) { LIBSSH2_FREE(session, pkey->remove_packet); pkey->remove_packet = NULL; pkey->remove_state = libssh2_NB_state_idle; @@ -746,7 +801,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey, } rc = publickey_response_success(pkey); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } @@ -776,7 +831,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, channel = pkey->channel; session = channel->session; - if (pkey->listFetch_state == libssh2_NB_state_idle) { + if(pkey->listFetch_state == libssh2_NB_state_idle) { pkey->listFetch_data = NULL; pkey->listFetch_s = pkey->listFetch_buffer; @@ -793,14 +848,15 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, pkey->listFetch_state = libssh2_NB_state_created; } - if (pkey->listFetch_state == libssh2_NB_state_created) { + if(pkey->listFetch_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, pkey->listFetch_buffer, (pkey->listFetch_s - pkey->listFetch_buffer)); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) { + } + else if((pkey->listFetch_s - pkey->listFetch_buffer) != rc) { pkey->listFetch_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send publickey list packet"); @@ -809,12 +865,13 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, pkey->listFetch_state = libssh2_NB_state_sent; } - while (1) { + while(1) { rc = publickey_packet_receive(pkey, &pkey->listFetch_data, &pkey->listFetch_data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (rc) { + } + else if(rc) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for response from " "publickey subsystem"); @@ -822,7 +879,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, } pkey->listFetch_s = pkey->listFetch_data; - if ((response = + if((response = publickey_response_id(&pkey->listFetch_s, pkey->listFetch_data_len)) < 0) { _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, @@ -830,31 +887,57 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, goto err_exit; } - switch (response) { + switch(response) { case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: /* Error, or processing complete */ { unsigned long status, descr_len, lang_len; - status = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - descr_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - /* description starts at pkey->listFetch_s */ - pkey->listFetch_s += descr_len; - lang_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - /* lang starts at pkey->listFetch_s */ - pkey->listFetch_s += lang_len; + if(pkey->listFetch_s + 8 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + status = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + descr_len = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } - if (pkey->listFetch_s > + if(pkey->listFetch_s + descr_len + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + /* description starts at pkey->listFetch_s */ + pkey->listFetch_s += descr_len; + lang_len = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + lang_len <= + pkey->listFetch_data + pkey->listFetch_data_len) { + /* lang starts at pkey->listFetch_s */ + pkey->listFetch_s += lang_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s > pkey->listFetch_data + pkey->listFetch_data_len) { _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, "Malformed publickey subsystem packet"); goto err_exit; } - if (status == LIBSSH2_PUBLICKEY_SUCCESS) { + if(status == LIBSSH2_PUBLICKEY_SUCCESS) { LIBSSH2_FREE(session, pkey->listFetch_data); pkey->listFetch_data = NULL; *pkey_list = list; @@ -868,7 +951,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, } case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY: /* What we want */ - if (keys >= max_keys) { + if(keys >= max_keys) { libssh2_publickey_list *newlist; /* Grow the key list if necessary */ max_keys += 8; @@ -876,7 +959,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, LIBSSH2_REALLOC(session, list, (max_keys + 1) * sizeof(libssh2_publickey_list)); - if (!newlist) { + if(!newlist) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "publickey list"); @@ -884,17 +967,26 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, } list = newlist; } - if (pkey->version == 1) { + if(pkey->version == 1) { unsigned long comment_len; - comment_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - if (comment_len) { + if(pkey->listFetch_s + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + comment_len = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(comment_len) { list[keys].num_attrs = 1; list[keys].attrs = LIBSSH2_ALLOC(session, sizeof(libssh2_publickey_attribute)); - if (!list[keys].attrs) { + if(!list[keys].attrs) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "publickey attributes"); @@ -907,57 +999,184 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, list[keys].attrs[0].mandatory = 0; pkey->listFetch_s += comment_len; - } else { + } + else { list[keys].num_attrs = 0; list[keys].attrs = NULL; } - list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].name = pkey->listFetch_s; - pkey->listFetch_s += list[keys].name_len; - list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].blob = pkey->listFetch_s; - pkey->listFetch_s += list[keys].blob_len; - } else { + + if(pkey->listFetch_s + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + list[keys].name_len <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].name = pkey->listFetch_s; + pkey->listFetch_s += list[keys].name_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + list[keys].blob_len <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].blob = pkey->listFetch_s; + pkey->listFetch_s += list[keys].blob_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + } + else { /* Version == 2 */ - list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].name = pkey->listFetch_s; - pkey->listFetch_s += list[keys].name_len; - list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].blob = pkey->listFetch_s; - pkey->listFetch_s += list[keys].blob_len; - list[keys].num_attrs = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - if (list[keys].num_attrs) { + + if(pkey->listFetch_s + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].name_len = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + list[keys].name_len <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].name = pkey->listFetch_s; + pkey->listFetch_s += list[keys].name_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].blob_len = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + list[keys].blob_len <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].blob = pkey->listFetch_s; + pkey->listFetch_s += list[keys].blob_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].num_attrs = _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(list[keys].num_attrs) { list[keys].attrs = LIBSSH2_ALLOC(session, list[keys].num_attrs * sizeof(libssh2_publickey_attribute)); - if (!list[keys].attrs) { + if(!list[keys].attrs) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "publickey attributes"); goto err_exit; } for(i = 0; i < list[keys].num_attrs; i++) { - list[keys].attrs[i].name_len = - _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].attrs[i].name = (char *) pkey->listFetch_s; - pkey->listFetch_s += list[keys].attrs[i].name_len; - list[keys].attrs[i].value_len = - _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - list[keys].attrs[i].value = (char *) pkey->listFetch_s; - pkey->listFetch_s += list[keys].attrs[i].value_len; + if(pkey->listFetch_s + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].attrs[i].name_len = + _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, + LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + list[keys].attrs[i].name_len <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].attrs[i].name = + (char *) pkey->listFetch_s; + pkey->listFetch_s += list[keys].attrs[i].name_len; + } + else { + _libssh2_error(session, + LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + 4 <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].attrs[i].value_len = + _libssh2_ntohu32(pkey->listFetch_s); + pkey->listFetch_s += 4; + } + else { + _libssh2_error(session, + LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + + if(pkey->listFetch_s + + list[keys].attrs[i].value_len <= + pkey->listFetch_data + pkey->listFetch_data_len) { + list[keys].attrs[i].value = + (char *) pkey->listFetch_s; + pkey->listFetch_s += list[keys].attrs[i].value_len; + } + else { + _libssh2_error(session, + LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } /* actually an ignored value */ list[keys].attrs[i].mandatory = 0; } - } else { + } + else { list[keys].attrs = NULL; } } @@ -979,11 +1198,11 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, /* Only reached via explicit goto */ err_exit: - if (pkey->listFetch_data) { + if(pkey->listFetch_data) { LIBSSH2_FREE(session, pkey->listFetch_data); pkey->listFetch_data = NULL; } - if (list) { + if(list) { libssh2_publickey_list_free(pkey, list); } pkey->listFetch_state = libssh2_NB_state_idle; @@ -1005,8 +1224,8 @@ libssh2_publickey_list_free(LIBSSH2_PUBLICKEY * pkey, session = pkey->channel->session; - while (p->packet) { - if (p->attrs) { + while(p->packet) { + if(p->attrs) { LIBSSH2_FREE(session, p->attrs); } LIBSSH2_FREE(session, p->packet); @@ -1033,25 +1252,25 @@ libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey) /* * Make sure all memory used in the state variables are free */ - if (pkey->receive_packet) { + if(pkey->receive_packet) { LIBSSH2_FREE(session, pkey->receive_packet); pkey->receive_packet = NULL; } - if (pkey->add_packet) { + if(pkey->add_packet) { LIBSSH2_FREE(session, pkey->add_packet); pkey->add_packet = NULL; } - if (pkey->remove_packet) { + if(pkey->remove_packet) { LIBSSH2_FREE(session, pkey->remove_packet); pkey->remove_packet = NULL; } - if (pkey->listFetch_data) { + if(pkey->listFetch_data) { LIBSSH2_FREE(session, pkey->listFetch_data); pkey->listFetch_data = NULL; } rc = _libssh2_channel_free(pkey->channel); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; LIBSSH2_FREE(session, pkey); diff --git a/libssh2/src/scp.c b/libssh2/src/scp.c index 22778dd38..a9d2db535 100644 --- a/libssh2/src/scp.c +++ b/libssh2/src/scp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010 by Daniel Stenberg +/* Copyright (c) 2009-2019 by Daniel Stenberg * Copyright (c) 2004-2008, Sara Golemon * All rights reserved. * @@ -141,9 +141,9 @@ shell_quotearg(const char *path, unsigned char *buf, endp = &buf[bufsize]; src = path; dst = buf; - while (*src && dst < endp - 1) { + while(*src && dst < endp - 1) { - switch (*src) { + switch(*src) { /* * Special handling for apostrophe. * An apostrophe is always written in quotation marks, e.g. @@ -151,16 +151,16 @@ shell_quotearg(const char *path, unsigned char *buf, */ case '\'': - switch (state) { + switch(state) { case UQSTRING: /* Unquoted string */ - if (dst+1 >= endp) + if(dst + 1 >= endp) return 0; *dst++ = '"'; break; case QSTRING: /* Continue quoted string */ break; case SQSTRING: /* Close single quoted string */ - if (dst+2 >= endp) + if(dst + 2 >= endp) return 0; *dst++ = '\''; *dst++ = '"'; @@ -179,20 +179,20 @@ shell_quotearg(const char *path, unsigned char *buf, */ case '!': - switch (state) { + switch(state) { case UQSTRING: - if (dst+1 >= endp) + if(dst + 1 >= endp) return 0; *dst++ = '\\'; break; case QSTRING: - if (dst+2 >= endp) + if(dst + 2 >= endp) return 0; *dst++ = '"'; /* Closing quotation mark */ *dst++ = '\\'; break; case SQSTRING: /* Close single quoted string */ - if (dst+2 >= endp) + if(dst + 2 >= endp) return 0; *dst++ = '\''; *dst++ = '\\'; @@ -208,14 +208,14 @@ shell_quotearg(const char *path, unsigned char *buf, */ default: - switch (state) { + switch(state) { case UQSTRING: - if (dst+1 >= endp) + if(dst + 1 >= endp) return 0; *dst++ = '\''; break; case QSTRING: - if (dst+2 >= endp) + if(dst + 2 >= endp) return 0; *dst++ = '"'; /* Closing quotation mark */ *dst++ = '\''; @@ -229,21 +229,21 @@ shell_quotearg(const char *path, unsigned char *buf, break; } - if (dst+1 >= endp) + if(dst + 1 >= endp) return 0; *dst++ = *src++; } - switch (state) { + switch(state) { case UQSTRING: break; case QSTRING: /* Close quoted string */ - if (dst+1 >= endp) + if(dst + 1 >= endp) return 0; *dst++ = '"'; break; case SQSTRING: /* Close single quoted string */ - if (dst+1 >= endp) + if(dst + 1 >= endp) return 0; *dst++ = '\''; break; @@ -251,7 +251,7 @@ shell_quotearg(const char *path, unsigned char *buf, break; } - if (dst+1 >= endp) + if(dst + 1 >= endp) return 0; *dst = '\0'; @@ -275,7 +275,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) int tmp_err_code; const char *tmp_err_msg; - if (session->scpRecv_state == libssh2_NB_state_idle) { + if(session->scpRecv_state == libssh2_NB_state_idle) { session->scpRecv_mode = 0; session->scpRecv_size = 0; session->scpRecv_mtime = 0; @@ -287,7 +287,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_command = LIBSSH2_ALLOC(session, session->scpRecv_command_len); - if (!session->scpRecv_command) { + if(!session->scpRecv_command) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a command buffer for " "SCP session"); @@ -303,8 +303,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) &session->scpRecv_command[cmd_len], session->scpRecv_command_len - cmd_len); - session->scpRecv_command[cmd_len] = '\0'; - session->scpRecv_command_len = cmd_len + 1; + /* the command to exec should _not_ be NUL-terminated */ + session->scpRecv_command_len = cmd_len; _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Opening channel for SCP receive"); @@ -312,7 +312,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_state = libssh2_NB_state_created; } - if (session->scpRecv_state == libssh2_NB_state_created) { + if(session->scpRecv_state == libssh2_NB_state_created) { /* Allocate a channel */ session->scpRecv_channel = _libssh2_channel_open(session, "session", @@ -320,8 +320,8 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); - if (!session->scpRecv_channel) { - if (libssh2_session_last_errno(session) != + if(!session->scpRecv_channel) { + if(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { LIBSSH2_FREE(session, session->scpRecv_command); session->scpRecv_command = NULL; @@ -337,17 +337,18 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_state = libssh2_NB_state_sent; } - if (session->scpRecv_state == libssh2_NB_state_sent) { + if(session->scpRecv_state == libssh2_NB_state_sent) { /* Request SCP for the desired file */ rc = _libssh2_channel_process_startup(session->scpRecv_channel, "exec", sizeof("exec") - 1, - (char *) session->scpRecv_command, + (char *)session->scpRecv_command, session->scpRecv_command_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting SCP startup"); return NULL; - } else if (rc) { + } + else if(rc) { LIBSSH2_FREE(session, session->scpRecv_command); session->scpRecv_command = NULL; goto scp_recv_error; @@ -362,14 +363,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_state = libssh2_NB_state_sent1; } - if (session->scpRecv_state == libssh2_NB_state_sent1) { + if(session->scpRecv_state == libssh2_NB_state_sent1) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending initial wakeup"); return NULL; - } else if (rc != 1) { + } + else if(rc != 1) { goto scp_recv_error; } @@ -379,23 +381,23 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_state = libssh2_NB_state_sent2; } - if ((session->scpRecv_state == libssh2_NB_state_sent2) + if((session->scpRecv_state == libssh2_NB_state_sent2) || (session->scpRecv_state == libssh2_NB_state_sent3)) { - while (sb && (session->scpRecv_response_len < + while(sb && (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN)) { unsigned char *s, *p; - if (session->scpRecv_state == libssh2_NB_state_sent2) { + if(session->scpRecv_state == libssh2_NB_state_sent2) { rc = _libssh2_channel_read(session->scpRecv_channel, 0, (char *) session-> scpRecv_response + session->scpRecv_response_len, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for SCP response"); return NULL; } - else if (rc < 0) { + else if(rc < 0) { /* error, give up */ _libssh2_error(session, rc, "Failed reading SCP response"); goto scp_recv_error; @@ -405,7 +407,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_response_len++; - if (session->scpRecv_response[0] != 'T') { + if(session->scpRecv_response[0] != 'T') { size_t err_len; char *err_msg; @@ -419,7 +421,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) _libssh2_channel_packet_data_len(session-> scpRecv_channel, 0); err_msg = LIBSSH2_ALLOC(session, err_len + 1); - if (!err_msg) { + if(!err_msg) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Failed to get memory "); goto scp_recv_error; @@ -431,7 +433,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) /* If it failed for any reason, we ignore it anyway. */ /* zero terminate the error */ - err_msg[err_len]=0; + err_msg[err_len] = 0; _libssh2_debug(session, LIBSSH2_TRACE_SCP, "got %02x %s", session->scpRecv_response[0], @@ -444,7 +446,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) goto scp_recv_error; } - if ((session->scpRecv_response_len > 1) && + if((session->scpRecv_response_len > 1) && ((session-> scpRecv_response[session->scpRecv_response_len - 1] < '0') @@ -465,15 +467,16 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) goto scp_recv_error; } - if ((session->scpRecv_response_len < 9) + if((session->scpRecv_response_len < 9) || (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\n')) { - if (session->scpRecv_response_len == + if(session->scpRecv_response_len == LIBSSH2_SCP_RESPONSE_BUFLEN) { /* You had your chance */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unterminated response from SCP server"); + "Unterminated response from " + "SCP server"); goto scp_recv_error; } /* Way too short to be an SCP response, or not done yet, @@ -483,7 +486,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) /* We're guaranteed not to go under response_len == 0 by the logic above */ - while ((session-> + while((session-> scpRecv_response[session->scpRecv_response_len - 1] == '\r') || (session-> @@ -493,18 +496,18 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_response[session->scpRecv_response_len] = '\0'; - if (session->scpRecv_response_len < 8) { + if(session->scpRecv_response_len < 8) { /* EOL came too soon */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, " - "too short" ); + "too short"); goto scp_recv_error; } s = session->scpRecv_response + 1; p = (unsigned char *) strchr((char *) s, ' '); - if (!p || ((p - s) <= 0)) { + if(!p || ((p - s) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server, " @@ -517,20 +520,22 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_mtime = strtol((char *) s, NULL, 10); s = (unsigned char *) strchr((char *) p, ' '); - if (!s || ((s - p) <= 0)) { + if(!s || ((s - p) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, malformed mtime.usec"); + "Invalid response from SCP server, " + "malformed mtime.usec"); goto scp_recv_error; } /* Ignore mtime.usec */ s++; p = (unsigned char *) strchr((char *) s, ' '); - if (!p || ((p - s) <= 0)) { + if(!p || ((p - s) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, too short or malformed"); + "Invalid response from SCP server, " + "too short or malformed"); goto scp_recv_error; } @@ -544,14 +549,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_state = libssh2_NB_state_sent3; } - if (session->scpRecv_state == libssh2_NB_state_sent3) { + if(session->scpRecv_state == libssh2_NB_state_sent3) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting to send SCP ACK"); return NULL; - } else if (rc != 1) { + } + else if(rc != 1) { goto scp_recv_error; } @@ -568,28 +574,28 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_state = libssh2_NB_state_sent4; } - if (session->scpRecv_state == libssh2_NB_state_sent4) { + if(session->scpRecv_state == libssh2_NB_state_sent4) { session->scpRecv_response_len = 0; session->scpRecv_state = libssh2_NB_state_sent5; } - if ((session->scpRecv_state == libssh2_NB_state_sent5) + if((session->scpRecv_state == libssh2_NB_state_sent5) || (session->scpRecv_state == libssh2_NB_state_sent6)) { - while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) { + while(session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) { char *s, *p, *e = NULL; - if (session->scpRecv_state == libssh2_NB_state_sent5) { + if(session->scpRecv_state == libssh2_NB_state_sent5) { rc = _libssh2_channel_read(session->scpRecv_channel, 0, (char *) session-> scpRecv_response + session->scpRecv_response_len, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for SCP response"); return NULL; } - else if (rc < 0) { + else if(rc < 0) { /* error, bail out*/ _libssh2_error(session, rc, "Failed reading SCP response"); goto scp_recv_error; @@ -599,13 +605,13 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_response_len++; - if (session->scpRecv_response[0] != 'C') { + if(session->scpRecv_response[0] != 'C') { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid response from SCP server"); goto scp_recv_error; } - if ((session->scpRecv_response_len > 1) && + if((session->scpRecv_response_len > 1) && (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\r') @@ -621,15 +627,16 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) goto scp_recv_error; } - if ((session->scpRecv_response_len < 7) + if((session->scpRecv_response_len < 7) || (session-> scpRecv_response[session->scpRecv_response_len - 1] != '\n')) { - if (session->scpRecv_response_len == + if(session->scpRecv_response_len == LIBSSH2_SCP_RESPONSE_BUFLEN) { /* You had your chance */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unterminated response from SCP server"); + "Unterminated response " + "from SCP server"); goto scp_recv_error; } /* Way too short to be an SCP response, or not done yet, @@ -639,7 +646,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) /* We're guaranteed not to go under response_len == 0 by the logic above */ - while ((session-> + while((session-> scpRecv_response[session->scpRecv_response_len - 1] == '\r') || (session-> @@ -650,20 +657,22 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_response[session->scpRecv_response_len] = '\0'; - if (session->scpRecv_response_len < 6) { + if(session->scpRecv_response_len < 6) { /* EOL came too soon */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, too short"); + "Invalid response from SCP server, " + "too short"); goto scp_recv_error; } s = (char *) session->scpRecv_response + 1; p = strchr(s, ' '); - if (!p || ((p - s) <= 0)) { + if(!p || ((p - s) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, malformed mode"); + "Invalid response from SCP server, " + "malformed mode"); goto scp_recv_error; } @@ -671,26 +680,29 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) /* Make sure we don't get fooled by leftover values */ session->scpRecv_mode = strtol(s, &e, 8); - if (e && *e) { + if(e && *e) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, invalid mode"); + "Invalid response from SCP server, " + "invalid mode"); goto scp_recv_error; } s = strchr(p, ' '); - if (!s || ((s - p) <= 0)) { + if(!s || ((s - p) <= 0)) { /* No spaces or space in the wrong spot */ _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, too short or malformed"); + "Invalid response from SCP server, " + "too short or malformed"); goto scp_recv_error; } *s = '\0'; /* Make sure we don't get fooled by leftover values */ session->scpRecv_size = scpsize_strtol(p, &e, 10); - if (e && *e) { + if(e && *e) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, invalid size"); + "Invalid response from SCP server, " + "invalid size"); goto scp_recv_error; } @@ -700,14 +712,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_state = libssh2_NB_state_sent6; } - if (session->scpRecv_state == libssh2_NB_state_sent6) { + if(session->scpRecv_state == libssh2_NB_state_sent6) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending SCP ACK"); return NULL; - } else if (rc != 1) { + } + else if(rc != 1) { goto scp_recv_error; } _libssh2_debug(session, LIBSSH2_TRACE_SCP, @@ -723,7 +736,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) session->scpRecv_state = libssh2_NB_state_sent7; } - if (sb) { + if(sb) { memset(sb, 0, sizeof(libssh2_struct_stat)); sb->st_mtime = session->scpRecv_mtime; @@ -747,7 +760,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) scp_recv_error: tmp_err_code = session->err_code; tmp_err_msg = session->err_msg; - while (libssh2_channel_free(session->scpRecv_channel) == + while(libssh2_channel_free(session->scpRecv_channel) == LIBSSH2_ERROR_EAGAIN); session->err_code = tmp_err_code; session->err_msg = tmp_err_msg; @@ -761,9 +774,9 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) * * DEPRECATED * - * Open a channel and request a remote file via SCP. This receives files larger - * than 2 GB, but is unable to report the proper size on platforms where the - * st_size member of struct stat is limited to 2 GB (e.g. windows). + * Open a channel and request a remote file via SCP. This receives files + * larger than 2 GB, but is unable to report the proper size on platforms + * where the st_size member of struct stat is limited to 2 GB (e.g. windows). * */ LIBSSH2_API LIBSSH2_CHANNEL * @@ -771,15 +784,17 @@ libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb) { LIBSSH2_CHANNEL *ptr; - /* scp_recv uses libssh2_struct_stat, so pass one if the caller gave us a struct to populate... */ + /* scp_recv uses libssh2_struct_stat, so pass one if the caller gave us a + struct to populate... */ libssh2_struct_stat sb_intl; libssh2_struct_stat *sb_ptr; + memset(&sb_intl, 0, sizeof(sb_intl)); sb_ptr = sb ? &sb_intl : NULL; BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb_ptr)); /* ...and populate the caller's with as much info as fits. */ - if (sb) { + if(sb) { memset(sb, 0, sizeof(struct stat)); sb->st_mtime = sb_intl.st_mtime; @@ -799,7 +814,8 @@ libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb) * */ LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_recv2(LIBSSH2_SESSION *session, const char *path, libssh2_struct_stat * sb) +libssh2_scp_recv2(LIBSSH2_SESSION *session, const char *path, + libssh2_struct_stat *sb) { LIBSSH2_CHANNEL *ptr; BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb)); @@ -821,7 +837,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, int tmp_err_code; const char *tmp_err_msg; - if (session->scpSend_state == libssh2_NB_state_idle) { + if(session->scpSend_state == libssh2_NB_state_idle) { session->scpSend_command_len = _libssh2_shell_quotedsize(path) + sizeof("scp -t ") + ((mtime || atime)?1:0); @@ -829,7 +845,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, session->scpSend_command = LIBSSH2_ALLOC(session, session->scpSend_command_len); - if (!session->scpSend_command) { + if(!session->scpSend_command) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a command buffer for " "SCP session"); @@ -845,8 +861,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, &session->scpSend_command[cmd_len], session->scpSend_command_len - cmd_len); - session->scpSend_command[cmd_len] = '\0'; - session->scpSend_command_len = cmd_len + 1; + /* the command to exec should _not_ be NUL-terminated */ + session->scpSend_command_len = cmd_len; _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Opening channel for SCP send"); @@ -855,13 +871,13 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, session->scpSend_state = libssh2_NB_state_created; } - if (session->scpSend_state == libssh2_NB_state_created) { + if(session->scpSend_state == libssh2_NB_state_created) { session->scpSend_channel = _libssh2_channel_open(session, "session", sizeof("session") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); - if (!session->scpSend_channel) { - if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { + if(!session->scpSend_channel) { + if(libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { /* previous call set libssh2_session_last_error(), pass it through */ LIBSSH2_FREE(session, session->scpSend_command); @@ -878,18 +894,18 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, session->scpSend_state = libssh2_NB_state_sent; } - if (session->scpSend_state == libssh2_NB_state_sent) { + if(session->scpSend_state == libssh2_NB_state_sent) { /* Request SCP for the desired file */ rc = _libssh2_channel_process_startup(session->scpSend_channel, "exec", sizeof("exec") - 1, - (char *) session->scpSend_command, + (char *)session->scpSend_command, session->scpSend_command_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting SCP startup"); return NULL; } - else if (rc) { + else if(rc) { /* previous call set libssh2_session_last_error(), pass it through */ LIBSSH2_FREE(session, session->scpSend_command); @@ -904,28 +920,28 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, session->scpSend_state = libssh2_NB_state_sent1; } - if (session->scpSend_state == libssh2_NB_state_sent1) { + if(session->scpSend_state == libssh2_NB_state_sent1) { /* Wait for ACK */ rc = _libssh2_channel_read(session->scpSend_channel, 0, (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response from remote"); return NULL; } - else if (rc < 0) { + else if(rc < 0) { _libssh2_error(session, rc, "SCP failure"); goto scp_send_error; } else if(!rc) /* remain in the same state */ goto scp_send_empty_channel; - else if (session->scpSend_response[0] != 0) { + else if(session->scpSend_response[0] != 0) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote"); goto scp_send_error; } - if (mtime || atime) { + if(mtime || atime) { /* Send mtime and atime to be used for file */ session->scpSend_response_len = snprintf((char *) session->scpSend_response, @@ -939,16 +955,17 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, } /* Send mtime and atime to be used for file */ - if (mtime || atime) { - if (session->scpSend_state == libssh2_NB_state_sent2) { + if(mtime || atime) { + if(session->scpSend_state == libssh2_NB_state_sent2) { rc = _libssh2_channel_write(session->scpSend_channel, 0, session->scpSend_response, session->scpSend_response_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending time data for SCP file"); return NULL; - } else if (rc != (int)session->scpSend_response_len) { + } + else if(rc != (int)session->scpSend_response_len) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send time data for SCP file"); goto scp_send_error; @@ -957,23 +974,23 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, session->scpSend_state = libssh2_NB_state_sent3; } - if (session->scpSend_state == libssh2_NB_state_sent3) { + if(session->scpSend_state == libssh2_NB_state_sent3) { /* Wait for ACK */ rc = _libssh2_channel_read(session->scpSend_channel, 0, (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response"); return NULL; } - else if (rc < 0) { + else if(rc < 0) { _libssh2_error(session, rc, "SCP failure"); goto scp_send_error; } else if(!rc) /* remain in the same state */ goto scp_send_empty_channel; - else if (session->scpSend_response[0] != 0) { + else if(session->scpSend_response[0] != 0) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid SCP ACK response"); goto scp_send_error; @@ -981,16 +998,17 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, session->scpSend_state = libssh2_NB_state_sent4; } - } else { - if (session->scpSend_state == libssh2_NB_state_sent2) { + } + else { + if(session->scpSend_state == libssh2_NB_state_sent2) { session->scpSend_state = libssh2_NB_state_sent4; } } - if (session->scpSend_state == libssh2_NB_state_sent4) { + if(session->scpSend_state == libssh2_NB_state_sent4) { /* Send mode, size, and basename */ const char *base = strrchr(path, '/'); - if (base) + if(base) base++; else base = path; @@ -1006,15 +1024,16 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, session->scpSend_state = libssh2_NB_state_sent5; } - if (session->scpSend_state == libssh2_NB_state_sent5) { + if(session->scpSend_state == libssh2_NB_state_sent5) { rc = _libssh2_channel_write(session->scpSend_channel, 0, session->scpSend_response, session->scpSend_response_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block send core file data for SCP file"); return NULL; - } else if (rc != (int)session->scpSend_response_len) { + } + else if(rc != (int)session->scpSend_response_len) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send core file data for SCP file"); goto scp_send_error; @@ -1023,31 +1042,31 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, session->scpSend_state = libssh2_NB_state_sent6; } - if (session->scpSend_state == libssh2_NB_state_sent6) { + if(session->scpSend_state == libssh2_NB_state_sent6) { /* Wait for ACK */ rc = _libssh2_channel_read(session->scpSend_channel, 0, (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response"); return NULL; } - else if (rc < 0) { + else if(rc < 0) { _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote"); goto scp_send_error; } - else if (rc == 0) + else if(rc == 0) goto scp_send_empty_channel; - else if (session->scpSend_response[0] != 0) { + else if(session->scpSend_response[0] != 0) { size_t err_len; char *err_msg; err_len = _libssh2_channel_packet_data_len(session->scpSend_channel, 0); err_msg = LIBSSH2_ALLOC(session, err_len + 1); - if (!err_msg) { + if(!err_msg) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "failed to get memory"); goto scp_send_error; @@ -1056,8 +1075,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, /* Read the remote error message */ rc = _libssh2_channel_read(session->scpSend_channel, 0, err_msg, err_len); - if (rc > 0) { - err_msg[err_len]=0; + if(rc > 0) { + err_msg[err_len] = 0; _libssh2_debug(session, LIBSSH2_TRACE_SCP, "got %02x %s", session->scpSend_response[0], err_msg); @@ -1085,8 +1104,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, scp_send_error: tmp_err_code = session->err_code; tmp_err_msg = session->err_msg; - while (libssh2_channel_free(session->scpSend_channel) == - LIBSSH2_ERROR_EAGAIN); + while(libssh2_channel_free(session->scpSend_channel) == + LIBSSH2_ERROR_EAGAIN); session->err_code = tmp_err_code; session->err_msg = tmp_err_msg; session->scpSend_channel = NULL; diff --git a/libssh2/src/session.c b/libssh2/src/session.c index b5a83ddd6..e439acde5 100644 --- a/libssh2/src/session.c +++ b/libssh2/src/session.c @@ -99,15 +99,16 @@ banner_receive(LIBSSH2_SESSION * session) int ret; int banner_len; - if (session->banner_TxRx_state == libssh2_NB_state_idle) { + if(session->banner_TxRx_state == libssh2_NB_state_idle) { banner_len = 0; session->banner_TxRx_state = libssh2_NB_state_created; - } else { + } + else { banner_len = session->banner_TxRx_total_send; } - while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) && + while((banner_len < (int) sizeof(session->banner_TxRx_banner)) && ((banner_len == 0) || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) { char c = '\0'; @@ -117,7 +118,7 @@ banner_receive(LIBSSH2_SESSION * session) ret = LIBSSH2_RECV(session, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); - if (ret < 0) { + if(ret < 0) { if(session->api_block_mode || (ret != -EAGAIN)) /* ignore EAGAIN when non-blocking */ _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, @@ -127,8 +128,8 @@ banner_receive(LIBSSH2_SESSION * session) _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Recved %d bytes banner", ret); - if (ret < 0) { - if (ret == -EAGAIN) { + if(ret < 0) { + if(ret == -EAGAIN) { session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND; session->banner_TxRx_total_send = banner_len; @@ -141,12 +142,12 @@ banner_receive(LIBSSH2_SESSION * session) return LIBSSH2_ERROR_SOCKET_RECV; } - if (ret == 0) { + if(ret == 0) { session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; return LIBSSH2_ERROR_SOCKET_DISCONNECT; } - if (c == '\0') { + if(c == '\0') { /* NULLs are not allowed in SSH banners */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; @@ -156,7 +157,7 @@ banner_receive(LIBSSH2_SESSION * session) session->banner_TxRx_banner[banner_len++] = c; } - while (banner_len && + while(banner_len && ((session->banner_TxRx_banner[banner_len - 1] == '\n') || (session->banner_TxRx_banner[banner_len - 1] == '\r'))) { banner_len--; @@ -166,11 +167,14 @@ banner_receive(LIBSSH2_SESSION * session) session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; - if (!banner_len) + if(!banner_len) return LIBSSH2_ERROR_BANNER_RECV; + if(session->remote.banner) + LIBSSH2_FREE(session, session->remote.banner); + session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1); - if (!session->remote.banner) { + if(!session->remote.banner) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocating space for remote banner"); } @@ -201,18 +205,19 @@ banner_send(LIBSSH2_SESSION * session) char banner_dup[256]; #endif - if (session->banner_TxRx_state == libssh2_NB_state_idle) { - if (session->local.banner) { + if(session->banner_TxRx_state == libssh2_NB_state_idle) { + if(session->local.banner) { /* setopt_string will have given us our \r\n characters */ banner_len = strlen((char *) session->local.banner); banner = (char *) session->local.banner; } #ifdef LIBSSH2DEBUG /* Hack and slash to avoid sending CRLF in debug output */ - if (banner_len < 256) { + if(banner_len < 256) { memcpy(banner_dup, banner, banner_len - 2); banner_dup[banner_len - 2] = '\0'; - } else { + } + else { memcpy(banner_dup, banner, 255); banner[255] = '\0'; } @@ -231,7 +236,7 @@ banner_send(LIBSSH2_SESSION * session) banner + session->banner_TxRx_total_send, banner_len - session->banner_TxRx_total_send, LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (ret < 0) + if(ret < 0) _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Error sending %d bytes: %d", banner_len - session->banner_TxRx_total_send, -ret); @@ -241,12 +246,12 @@ banner_send(LIBSSH2_SESSION * session) banner_len - session->banner_TxRx_total_send, banner, session->banner_TxRx_total_send); - if (ret != (banner_len - session->banner_TxRx_total_send)) { - if (ret >= 0 || ret == -EAGAIN) { + if(ret != (banner_len - session->banner_TxRx_total_send)) { + if(ret >= 0 || ret == -EAGAIN) { /* the whole packet could not be sent, save the what was */ session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND; - if (ret > 0) + if(ret > 0) session->banner_TxRx_total_send += ret; return LIBSSH2_ERROR_EAGAIN; } @@ -278,7 +283,7 @@ session_nonblock(libssh2_socket_t sockfd, /* operate on this */ int flags; flags = fcntl(sockfd, F_GETFL, 0); - if (nonblock) + if(nonblock) return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); @@ -327,7 +332,7 @@ session_nonblock(libssh2_socket_t sockfd, /* operate on this */ #define SETBLOCK 6 #endif -#if (SETBLOCK == 0) +#if(SETBLOCK == 0) #error "no non-blocking method was found/used/set" #endif } @@ -344,9 +349,9 @@ get_socket_nonblocking(int sockfd) #define GETBLOCK 0 #ifdef HAVE_O_NONBLOCK /* most recent unix versions */ - int flags; + int flags = fcntl(sockfd, F_GETFL, 0); - if ((flags = fcntl(sockfd, F_GETFL, 0)) == -1) { + if(flags == -1) { /* Assume blocking on error */ return 1; } @@ -360,7 +365,7 @@ get_socket_nonblocking(int sockfd) unsigned int option_value; socklen_t option_len = sizeof(option_value); - if (getsockopt + if(getsockopt (sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) { /* Assume blocking on error */ return 1; @@ -373,7 +378,7 @@ get_socket_nonblocking(int sockfd) #if defined(HAVE_SO_NONBLOCK) && (GETBLOCK == 0) /* BeOS */ long b; - if (getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) { + if(getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) { /* Assume blocking on error */ return 1; } @@ -382,19 +387,19 @@ get_socket_nonblocking(int sockfd) #define GETBLOCK 5 #endif -#if defined(SO_STATE) && defined( __VMS ) && (GETBLOCK == 0) +#if defined(SO_STATE) && defined(__VMS) && (GETBLOCK == 0) /* VMS TCP/IP Services */ size_t sockstat = 0; int callstat = 0; - size_t size = sizeof( int ); + size_t size = sizeof(int); callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE, (char *)&sockstat, &size); - if ( callstat == -1 ) return(0); - if ( (sockstat&SS_NBIO) )return(1); - return(0); + if(callstat == -1) return 0; + if((sockstat&SS_NBIO) != 0) return 1; + return 0; #undef GETBLOCK #define GETBLOCK 6 @@ -406,7 +411,7 @@ get_socket_nonblocking(int sockfd) #define GETBLOCK 7 #endif -#if (GETBLOCK == 0) +#if(GETBLOCK == 0) #error "no non-blocking method was found/used/get" #endif } @@ -419,16 +424,16 @@ libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner) { size_t banner_len = banner ? strlen(banner) : 0; - if (session->local.banner) { + if(session->local.banner) { LIBSSH2_FREE(session, session->local.banner); session->local.banner = NULL; } - if (!banner_len) + if(!banner_len) return 0; session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3); - if (!session->local.banner) { + if(!session->local.banner) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for local banner"); } @@ -474,18 +479,18 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc; LIBSSH2_SESSION *session; - if (my_alloc) { + if(my_alloc) { local_alloc = my_alloc; } - if (my_free) { + if(my_free) { local_free = my_free; } - if (my_realloc) { + if(my_realloc) { local_realloc = my_realloc; } session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract); - if (session) { + if(session) { memset(session, 0, sizeof(LIBSSH2_SESSION)); session->alloc = local_alloc; session->free = local_free; @@ -497,7 +502,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), session->api_block_mode = 1; /* blocking API by default */ _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "New session resource allocated"); - _libssh2_init_if_needed (); + _libssh2_init_if_needed(); } return session; } @@ -508,16 +513,18 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), * Set (or reset) a callback function * Returns the prior address * - * FIXME: this function relies on that we can typecast function pointers + * ALERT: this function relies on that we can typecast function pointers * to void pointers, which isn't allowed in ISO C! */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" LIBSSH2_API void * libssh2_session_callback_set(LIBSSH2_SESSION * session, int cbtype, void *callback) { void *oldcb; - switch (cbtype) { + switch(cbtype) { case LIBSSH2_CALLBACK_IGNORE: oldcb = session->ssh_msg_ignore; session->ssh_msg_ignore = callback; @@ -553,10 +560,12 @@ libssh2_session_callback_set(LIBSSH2_SESSION * session, session->recv = callback; return oldcb; } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", cbtype); + _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", + cbtype); return NULL; } +#pragma GCC diagnostic pop /* * _libssh2_wait_socket() @@ -579,8 +588,8 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time) being stored as error when a blocking function has returned */ session->err_code = LIBSSH2_ERROR_NONE; - rc = libssh2_keepalive_send (session, &seconds_to_next); - if (rc < 0) + rc = libssh2_keepalive_send(session, &seconds_to_next); + if(rc < 0) return rc; ms_to_next = seconds_to_next * 1000; @@ -597,19 +606,19 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time) ms_to_next = 1000; } - if (session->api_timeout > 0 && + if(session->api_timeout > 0 && (seconds_to_next == 0 || ms_to_next > session->api_timeout)) { - time_t now = time (NULL); + time_t now = time(NULL); elapsed_ms = (long)(1000*difftime(now, start_time)); - if (elapsed_ms > session->api_timeout) { + if(elapsed_ms > session->api_timeout) { return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "API timeout expired"); } ms_to_next = (session->api_timeout - elapsed_ms); has_timeout = 1; } - else if (ms_to_next > 0) { + else if(ms_to_next > 0) { has_timeout = 1; } else @@ -675,10 +684,10 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) { int rc; - if (session->startup_state == libssh2_NB_state_idle) { + if(session->startup_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "session_startup for socket %d", sock); - if (LIBSSH2_INVALID_SOCKET == sock) { + if(LIBSSH2_INVALID_SOCKET == sock) { /* Did we forget something? */ return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET, "Bad socket provided"); @@ -688,10 +697,10 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) session->socket_prev_blockstate = !get_socket_nonblocking(session->socket_fd); - if (session->socket_prev_blockstate) { + if(session->socket_prev_blockstate) { /* If in blocking state change to non-blocking */ rc = session_nonblock(session->socket_fd, 1); - if (rc) { + if(rc) { return _libssh2_error(session, rc, "Failed changing socket's " "blocking state to non-blocking"); @@ -701,9 +710,11 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) session->startup_state = libssh2_NB_state_created; } - if (session->startup_state == libssh2_NB_state_created) { + if(session->startup_state == libssh2_NB_state_created) { rc = banner_send(session); - if (rc) { + if(rc == LIBSSH2_ERROR_EAGAIN) + return rc; + else if(rc) { return _libssh2_error(session, rc, "Failed sending banner"); } @@ -711,10 +722,12 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) session->banner_TxRx_state = libssh2_NB_state_idle; } - if (session->startup_state == libssh2_NB_state_sent) { + if(session->startup_state == libssh2_NB_state_sent) { do { rc = banner_receive(session); - if (rc) + if(rc == LIBSSH2_ERROR_EAGAIN) + return rc; + else if(rc) return _libssh2_error(session, rc, "Failed getting banner"); } while(strncmp("SSH-", (char *)session->remote.banner, 4)); @@ -722,16 +735,18 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) session->startup_state = libssh2_NB_state_sent1; } - if (session->startup_state == libssh2_NB_state_sent1) { + if(session->startup_state == libssh2_NB_state_sent1) { rc = _libssh2_kex_exchange(session, 0, &session->startup_key_state); - if (rc) + if(rc == LIBSSH2_ERROR_EAGAIN) + return rc; + else if(rc) return _libssh2_error(session, rc, "Unable to exchange encryption keys"); session->startup_state = libssh2_NB_state_sent2; } - if (session->startup_state == libssh2_NB_state_sent2) { + if(session->startup_state == libssh2_NB_state_sent2) { _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Requesting userauth service"); @@ -745,11 +760,13 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) session->startup_state = libssh2_NB_state_sent3; } - if (session->startup_state == libssh2_NB_state_sent3) { + if(session->startup_state == libssh2_NB_state_sent3) { rc = _libssh2_transport_send(session, session->startup_service, sizeof("ssh-userauth") + 5 - 1, NULL, 0); - if (rc) { + if(rc == LIBSSH2_ERROR_EAGAIN) + return rc; + else if(rc) { return _libssh2_error(session, rc, "Unable to ask for ssh-userauth service"); } @@ -757,12 +774,12 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) session->startup_state = libssh2_NB_state_sent4; } - if (session->startup_state == libssh2_NB_state_sent4) { + if(session->startup_state == libssh2_NB_state_sent4) { rc = _libssh2_packet_require(session, SSH_MSG_SERVICE_ACCEPT, &session->startup_data, &session->startup_data_len, 0, NULL, 0, &session->startup_req_state); - if (rc) + if(rc) return rc; if(session->startup_data_len < 5) { @@ -773,7 +790,8 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) session->startup_service_length = _libssh2_ntohu32(session->startup_data + 1); - if ((session->startup_service_length != (sizeof("ssh-userauth") - 1)) + + if((session->startup_service_length != (sizeof("ssh-userauth") - 1)) || strncmp("ssh-userauth", (char *) session->startup_data + 5, session->startup_service_length)) { LIBSSH2_FREE(session, session->startup_data); @@ -843,203 +861,204 @@ session_free(LIBSSH2_SESSION *session) LIBSSH2_LISTENER *l; int packets_left = 0; - if (session->free_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource", + if(session->free_state == libssh2_NB_state_idle) { + _libssh2_debug(session, LIBSSH2_TRACE_TRANS, + "Freeing session resource", session->remote.banner); session->free_state = libssh2_NB_state_created; } - if (session->free_state == libssh2_NB_state_created) { - while ((ch = _libssh2_list_first(&session->channels))) { + if(session->free_state == libssh2_NB_state_created) { + while((ch = _libssh2_list_first(&session->channels))) { rc = _libssh2_channel_free(ch); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; } session->free_state = libssh2_NB_state_sent; } - if (session->free_state == libssh2_NB_state_sent) { - while ((l = _libssh2_list_first(&session->listeners))) { + if(session->free_state == libssh2_NB_state_sent) { + while((l = _libssh2_list_first(&session->listeners))) { rc = _libssh2_channel_forward_cancel(l); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; } session->free_state = libssh2_NB_state_sent1; } - if (session->state & LIBSSH2_STATE_NEWKEYS) { + if(session->state & LIBSSH2_STATE_NEWKEYS) { /* hostkey */ - if (session->hostkey && session->hostkey->dtor) { + if(session->hostkey && session->hostkey->dtor) { session->hostkey->dtor(session, &session->server_hostkey_abstract); } /* Client to Server */ /* crypt */ - if (session->local.crypt && session->local.crypt->dtor) { + if(session->local.crypt && session->local.crypt->dtor) { session->local.crypt->dtor(session, &session->local.crypt_abstract); } /* comp */ - if (session->local.comp && session->local.comp->dtor) { + if(session->local.comp && session->local.comp->dtor) { session->local.comp->dtor(session, 1, &session->local.comp_abstract); } /* mac */ - if (session->local.mac && session->local.mac->dtor) { + if(session->local.mac && session->local.mac->dtor) { session->local.mac->dtor(session, &session->local.mac_abstract); } /* Server to Client */ /* crypt */ - if (session->remote.crypt && session->remote.crypt->dtor) { + if(session->remote.crypt && session->remote.crypt->dtor) { session->remote.crypt->dtor(session, &session->remote.crypt_abstract); } /* comp */ - if (session->remote.comp && session->remote.comp->dtor) { + if(session->remote.comp && session->remote.comp->dtor) { session->remote.comp->dtor(session, 0, &session->remote.comp_abstract); } /* mac */ - if (session->remote.mac && session->remote.mac->dtor) { + if(session->remote.mac && session->remote.mac->dtor) { session->remote.mac->dtor(session, &session->remote.mac_abstract); } /* session_id */ - if (session->session_id) { + if(session->session_id) { LIBSSH2_FREE(session, session->session_id); } } /* Free banner(s) */ - if (session->remote.banner) { + if(session->remote.banner) { LIBSSH2_FREE(session, session->remote.banner); } - if (session->local.banner) { + if(session->local.banner) { LIBSSH2_FREE(session, session->local.banner); } /* Free preference(s) */ - if (session->kex_prefs) { + if(session->kex_prefs) { LIBSSH2_FREE(session, session->kex_prefs); } - if (session->hostkey_prefs) { + if(session->hostkey_prefs) { LIBSSH2_FREE(session, session->hostkey_prefs); } - if (session->local.kexinit) { + if(session->local.kexinit) { LIBSSH2_FREE(session, session->local.kexinit); } - if (session->local.crypt_prefs) { + if(session->local.crypt_prefs) { LIBSSH2_FREE(session, session->local.crypt_prefs); } - if (session->local.mac_prefs) { + if(session->local.mac_prefs) { LIBSSH2_FREE(session, session->local.mac_prefs); } - if (session->local.comp_prefs) { + if(session->local.comp_prefs) { LIBSSH2_FREE(session, session->local.comp_prefs); } - if (session->local.lang_prefs) { + if(session->local.lang_prefs) { LIBSSH2_FREE(session, session->local.lang_prefs); } - if (session->remote.kexinit) { + if(session->remote.kexinit) { LIBSSH2_FREE(session, session->remote.kexinit); } - if (session->remote.crypt_prefs) { + if(session->remote.crypt_prefs) { LIBSSH2_FREE(session, session->remote.crypt_prefs); } - if (session->remote.mac_prefs) { + if(session->remote.mac_prefs) { LIBSSH2_FREE(session, session->remote.mac_prefs); } - if (session->remote.comp_prefs) { + if(session->remote.comp_prefs) { LIBSSH2_FREE(session, session->remote.comp_prefs); } - if (session->remote.lang_prefs) { + if(session->remote.lang_prefs) { LIBSSH2_FREE(session, session->remote.lang_prefs); } /* * Make sure all memory used in the state variables are free */ - if (session->kexinit_data) { + if(session->kexinit_data) { LIBSSH2_FREE(session, session->kexinit_data); } - if (session->startup_data) { + if(session->startup_data) { LIBSSH2_FREE(session, session->startup_data); } - if (session->userauth_list_data) { + if(session->userauth_list_data) { LIBSSH2_FREE(session, session->userauth_list_data); } - if (session->userauth_pswd_data) { + if(session->userauth_pswd_data) { LIBSSH2_FREE(session, session->userauth_pswd_data); } - if (session->userauth_pswd_newpw) { + if(session->userauth_pswd_newpw) { LIBSSH2_FREE(session, session->userauth_pswd_newpw); } - if (session->userauth_host_packet) { + if(session->userauth_host_packet) { LIBSSH2_FREE(session, session->userauth_host_packet); } - if (session->userauth_host_method) { + if(session->userauth_host_method) { LIBSSH2_FREE(session, session->userauth_host_method); } - if (session->userauth_host_data) { + if(session->userauth_host_data) { LIBSSH2_FREE(session, session->userauth_host_data); } - if (session->userauth_pblc_data) { + if(session->userauth_pblc_data) { LIBSSH2_FREE(session, session->userauth_pblc_data); } - if (session->userauth_pblc_packet) { + if(session->userauth_pblc_packet) { LIBSSH2_FREE(session, session->userauth_pblc_packet); } - if (session->userauth_pblc_method) { + if(session->userauth_pblc_method) { LIBSSH2_FREE(session, session->userauth_pblc_method); } - if (session->userauth_kybd_data) { + if(session->userauth_kybd_data) { LIBSSH2_FREE(session, session->userauth_kybd_data); } - if (session->userauth_kybd_packet) { + if(session->userauth_kybd_packet) { LIBSSH2_FREE(session, session->userauth_kybd_packet); } - if (session->userauth_kybd_auth_instruction) { + if(session->userauth_kybd_auth_instruction) { LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction); } - if (session->open_packet) { + if(session->open_packet) { LIBSSH2_FREE(session, session->open_packet); } - if (session->open_data) { + if(session->open_data) { LIBSSH2_FREE(session, session->open_data); } - if (session->direct_message) { + if(session->direct_message) { LIBSSH2_FREE(session, session->direct_message); } - if (session->fwdLstn_packet) { + if(session->fwdLstn_packet) { LIBSSH2_FREE(session, session->fwdLstn_packet); } - if (session->pkeyInit_data) { + if(session->pkeyInit_data) { LIBSSH2_FREE(session, session->pkeyInit_data); } - if (session->scpRecv_command) { + if(session->scpRecv_command) { LIBSSH2_FREE(session, session->scpRecv_command); } - if (session->scpSend_command) { + if(session->scpSend_command) { LIBSSH2_FREE(session, session->scpSend_command); } - if (session->sftpInit_sftp) { + if(session->sftpInit_sftp) { LIBSSH2_FREE(session, session->sftpInit_sftp); } /* Free payload buffer */ - if (session->packet.total_num) { + if(session->packet.total_num) { LIBSSH2_FREE(session, session->packet.payload); } /* Cleanup all remaining packets */ - while ((pkg = _libssh2_list_first(&session->packets))) { + while((pkg = _libssh2_list_first(&session->packets))) { packets_left++; _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "packet left with id %d", pkg->data[0]); @@ -1056,18 +1075,19 @@ session_free(LIBSSH2_SESSION *session) if(session->socket_prev_blockstate) { /* if the socket was previously blocking, put it back so */ rc = session_nonblock(session->socket_fd, 0); - if (rc) { + if(rc) { _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "unable to reset socket's blocking state"); } } - if (session->server_hostkey) { + if(session->server_hostkey) { LIBSSH2_FREE(session, session->server_hostkey); } /* error string */ - if (session->err_msg && ((session->err_flags & LIBSSH2_ERR_FLAG_DUP) != 0)) { + if(session->err_msg && + ((session->err_flags & LIBSSH2_ERR_FLAG_DUP) != 0)) { LIBSSH2_FREE(session, (char *)session->err_msg); } @@ -1104,14 +1124,14 @@ session_disconnect(LIBSSH2_SESSION *session, int reason, unsigned long descr_len = 0, lang_len = 0; int rc; - if (session->disconnect_state == libssh2_NB_state_idle) { + if(session->disconnect_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Disconnecting: reason=%d, desc=%s, lang=%s", reason, description, lang); - if (description) + if(description) descr_len = strlen(description); - if (lang) + if(lang) lang_len = strlen(lang); if(descr_len > 256) @@ -1135,7 +1155,7 @@ session_disconnect(LIBSSH2_SESSION *session, int reason, rc = _libssh2_transport_send(session, session->disconnect_data, session->disconnect_data_len, (unsigned char *)lang, lang_len); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; session->disconnect_state = libssh2_NB_state_idle; @@ -1151,7 +1171,7 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *desc, const char *lang) { int rc; - + session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; BLOCK_ADJUST(rc, session, session_disconnect(session, reason, desc, lang)); @@ -1171,7 +1191,7 @@ libssh2_session_methods(LIBSSH2_SESSION * session, int method_type) /* All methods have char *name as their first element */ const LIBSSH2_KEX_METHOD *method = NULL; - switch (method_type) { + switch(method_type) { case LIBSSH2_METHOD_KEX: method = session->kex; break; @@ -1216,7 +1236,7 @@ libssh2_session_methods(LIBSSH2_SESSION * session, int method_type) return NULL; } - if (!method) { + if(!method) { _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, "No method negotiated"); return NULL; @@ -1247,32 +1267,33 @@ libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg, size_t msglen = 0; /* No error to report */ - if (!session->err_code) { - if (errmsg) { - if (want_buf) { + if(!session->err_code) { + if(errmsg) { + if(want_buf) { *errmsg = LIBSSH2_ALLOC(session, 1); - if (*errmsg) { + if(*errmsg) { **errmsg = 0; } - } else { + } + else { *errmsg = (char *) ""; } } - if (errmsg_len) { + if(errmsg_len) { *errmsg_len = 0; } return 0; } - if (errmsg) { + if(errmsg) { const char *error = session->err_msg ? session->err_msg : ""; msglen = strlen(error); - if (want_buf) { + if(want_buf) { /* Make a copy so the calling program can own it */ *errmsg = LIBSSH2_ALLOC(session, msglen + 1); - if (*errmsg) { + if(*errmsg) { memcpy(*errmsg, error, msglen); (*errmsg)[msglen] = 0; } @@ -1281,7 +1302,7 @@ libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg, *errmsg = (char *)error; } - if (errmsg_len) { + if(errmsg_len) { *errmsg_len = msglen; } @@ -1309,7 +1330,7 @@ libssh2_session_last_errno(LIBSSH2_SESSION * session) LIBSSH2_API int libssh2_session_set_last_error(LIBSSH2_SESSION* session, int errcode, - const char* errmsg) + const char *errmsg) { return _libssh2_error_flags(session, errcode, errmsg, LIBSSH2_ERR_FLAG_DUP); @@ -1417,14 +1438,20 @@ libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended) session = channel->session; packet = _libssh2_list_first(&session->packets); - while (packet) { - if ( channel->local.id == _libssh2_ntohu32(packet->data + 1)) { - if ( extended == 1 && - (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA - || packet->data[0] == SSH_MSG_CHANNEL_DATA )) { + while(packet) { + if(packet->data_len < 5) { + return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Packet too small"); + } + + if(channel->local.id == _libssh2_ntohu32(packet->data + 1)) { + if(extended == 1 && + (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA + || packet->data[0] == SSH_MSG_CHANNEL_DATA)) { return 1; - } else if ( extended == 0 && - packet->data[0] == SSH_MSG_CHANNEL_DATA) { + } + else if(extended == 0 && + packet->data[0] == SSH_MSG_CHANNEL_DATA) { return 1; } /* else - no data of any type is ready to be read */ @@ -1475,7 +1502,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) #else struct pollfd sockets[256]; - if (nfds > 256) + if(nfds > 256) /* systems without alloca use a fixed-size array, this can be fixed if we really want to, at least if the compiler is a C99 capable one */ return -1; @@ -1483,7 +1510,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) /* Setup sockets for polling */ for(i = 0; i < nfds; i++) { fds[i].revents = 0; - switch (fds[i].type) { + switch(fds[i].type) { case LIBSSH2_POLLFD_SOCKET: sockets[i].fd = fds[i].fd.socket; sockets[i].events = fds[i].events; @@ -1494,7 +1521,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) sockets[i].fd = fds[i].fd.channel->session->socket_fd; sockets[i].events = POLLIN; sockets[i].revents = 0; - if (!session) + if(!session) session = fds[i].fd.channel->session; break; @@ -1502,12 +1529,12 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) sockets[i].fd = fds[i].fd.listener->session->socket_fd; sockets[i].events = POLLIN; sockets[i].revents = 0; - if (!session) + if(!session) session = fds[i].fd.listener->session; break; default: - if (session) + if(session) _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, "Invalid descriptor passed to libssh2_poll()"); return -1; @@ -1523,38 +1550,38 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) FD_ZERO(&wfds); for(i = 0; i < nfds; i++) { fds[i].revents = 0; - switch (fds[i].type) { + switch(fds[i].type) { case LIBSSH2_POLLFD_SOCKET: - if (fds[i].events & LIBSSH2_POLLFD_POLLIN) { + if(fds[i].events & LIBSSH2_POLLFD_POLLIN) { FD_SET(fds[i].fd.socket, &rfds); - if (fds[i].fd.socket > maxfd) + if(fds[i].fd.socket > maxfd) maxfd = fds[i].fd.socket; } - if (fds[i].events & LIBSSH2_POLLFD_POLLOUT) { + if(fds[i].events & LIBSSH2_POLLFD_POLLOUT) { FD_SET(fds[i].fd.socket, &wfds); - if (fds[i].fd.socket > maxfd) + if(fds[i].fd.socket > maxfd) maxfd = fds[i].fd.socket; } break; case LIBSSH2_POLLFD_CHANNEL: FD_SET(fds[i].fd.channel->session->socket_fd, &rfds); - if (fds[i].fd.channel->session->socket_fd > maxfd) + if(fds[i].fd.channel->session->socket_fd > maxfd) maxfd = fds[i].fd.channel->session->socket_fd; - if (!session) + if(!session) session = fds[i].fd.channel->session; break; case LIBSSH2_POLLFD_LISTENER: FD_SET(fds[i].fd.listener->session->socket_fd, &rfds); - if (fds[i].fd.listener->session->socket_fd > maxfd) + if(fds[i].fd.listener->session->socket_fd > maxfd) maxfd = fds[i].fd.listener->session->socket_fd; - if (!session) + if(!session) session = fds[i].fd.listener->session; break; default: - if (session) + if(session) _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, "Invalid descriptor passed to libssh2_poll()"); return -1; @@ -1577,10 +1604,10 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) active_fds = 0; for(i = 0; i < nfds; i++) { - if (fds[i].events != fds[i].revents) { - switch (fds[i].type) { + if(fds[i].events != fds[i].revents) { + switch(fds[i].type) { case LIBSSH2_POLLFD_CHANNEL: - if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && + if((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want to be ready for read */ ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* Not yet known to be ready for read */ @@ -1589,7 +1616,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) 0) ? LIBSSH2_POLLFD_POLLIN : 0; } - if ((fds[i].events & LIBSSH2_POLLFD_POLLEXT) && + if((fds[i].events & LIBSSH2_POLLFD_POLLEXT) && /* Want to be ready for extended read */ ((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) { /* Not yet known to be ready for extended read */ @@ -1598,7 +1625,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) 1) ? LIBSSH2_POLLFD_POLLEXT : 0; } - if ((fds[i].events & LIBSSH2_POLLFD_POLLOUT) && + if((fds[i].events & LIBSSH2_POLLFD_POLLOUT) && /* Want to be ready for write */ ((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) { /* Not yet known to be ready for write */ @@ -1606,11 +1633,11 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) poll_channel_write(fds[i].fd. channel) ? LIBSSH2_POLLFD_POLLOUT : 0; } - if (fds[i].fd.channel->remote.close + if(fds[i].fd.channel->remote.close || fds[i].fd.channel->local.close) { fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED; } - if (fds[i].fd.channel->session->socket_state == + if(fds[i].fd.channel->session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) { fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED | @@ -1619,7 +1646,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) break; case LIBSSH2_POLLFD_LISTENER: - if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && + if((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want a connection */ ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* No connections known of yet */ @@ -1627,7 +1654,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) poll_listener_queued(fds[i].fd. listener) ? LIBSSH2_POLLFD_POLLIN : 0; } - if (fds[i].fd.listener->session->socket_state == + if(fds[i].fd.listener->session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) { fds[i].revents |= LIBSSH2_POLLFD_LISTENER_CLOSED | @@ -1636,12 +1663,12 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) break; } } - if (fds[i].revents) { + if(fds[i].revents) { active_fds++; } } - if (active_fds) { + if(active_fds) { /* Don't block on the sockets if we have channels/listeners which are ready */ timeout_remaining = 0; @@ -1666,23 +1693,25 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) timeout_remaining = 0; #endif /* HAVE_GETTIMEOFDAY */ - if (sysret > 0) { + if(sysret > 0) { for(i = 0; i < nfds; i++) { - switch (fds[i].type) { + switch(fds[i].type) { case LIBSSH2_POLLFD_SOCKET: fds[i].revents = sockets[i].revents; - sockets[i].revents = 0; /* In case we loop again, be nice */ - if (fds[i].revents) { + sockets[i].revents = 0; /* In case we loop again, be + nice */ + if(fds[i].revents) { active_fds++; } break; case LIBSSH2_POLLFD_CHANNEL: - if (sockets[i].events & POLLIN) { + if(sockets[i].events & POLLIN) { /* Spin session until no data available */ - while (_libssh2_transport_read(fds[i].fd.channel->session) - > 0); + while(_libssh2_transport_read(fds[i].fd. + channel->session) + > 0); } - if (sockets[i].revents & POLLHUP) { + if(sockets[i].revents & POLLHUP) { fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED; @@ -1690,12 +1719,13 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) sockets[i].revents = 0; break; case LIBSSH2_POLLFD_LISTENER: - if (sockets[i].events & POLLIN) { + if(sockets[i].events & POLLIN) { /* Spin session until no data available */ - while (_libssh2_transport_read(fds[i].fd.listener->session) - > 0); + while(_libssh2_transport_read(fds[i].fd. + listener->session) + > 0); } - if (sockets[i].revents & POLLHUP) { + if(sockets[i].revents & POLLHUP) { fds[i].revents |= LIBSSH2_POLLFD_LISTENER_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED; @@ -1713,7 +1743,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) struct timeval tv_begin, tv_end; _libssh2_gettimeofday((struct timeval *) &tv_begin, NULL); - sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv); + sysret = select(maxfd + 1, &rfds, &wfds, NULL, &tv); _libssh2_gettimeofday((struct timeval *) &tv_end, NULL); timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000; @@ -1723,39 +1753,42 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) /* If the platform doesn't support gettimeofday, * then just make the call non-blocking and walk away */ - sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv); + sysret = select(maxfd + 1, &rfds, &wfds, NULL, &tv); timeout_remaining = 0; #endif - if (sysret > 0) { + if(sysret > 0) { for(i = 0; i < nfds; i++) { - switch (fds[i].type) { + switch(fds[i].type) { case LIBSSH2_POLLFD_SOCKET: - if (FD_ISSET(fds[i].fd.socket, &rfds)) { + if(FD_ISSET(fds[i].fd.socket, &rfds)) { fds[i].revents |= LIBSSH2_POLLFD_POLLIN; } - if (FD_ISSET(fds[i].fd.socket, &wfds)) { + if(FD_ISSET(fds[i].fd.socket, &wfds)) { fds[i].revents |= LIBSSH2_POLLFD_POLLOUT; } - if (fds[i].revents) { + if(fds[i].revents) { active_fds++; } break; case LIBSSH2_POLLFD_CHANNEL: - if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) { + if(FD_ISSET(fds[i].fd.channel->session->socket_fd, + &rfds)) { /* Spin session until no data available */ - while (_libssh2_transport_read(fds[i].fd.channel->session) - > 0); + while(_libssh2_transport_read(fds[i].fd. + channel->session) + > 0); } break; case LIBSSH2_POLLFD_LISTENER: - if (FD_ISSET + if(FD_ISSET (fds[i].fd.listener->session->socket_fd, &rfds)) { /* Spin session until no data available */ - while (_libssh2_transport_read(fds[i].fd.listener->session) - > 0); + while(_libssh2_transport_read(fds[i].fd. + listener->session) + > 0); } break; } @@ -1763,7 +1796,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout) } #endif /* else no select() or poll() -- timeout (and by extension * timeout_remaining) will be equal to 0 */ - } while ((timeout_remaining > 0) && !active_fds); + } while((timeout_remaining > 0) && !active_fds); return active_fds; } @@ -1789,10 +1822,10 @@ LIBSSH2_API const char * libssh2_session_banner_get(LIBSSH2_SESSION *session) { /* to avoid a coredump when session is NULL */ - if (NULL == session) + if(NULL == session) return NULL; - if (NULL==session->remote.banner) + if(NULL == session->remote.banner) return NULL; return (const char *) session->remote.banner; diff --git a/libssh2/src/session.h b/libssh2/src/session.h index aff4f2c5c..7b6c291e2 100644 --- a/libssh2/src/session.h +++ b/libssh2/src/session.h @@ -51,9 +51,9 @@ function. */ -#define BLOCK_ADJUST(rc,sess,x) \ +#define BLOCK_ADJUST(rc, sess, x) \ do { \ - time_t entry_time = time (NULL); \ + time_t entry_time = time(NULL); \ do { \ rc = x; \ /* the order of the check below is important to properly deal with \ @@ -70,9 +70,9 @@ * immediately. If the API is blocking and we get a NULL we check the errno * and *only* if that is EAGAIN we loop and wait for socket action. */ -#define BLOCK_ADJUST_ERRNO(ptr,sess,x) \ +#define BLOCK_ADJUST_ERRNO(ptr, sess, x) \ do { \ - time_t entry_time = time (NULL); \ + time_t entry_time = time(NULL); \ int rc; \ do { \ ptr = x; \ diff --git a/libssh2/src/sftp.c b/libssh2/src/sftp.c index fd94d3902..ece590e51 100644 --- a/libssh2/src/sftp.c +++ b/libssh2/src/sftp.c @@ -1,6 +1,6 @@ /* Copyright (c) 2004-2008, Sara Golemon * Copyright (c) 2007 Eli Fant - * Copyright (c) 2009-2014 by Daniel Stenberg + * Copyright (c) 2009-2019 by Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -91,7 +91,7 @@ /* This is the maximum packet length to accept, as larger than this indicate some kind of server problem. */ -#define LIBSSH2_SFTP_PACKET_MAXLEN 80000 +#define LIBSSH2_SFTP_PACKET_MAXLEN (256 * 1024) static int sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type, uint32_t request_id, unsigned char **data, @@ -161,7 +161,8 @@ remove_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) request_id); if(zombie) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Removing request ID %ld from the list of zombie requests", + "Removing request ID %ld from the list of " + "zombie requests", request_id); _libssh2_list_remove(&zombie->node); @@ -181,7 +182,7 @@ add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) zombie = LIBSSH2_ALLOC(sftp->channel->session, sizeof(struct sftp_zombie_requests)); - if (!zombie) + if(!zombie) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "malloc fail for zombie request ID"); else { @@ -204,7 +205,7 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data, LIBSSH2_SFTP_PACKET *packet; uint32_t request_id; - if (data_len < 5) { + if(data_len < 5) { return LIBSSH2_ERROR_OUT_OF_BOUNDARY; } @@ -272,7 +273,7 @@ sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data, } packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_PACKET)); - if (!packet) { + if(!packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate datablock for SFTP packet"); } @@ -331,9 +332,9 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) (char *)&sftp->partial_size[ sftp->partial_size_len], 4 - sftp->partial_size_len); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; - else if (rc < 0) + else if(rc < 0) return _libssh2_error(session, rc, "channel read"); sftp->partial_size_len += rc; @@ -345,11 +346,15 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) sftp->partial_len = _libssh2_ntohu32(sftp->partial_size); /* make sure we don't proceed if the packet size is unreasonably large */ - if (sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN) + if(sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN) { + libssh2_channel_flush(channel); + sftp->partial_size_len = 0; return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, "SFTP packet too large"); - if (sftp->partial_len == 0) + } + + if(sftp->partial_len == 0) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate empty SFTP packet"); @@ -358,7 +363,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) "Data begin - Packet Length: %lu", sftp->partial_len); packet = LIBSSH2_ALLOC(session, sftp->partial_len); - if (!packet) + if(!packet) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate SFTP packet"); sftp->partial_size_len = 0; @@ -372,7 +377,8 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) if(sftp->partial_len > recv_window) { /* ask for twice the data amount we need at once */ rc = _libssh2_channel_receive_window_adjust(channel, - sftp->partial_len*2, + sftp->partial_len + * 2, 1, NULL); /* store the state so that we continue with the correct operation at next invoke */ @@ -386,13 +392,13 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) } /* Read as much of the packet as we can */ - while (sftp->partial_len > sftp->partial_received) { + while(sftp->partial_len > sftp->partial_received) { rc = _libssh2_channel_read(channel, 0, (char *)&packet[sftp->partial_received], sftp->partial_len - sftp->partial_received); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { /* * We received EAGAIN, save what we have and return EAGAIN to * the caller. Set 'partial_packet' so that this function @@ -401,7 +407,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) sftp->packet_state = libssh2_NB_state_sent1; return rc; } - else if (rc < 0) { + else if(rc < 0) { LIBSSH2_FREE(session, packet); sftp->partial_packet = NULL; return _libssh2_error(session, rc, @@ -416,7 +422,7 @@ sftp_packet_read(LIBSSH2_SFTP *sftp) so we take a copy of the packet type before we call it. */ packet_type = packet[0]; rc = sftp_packet_add(sftp, packet, sftp->partial_len); - if (rc) { + if(rc) { LIBSSH2_FREE(session, packet); return rc; } @@ -485,7 +491,7 @@ sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type, /* Special consideration when getting VERSION packet */ - while (packet) { + while(packet) { if((packet->data[0] == packet_type) && ((packet_type == SSH_FXP_VERSION) || (packet->request_id == request_id))) { @@ -517,38 +523,38 @@ sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type, LIBSSH2_SESSION *session = sftp->channel->session; int rc; - if (data == NULL || data_len == NULL || required_size == 0) { + if(data == NULL || data_len == NULL || required_size == 0) { return LIBSSH2_ERROR_BAD_USE; } _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld", (int) packet_type, request_id); - if (sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) { + if(sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) { /* The right packet was available in the packet brigade */ _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d", (int) packet_type); if (*data_len < required_size) { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + return LIBSSH2_ERROR_BUFFER_TOO_SMALL; } return LIBSSH2_ERROR_NONE; } - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { + while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) { rc = sftp_packet_read(sftp); - if (rc < 0) + if(rc < 0) return rc; /* data was read, check the queue again */ - if (!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) { + if(!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) { /* The right packet was available in the packet brigade */ _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d", (int) packet_type); if (*data_len < required_size) { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + return LIBSSH2_ERROR_BUFFER_TOO_SMALL; } return LIBSSH2_ERROR_NONE; @@ -571,17 +577,17 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses, int i; int rc; - if (data == NULL || data_len == NULL || required_size == 0) { + if(data == NULL || data_len == NULL || required_size == 0) { return LIBSSH2_ERROR_BAD_USE; } /* If no timeout is active, start a new one */ - if (sftp->requirev_start == 0) + if(sftp->requirev_start == 0) sftp->requirev_start = time(NULL); - while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) { + while(sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) { for(i = 0; i < num_valid_responses; i++) { - if (sftp_packet_ask(sftp, valid_responses[i], request_id, + if(sftp_packet_ask(sftp, valid_responses[i], request_id, data, data_len) == 0) { /* * Set to zero before all returns to say @@ -590,7 +596,7 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses, sftp->requirev_start = 0; if (*data_len < required_size) { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + return LIBSSH2_ERROR_BUFFER_TOO_SMALL; } return LIBSSH2_ERROR_NONE; @@ -598,19 +604,21 @@ sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses, } rc = sftp_packet_read(sftp); - if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) { + if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) { sftp->requirev_start = 0; return rc; - } else if (rc <= 0) { + } + else if(rc <= 0) { /* prevent busy-looping */ long left = - LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - sftp->requirev_start); + LIBSSH2_READ_TIMEOUT - + (long)(time(NULL) - sftp->requirev_start); - if (left <= 0) { + if(left <= 0) { sftp->requirev_start = 0; return LIBSSH2_ERROR_TIMEOUT; } - else if (rc == LIBSSH2_ERROR_EAGAIN) { + else if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } } @@ -636,27 +644,27 @@ sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs) /* TODO: When we add SFTP4+ functionality flag_mask can get additional bits */ - if (!attrs) { + if(!attrs) { _libssh2_htonu32(s, 0); return 4; } _libssh2_store_u32(&s, attrs->flags & flag_mask); - if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) { + if(attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) { _libssh2_store_u64(&s, attrs->filesize); } - if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) { + if(attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) { _libssh2_store_u32(&s, attrs->uid); _libssh2_store_u32(&s, attrs->gid); } - if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { + if(attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { _libssh2_store_u32(&s, attrs->permissions); } - if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { + if(attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { _libssh2_store_u32(&s, attrs->atime); _libssh2_store_u32(&s, attrs->mtime); } @@ -667,68 +675,57 @@ sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs) /* sftp_bin2attr */ static int -sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs, const unsigned char *p, size_t data_len) +sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES *attrs, const unsigned char *p, + size_t data_len) { - const unsigned char *s = p; + struct string_buf buf; + uint32_t flags = 0; + buf.data = (unsigned char *)p; + buf.dataptr = buf.data; + buf.len = data_len; - if (data_len >= 4) { - memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - attrs->flags = _libssh2_ntohu32(s); - s += 4; - data_len -= 4; - } - else { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + if(_libssh2_get_u32(&buf, &flags) != 0) { + return LIBSSH2_ERROR_BUFFER_TOO_SMALL; } + attrs->flags = flags; - if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) { - if (data_len >= 8) { - attrs->filesize = _libssh2_ntohu64(s); - s += 8; - data_len -= 8; - } - else { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + if(attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) { + if(_libssh2_get_u64(&buf, &(attrs->filesize)) != 0) { + return LIBSSH2_ERROR_BUFFER_TOO_SMALL; } } - if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) { - if (data_len >= 8) { - attrs->uid = _libssh2_ntohu32(s); - s += 4; - attrs->gid = _libssh2_ntohu32(s); - s += 4; - data_len -= 8; - } - else { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + if(attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) { + uint32_t uid = 0; + uint32_t gid = 0; + if(_libssh2_get_u32(&buf, &uid) != 0 || + _libssh2_get_u32(&buf, &gid) != 0) { + return LIBSSH2_ERROR_BUFFER_TOO_SMALL; } + attrs->uid = uid; + attrs->gid = gid; } - if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { - if (data_len >= 4) { - attrs->permissions = _libssh2_ntohu32(s); - s += 4; - data_len -= 4; - } - else { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + if(attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { + uint32_t permissions; + if(_libssh2_get_u32(&buf, &permissions) != 0) { + return LIBSSH2_ERROR_BUFFER_TOO_SMALL; } + attrs->permissions = permissions; } - if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { - if (data_len >= 8) { - attrs->atime = _libssh2_ntohu32(s); - s += 4; - attrs->mtime = _libssh2_ntohu32(s); - s += 4; - } - else { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; + if(attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { + uint32_t atime; + uint32_t mtime; + if(_libssh2_get_u32(&buf, &atime) != 0 || + _libssh2_get_u32(&buf, &mtime) != 0) { + return LIBSSH2_ERROR_BUFFER_TOO_SMALL; } + attrs->atime = atime; + attrs->mtime = mtime; } - return (s - p); + return (buf.dataptr - buf.data); } /* ************ @@ -748,12 +745,12 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor) (void) channel; /* Free the partial packet storage for sftp_packet_read */ - if (sftp->partial_packet) { + if(sftp->partial_packet) { LIBSSH2_FREE(session, sftp->partial_packet); } /* Free the packet storage for _libssh2_sftp_packet_readdir */ - if (sftp->readdir_packet) { + if(sftp->readdir_packet) { LIBSSH2_FREE(session, sftp->readdir_packet); } @@ -767,12 +764,14 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor) */ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) { - unsigned char *data, *s; + unsigned char *data; size_t data_len; ssize_t rc; LIBSSH2_SFTP *sftp_handle; + struct string_buf buf; + unsigned char *endp; - if (session->sftpInit_state == libssh2_NB_state_idle) { + if(session->sftpInit_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Initializing SFTP subsystem"); @@ -795,13 +794,13 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) sftp_handle = session->sftpInit_sftp; - if (session->sftpInit_state == libssh2_NB_state_created) { + if(session->sftpInit_state == libssh2_NB_state_created) { session->sftpInit_channel = _libssh2_channel_open(session, "session", sizeof("session") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0); - if (!session->sftpInit_channel) { - if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { + if(!session->sftpInit_channel) { + if(libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block starting up channel"); } @@ -816,16 +815,18 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) session->sftpInit_state = libssh2_NB_state_sent; } - if (session->sftpInit_state == libssh2_NB_state_sent) { + if(session->sftpInit_state == libssh2_NB_state_sent) { int ret = _libssh2_channel_process_startup(session->sftpInit_channel, "subsystem", - sizeof("subsystem") - 1, "sftp", + sizeof("subsystem") - 1, + "sftp", strlen("sftp")); - if (ret == LIBSSH2_ERROR_EAGAIN) { + if(ret == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block to request SFTP subsystem"); return NULL; - } else if (ret) { + } + else if(ret) { _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Unable to request SFTP subsystem"); goto sftp_init_error; @@ -834,10 +835,10 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) session->sftpInit_state = libssh2_NB_state_sent1; } - if (session->sftpInit_state == libssh2_NB_state_sent1) { + if(session->sftpInit_state == libssh2_NB_state_sent1) { rc = _libssh2_channel_extended_data(session->sftpInit_channel, - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); - if (rc == LIBSSH2_ERROR_EAGAIN) { + LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting handle extended data"); return NULL; @@ -846,7 +847,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) sftp_handle = session->sftpInit_sftp = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP)); - if (!sftp_handle) { + if(!sftp_handle) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a new SFTP structure"); goto sftp_init_error; @@ -860,19 +861,20 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) session->sftpInit_sent = 0; /* nothing's sent yet */ _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Sending FXP_INIT packet advertising version %d support", + "Sending FXP_INIT packet advertising " + "version %d support", (int) LIBSSH2_SFTP_VERSION); session->sftpInit_state = libssh2_NB_state_sent2; } - if (session->sftpInit_state == libssh2_NB_state_sent2) { + if(session->sftpInit_state == libssh2_NB_state_sent2) { /* sent off what's left of the init buffer to send */ rc = _libssh2_channel_write(session->sftpInit_channel, 0, session->sftpInit_buffer + session->sftpInit_sent, 9 - session->sftpInit_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending SSH_FXP_INIT"); return NULL; @@ -896,29 +898,37 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION, 0, &data, &data_len, 5); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block receiving SSH_FXP_VERSION"); return NULL; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Invalid SSH_FXP_VERSION response"); goto sftp_init_error; } - else if (rc) { + else if(rc) { _libssh2_error(session, rc, "Timeout waiting for response from SFTP subsystem"); goto sftp_init_error; } - s = data + 1; - sftp_handle->version = _libssh2_ntohu32(s); - s += 4; - if (sftp_handle->version > LIBSSH2_SFTP_VERSION) { + buf.data = data; + buf.dataptr = buf.data + 1; + buf.len = data_len; + endp = &buf.data[data_len]; + + if(_libssh2_get_u32(&buf, &(sftp_handle->version)) != 0) { + LIBSSH2_FREE(session, data); + rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL; + goto sftp_init_error; + } + + if(sftp_handle->version > LIBSSH2_SFTP_VERSION) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Truncating remote SFTP version from %lu", sftp_handle->version); @@ -927,20 +937,22 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Enabling SFTP version %lu compatibility", sftp_handle->version); - while (s < (data + data_len)) { - size_t extname_len, extdata_len; + while(buf.dataptr < endp) { + unsigned char *extname, *extdata; - extname_len = _libssh2_ntohu32(s); - s += 4; - /* the extension name starts here */ - s += extname_len; - - extdata_len = _libssh2_ntohu32(s); - s += 4; - - /* TODO: Actually process extensions */ - s += extdata_len; + if(_libssh2_get_string(&buf, &extname, NULL)) { + LIBSSH2_FREE(session, data); + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short when extracting extname"); + goto sftp_init_error; + } + if(_libssh2_get_string(&buf, &extdata, NULL)) { + LIBSSH2_FREE(session, data); + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "Data too short when extracting extdata"); + goto sftp_init_error; + } } LIBSSH2_FREE(session, data); @@ -960,10 +972,10 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) return sftp_handle; sftp_init_error: - while (_libssh2_channel_free(session->sftpInit_channel) == + while(_libssh2_channel_free(session->sftpInit_channel) == LIBSSH2_ERROR_EAGAIN); session->sftpInit_channel = NULL; - if (session->sftpInit_sftp) { + if(session->sftpInit_sftp) { LIBSSH2_FREE(session, session->sftpInit_sftp); session->sftpInit_sftp = NULL; } @@ -1006,55 +1018,55 @@ sftp_shutdown(LIBSSH2_SFTP *sftp) /* * Make sure all memory used in the state variables are free */ - if (sftp->partial_packet) { + if(sftp->partial_packet) { LIBSSH2_FREE(session, sftp->partial_packet); sftp->partial_packet = NULL; } - if (sftp->open_packet) { + if(sftp->open_packet) { LIBSSH2_FREE(session, sftp->open_packet); sftp->open_packet = NULL; } - if (sftp->readdir_packet) { + if(sftp->readdir_packet) { LIBSSH2_FREE(session, sftp->readdir_packet); sftp->readdir_packet = NULL; } - if (sftp->fstat_packet) { + if(sftp->fstat_packet) { LIBSSH2_FREE(session, sftp->fstat_packet); sftp->fstat_packet = NULL; } - if (sftp->unlink_packet) { + if(sftp->unlink_packet) { LIBSSH2_FREE(session, sftp->unlink_packet); sftp->unlink_packet = NULL; } - if (sftp->rename_packet) { + if(sftp->rename_packet) { LIBSSH2_FREE(session, sftp->rename_packet); sftp->rename_packet = NULL; } - if (sftp->fstatvfs_packet) { + if(sftp->fstatvfs_packet) { LIBSSH2_FREE(session, sftp->fstatvfs_packet); sftp->fstatvfs_packet = NULL; } - if (sftp->statvfs_packet) { + if(sftp->statvfs_packet) { LIBSSH2_FREE(session, sftp->statvfs_packet); sftp->statvfs_packet = NULL; } - if (sftp->mkdir_packet) { + if(sftp->mkdir_packet) { LIBSSH2_FREE(session, sftp->mkdir_packet); sftp->mkdir_packet = NULL; } - if (sftp->rmdir_packet) { + if(sftp->rmdir_packet) { LIBSSH2_FREE(session, sftp->rmdir_packet); sftp->rmdir_packet = NULL; } - if (sftp->stat_packet) { + if(sftp->stat_packet) { LIBSSH2_FREE(session, sftp->stat_packet); sftp->stat_packet = NULL; } - if (sftp->symlink_packet) { + if(sftp->symlink_packet) { LIBSSH2_FREE(session, sftp->symlink_packet); sftp->symlink_packet = NULL; } - if (sftp->fsync_packet) { + if(sftp->fsync_packet) { LIBSSH2_FREE(session, sftp->fsync_packet); sftp->fsync_packet = NULL; } @@ -1103,16 +1115,17 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, ssize_t rc; int open_file = (open_type == LIBSSH2_SFTP_OPENFILE)?1:0; - if (sftp->open_state == libssh2_NB_state_idle) { + if(sftp->open_state == libssh2_NB_state_idle) { /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) + flags(4) */ sftp->open_packet_len = filename_len + 13 + - (open_file? (4 + sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0); + (open_file? (4 + + sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0); /* surprise! this starts out with nothing sent */ sftp->open_packet_sent = 0; s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len); - if (!sftp->open_packet) { + if(!sftp->open_packet) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_OPEN or " "FXP_OPENDIR packet"); @@ -1129,7 +1142,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, _libssh2_store_u32(&s, sftp->open_request_id); _libssh2_store_str(&s, filename, filename_len); - if (open_file) { + if(open_file) { _libssh2_store_u32(&s, flags); s += sftp_attr2bin(s, &attrs); } @@ -1140,14 +1153,15 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, sftp->open_state = libssh2_NB_state_created; } - if (sftp->open_state == libssh2_NB_state_created) { + if(sftp->open_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, sftp->open_packet+ sftp->open_packet_sent, sftp->open_packet_len - sftp->open_packet_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending FXP_OPEN or FXP_OPENDIR command"); + "Would block sending FXP_OPEN or " + "FXP_OPENDIR command"); return NULL; } else if(rc < 0) { @@ -1170,7 +1184,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, } } - if (sftp->open_state == libssh2_NB_state_sent) { + if(sftp->open_state == libssh2_NB_state_sent) { size_t data_len; unsigned char *data; static const unsigned char fopen_responses[2] = @@ -1178,13 +1192,13 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, rc = sftp_packet_requirev(sftp, 2, fopen_responses, sftp->open_request_id, &data, &data_len, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for status message"); return NULL; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, @@ -1192,7 +1206,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, return NULL; } sftp->open_state = libssh2_NB_state_idle; - if (rc) { + if(rc) { _libssh2_error(session, rc, "Timeout waiting for status message"); return NULL; } @@ -1201,7 +1215,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, a fine response while STATUS means error. It seems though that at times we get an SSH_FX_OK back in a STATUS, followed the "real" HANDLE so we need to properly deal with that. */ - if (data[0] == SSH_FXP_STATUS) { + if(data[0] == SSH_FXP_STATUS) { int badness = 1; if(data_len < 9) { @@ -1214,7 +1228,8 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, sftp->last_errno = _libssh2_ntohu32(data + 5); if(LIBSSH2_FX_OK == sftp->last_errno) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got HANDLE FXOK!"); + _libssh2_debug(session, LIBSSH2_TRACE_SFTP, + "got HANDLE FXOK!"); LIBSSH2_FREE(session, data); @@ -1227,8 +1242,8 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, sftp->open_state = libssh2_NB_state_sent; return NULL; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, @@ -1243,7 +1258,8 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, if(badness) { _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Failed opening remote file"); - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got FXP_STATUS %d", + _libssh2_debug(session, LIBSSH2_TRACE_SFTP, + "got FXP_STATUS %d", sftp->last_errno); LIBSSH2_FREE(session, data); return NULL; @@ -1258,7 +1274,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, } fp = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE)); - if (!fp) { + if(!fp) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate new SFTP handle structure"); LIBSSH2_FREE(session, data); @@ -1268,7 +1284,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, LIBSSH2_SFTP_HANDLE_DIR; fp->handle_len = _libssh2_ntohu32(data + 5); - if (fp->handle_len > SFTP_HANDLE_MAXLEN) + if(fp->handle_len > SFTP_HANDLE_MAXLEN) /* SFTP doesn't allow handles longer than 256 characters */ fp->handle_len = SFTP_HANDLE_MAXLEN; @@ -1364,7 +1380,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, and second phases on the next call and resume sending. */ - switch (sftp->read_state) { + switch(sftp->read_state) { case libssh2_NB_state_idle: /* Some data may already have been read from the server in the @@ -1388,9 +1404,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, return copy; } - if (filep->eof) { + if(filep->eof) { return 0; - } else { + } + else { /* We allow a number of bytes being requested at any given time without having been acked - until we reach EOF. */ @@ -1441,7 +1458,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, at next call */ assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->data_left); assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->eof); - if (rc) + if(rc) return rc; } } @@ -1455,14 +1472,14 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, uint32_t request_id; uint32_t size = count; - if (size < buffer_size) + if(size < buffer_size) size = buffer_size; - if (size > MAX_SFTP_READ_SIZE) + if(size > MAX_SFTP_READ_SIZE) size = MAX_SFTP_READ_SIZE; chunk = LIBSSH2_ALLOC(session, packet_len + sizeof(struct sftp_pipeline_chunk)); - if (!chunk) + if(!chunk) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "malloc fail for FXP_WRITE"); @@ -1485,13 +1502,13 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, /* add this new entry LAST in the list */ _libssh2_list_add(&handle->packet_list, &chunk->node); - count -= MIN(size,count); /* deduct the size we used, as we might - * have to create more packets */ + count -= MIN(size, count); /* deduct the size we used, as we might + * have to create more packets */ _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "read request id %d sent (offset: %d, size: %d)", request_id, (int)chunk->offset, (int)chunk->len); } - + /* FALL-THROUGH */ case libssh2_NB_state_sent: sftp->read_state = libssh2_NB_state_idle; @@ -1519,9 +1536,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, /* We still have data left to send for this chunk. * If there is at least one completely sent chunk, * we can get out of this loop and start reading. */ - if (chunk != _libssh2_list_first(&handle->packet_list)) { + if(chunk != _libssh2_list_first(&handle->packet_list)) { break; - } else { + } + else { continue; } } @@ -1530,6 +1548,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, /* move on to the next chunk with data to send */ chunk = _libssh2_list_next(&chunk->node); } + /* FALL-THROUGH */ case libssh2_NB_state_sent2: @@ -1551,9 +1570,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, if(chunk->lefttosend) { /* if the chunk still has data left to send, we shouldn't wait for an ACK for it just yet */ - if (bytes_in_buffer > 0) { + if(bytes_in_buffer > 0) { return bytes_in_buffer; - } else { + } + else { /* we should never reach this point */ return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "sftp_read() internal error"); @@ -1562,14 +1582,14 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, rc = sftp_packet_requirev(sftp, 2, read_responses, chunk->request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN && bytes_in_buffer != 0) { + if(rc == LIBSSH2_ERROR_EAGAIN && bytes_in_buffer != 0) { /* do not return EAGAIN if we have already * written data into the buffer */ return bytes_in_buffer; } - if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, @@ -1585,7 +1605,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, * FX_EOF when we reach the end of the file. */ - switch (data[0]) { + switch(data[0]) { case SSH_FXP_STATUS: /* remove the chunk we just processed */ @@ -1599,7 +1619,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, rc32 = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (rc32 == LIBSSH2_FX_EOF) { + if(rc32 == LIBSSH2_FX_EOF) { filep->eof = TRUE; return bytes_in_buffer; } @@ -1611,7 +1631,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, break; case SSH_FXP_DATA: - if (chunk->offset != filep->offset) { + if(chunk->offset != filep->offset) { /* This could happen if the server returns less bytes than requested, which shouldn't happen for normal files. See: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02 @@ -1622,7 +1642,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, } rc32 = _libssh2_ntohu32(data + 5); - if (rc32 > (data_len - 9)) + if(rc32 > (data_len - 9)) return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol badness"); @@ -1676,9 +1696,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, /* check if we have space left in the buffer * and either continue to the next chunk or stop */ - if (bytes_in_buffer < buffer_size) { + if(bytes_in_buffer < buffer_size) { chunk = next; - } else { + } + else { chunk = NULL; } @@ -1690,7 +1711,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, } } - if (bytes_in_buffer > 0) + if(bytes_in_buffer > 0) return bytes_in_buffer; break; @@ -1739,8 +1760,8 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, SSH_FXP_NAME, SSH_FXP_STATUS }; ssize_t retcode; - if (sftp->readdir_state == libssh2_NB_state_idle) { - if (handle->u.dir.names_left) { + if(sftp->readdir_state == libssh2_NB_state_idle) { + if(handle->u.dir.names_left) { /* * A prior request returned more than one directory entry, * feed it back from the buffer @@ -1750,29 +1771,53 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t real_filename_len; size_t filename_len; size_t longentry_len; + size_t names_packet_len = handle->u.dir.names_packet_len; + int attr_len = 0; - s = (unsigned char *) handle->u.dir.next_name; - real_filename_len = _libssh2_ntohu32(s); - - s += 4; - - filename_len = real_filename_len; - if (filename_len >= buffer_maxlen) { + if(names_packet_len >= 4) { + s = (unsigned char *) handle->u.dir.next_name; + real_filename_len = _libssh2_ntohu32(s); + s += 4; + names_packet_len -= 4; + } + else { filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL; goto end; } - memcpy(buffer, s, filename_len); - buffer[filename_len] = '\0'; /* zero terminate */ - s += real_filename_len; + filename_len = real_filename_len; + if(filename_len >= buffer_maxlen) { + filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL; + goto end; + } - real_longentry_len = _libssh2_ntohu32(s); - s += 4; + if(buffer_maxlen >= filename_len && names_packet_len >= + filename_len) { + memcpy(buffer, s, filename_len); + buffer[filename_len] = '\0'; /* zero terminate */ + s += real_filename_len; + names_packet_len -= real_filename_len; + } + else { + filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL; + goto end; + } - if (longentry && (longentry_maxlen>1)) { + if(names_packet_len >= 4) { + real_longentry_len = _libssh2_ntohu32(s); + s += 4; + names_packet_len -= 4; + } + else { + filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL; + goto end; + } + + if(longentry && (longentry_maxlen>1)) { longentry_len = real_longentry_len; - if (longentry_len >= longentry_maxlen) { + if(longentry_len >= longentry_maxlen || + longentry_len > names_packet_len) { filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL; goto end; } @@ -1780,17 +1825,36 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, memcpy(longentry, s, longentry_len); longentry[longentry_len] = '\0'; /* zero terminate */ } - s += real_longentry_len; - if (attrs) + if(real_longentry_len <= names_packet_len) { + s += real_longentry_len; + names_packet_len -= real_longentry_len; + } + else { + filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL; + goto end; + } + + if(attrs) memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - s += sftp_bin2attr(attrs ? attrs : &attrs_dummy, s, 32); + attr_len = sftp_bin2attr(attrs ? attrs : &attrs_dummy, s, + names_packet_len); + + if(attr_len >= 0) { + s += attr_len; + names_packet_len -= attr_len; + } + else { + filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL; + goto end; + } handle->u.dir.next_name = (char *) s; + handle->u.dir.names_packet_len = names_packet_len; end: - if ((--handle->u.dir.names_left) == 0) + if((--handle->u.dir.names_left) == 0) LIBSSH2_FREE(session, handle->u.dir.names_packet); _libssh2_debug(session, LIBSSH2_TRACE_SFTP, @@ -1802,7 +1866,7 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, /* Request another entry(entries?) */ s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->readdir_packet) + if(!sftp->readdir_packet) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "FXP_READDIR packet"); @@ -1816,15 +1880,15 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, sftp->readdir_state = libssh2_NB_state_created; } - if (sftp->readdir_state == libssh2_NB_state_created) { + if(sftp->readdir_state == libssh2_NB_state_created) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Reading entries from directory handle"); retcode = _libssh2_channel_write(channel, 0, sftp->readdir_packet, packet_len); - if (retcode == LIBSSH2_ERROR_EAGAIN) { + if(retcode == LIBSSH2_ERROR_EAGAIN) { return retcode; } - else if ((ssize_t)packet_len != retcode) { + else if((ssize_t)packet_len != retcode) { LIBSSH2_FREE(session, sftp->readdir_packet); sftp->readdir_packet = NULL; sftp->readdir_state = libssh2_NB_state_idle; @@ -1841,25 +1905,25 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, retcode = sftp_packet_requirev(sftp, 2, read_responses, sftp->readdir_request_id, &data, &data_len, 9); - if (retcode == LIBSSH2_ERROR_EAGAIN) + if(retcode == LIBSSH2_ERROR_EAGAIN) return retcode; - else if (retcode == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(retcode == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Status message too short"); + return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, + "Status message too short"); } - else if (retcode) { + else if(retcode) { sftp->readdir_state = libssh2_NB_state_idle; return _libssh2_error(session, retcode, "Timeout waiting for status message"); } - if (data[0] == SSH_FXP_STATUS) { + if(data[0] == SSH_FXP_STATUS) { retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_EOF) { + if(retcode == LIBSSH2_FX_EOF) { sftp->readdir_state = libssh2_NB_state_idle; return 0; } @@ -1876,7 +1940,7 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, num_names = _libssh2_ntohu32(data + 5); _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned", num_names); - if (!num_names) { + if(!num_names) { LIBSSH2_FREE(session, data); return 0; } @@ -1884,6 +1948,7 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, handle->u.dir.names_left = num_names; handle->u.dir.names_packet = data; handle->u.dir.next_name = (char *) data + 9; + handle->u.dir.names_packet_len = data_len - 9; /* use the name popping mechanism from the start of the function */ return sftp_readdir(handle, buffer, buffer_maxlen, longentry, @@ -1967,14 +2032,15 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, default: case libssh2_NB_state_idle: - /* Number of bytes sent off that haven't been acked and therefor we + /* Number of bytes sent off that haven't been acked and therefore we will get passed in here again. Also, add up the number of bytes that actually already have been acked but we haven't been able to return as such yet, so we will get that data as well passed in here again. */ - already = (size_t) (handle->u.file.offset_sent - handle->u.file.offset)+ + already = (size_t) (handle->u.file.offset_sent - + handle->u.file.offset)+ handle->u.file.acked; if(count >= already) { @@ -1999,7 +2065,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, chunk = LIBSSH2_ALLOC(session, packet_len + sizeof(struct sftp_pipeline_chunk)); - if (!chunk) + if(!chunk) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "malloc fail for FXP_WRITE"); @@ -2027,8 +2093,8 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, to create more packets */ } - /* move through the WRITE packets that haven't been sent and send as many - as possible - remember that we don't block */ + /* move through the WRITE packets that haven't been sent and send as + many as possible - remember that we don't block */ chunk = _libssh2_list_first(&handle->packet_list); while(chunk) { @@ -2076,15 +2142,15 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, /* we check the packets in order */ rc = sftp_packet_require(sftp, SSH_FXP_STATUS, chunk->request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "FXP write packet too short"); } - else if (rc < 0) { - if (rc == LIBSSH2_ERROR_EAGAIN) + else if(rc < 0) { + if(rc == LIBSSH2_ERROR_EAGAIN) sftp->write_state = libssh2_NB_state_sent; return rc; } @@ -2093,7 +2159,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, LIBSSH2_FREE(session, data); sftp->last_errno = retcode; - if (retcode == LIBSSH2_FX_OK) { + if(retcode == LIBSSH2_FX_OK) { acked += chunk->len; /* number of payload data that was acked here */ @@ -2113,7 +2179,8 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, /* since we return error now, the application will not get any outstanding data acked, so we need to rewind the offset to - where the application knows it has reached with acked data */ + where the application knows it has reached with acked + data */ handle->u.file.offset -= handle->u.file.acked; /* then reset the offset_sent to be the same as the offset */ @@ -2123,8 +2190,8 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, ack after an error */ handle->u.file.acked = 0; - /* the server returned an error for that written chunk, propagate - this back to our parent function */ + /* the server returned an error for that written chunk, + propagate this back to our parent function */ return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "FXP write failed"); } @@ -2183,11 +2250,11 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle) ssize_t rc; uint32_t retcode; - if (sftp->fsync_state == libssh2_NB_state_idle) { + if(sftp->fsync_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing fsync command"); s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { + if(!packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_EXTENDED " "packet"); @@ -2201,13 +2268,14 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle) _libssh2_store_str(&s, handle->handle, handle->handle_len); sftp->fsync_state = libssh2_NB_state_created; - } else { + } + else { packet = sftp->fsync_packet; } - if (sftp->fsync_state == libssh2_NB_state_created) { + if(sftp->fsync_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN || + if(rc == LIBSSH2_ERROR_EAGAIN || (0 <= rc && rc < (ssize_t)packet_len)) { sftp->fsync_packet = packet; return LIBSSH2_ERROR_EAGAIN; @@ -2216,7 +2284,7 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle) LIBSSH2_FREE(session, packet); sftp->fsync_packet = NULL; - if (rc < 0) { + if(rc < 0) { sftp->fsync_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "_libssh2_channel_write() failed"); @@ -2226,17 +2294,17 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle) rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->fsync_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP fsync packet too short"); } - else if (rc) { + else if(rc) { sftp->fsync_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Error waiting for FXP EXTENDED REPLY"); @@ -2247,7 +2315,7 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle) retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode != LIBSSH2_FX_OK) { + if(retcode != LIBSSH2_FX_OK) { sftp->last_errno = retcode; return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "fsync failed"); @@ -2291,11 +2359,11 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle, { SSH_FXP_ATTRS, SSH_FXP_STATUS }; ssize_t rc; - if (sftp->fstat_state == libssh2_NB_state_idle) { + if(sftp->fstat_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command", setstat ? "set-stat" : "stat"); s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->fstat_packet) { + if(!sftp->fstat_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "FSTAT/FSETSTAT packet"); @@ -2307,20 +2375,20 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle, _libssh2_store_u32(&s, sftp->fstat_request_id); _libssh2_store_str(&s, handle->handle, handle->handle_len); - if (setstat) { + if(setstat) { s += sftp_attr2bin(s, attrs); } sftp->fstat_state = libssh2_NB_state_created; } - if (sftp->fstat_state == libssh2_NB_state_created) { + if(sftp->fstat_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, sftp->fstat_packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if ((ssize_t)packet_len != rc) { + else if((ssize_t)packet_len != rc) { LIBSSH2_FREE(session, sftp->fstat_packet); sftp->fstat_packet = NULL; sftp->fstat_state = libssh2_NB_state_idle; @@ -2337,16 +2405,16 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle, rc = sftp_packet_requirev(sftp, 2, fstat_responses, sftp->fstat_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP fstat packet too short"); } - else if (rc) { + else if(rc) { sftp->fstat_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Timeout waiting for status message"); @@ -2354,21 +2422,22 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle, sftp->fstat_state = libssh2_NB_state_idle; - if (data[0] == SSH_FXP_STATUS) { + if(data[0] == SSH_FXP_STATUS) { uint32_t retcode; retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) { + if(retcode == LIBSSH2_FX_OK) { return 0; - } else { + } + else { sftp->last_errno = retcode; return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error"); } } - if (sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) { + if(sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) { LIBSSH2_FREE(session, data); return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Attributes too short in SFTP fstat"); @@ -2411,7 +2480,7 @@ libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset) sftp_packetlist_flush(handle); /* free the left received buffered data */ - if (handle->u.file.data_left) { + if(handle->u.file.data_left) { LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data); handle->u.file.data_left = handle->u.file.data_len = 0; handle->u.file.data = NULL; @@ -2512,15 +2581,16 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) unsigned char *s, *data = NULL; int rc = 0; - if (handle->close_state == libssh2_NB_state_idle) { + if(handle->close_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle"); s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len); - if (!handle->close_packet) { + if(!handle->close_packet) { handle->close_state = libssh2_NB_state_idle; rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_CLOSE " "packet"); - } else { + } + else { _libssh2_store_u32(&s, packet_len - 4); *(s++) = SSH_FXP_CLOSE; @@ -2531,38 +2601,40 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) } } - if (handle->close_state == libssh2_NB_state_created) { + if(handle->close_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, handle->close_packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if ((ssize_t)packet_len != rc) { + } + else if((ssize_t)packet_len != rc) { handle->close_state = libssh2_NB_state_idle; rc = _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_CLOSE command"); - } else + } + else handle->close_state = libssh2_NB_state_sent; LIBSSH2_FREE(session, handle->close_packet); handle->close_packet = NULL; } - if (handle->close_state == libssh2_NB_state_sent) { + if(handle->close_state == libssh2_NB_state_sent) { rc = sftp_packet_require(sftp, SSH_FXP_STATUS, handle->close_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } data = NULL; _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Packet too short in FXP_CLOSE command"); } - else if (rc) { + else if(rc) { _libssh2_error(session, rc, "Error waiting for status message"); } @@ -2575,11 +2647,12 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) happened for which we should have set an error code */ assert(rc); - } else { + } + else { int retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode != LIBSSH2_FX_OK) { + if(retcode != LIBSSH2_FX_OK) { sftp->last_errno = retcode; handle->close_state = libssh2_NB_state_idle; rc = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, @@ -2590,11 +2663,11 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) /* remove this handle from the parent's list */ _libssh2_list_remove(&handle->node); - if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) - && handle->u.dir.names_left) { - LIBSSH2_FREE(session, handle->u.dir.names_packet); + if(handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) { + if(handle->u.dir.names_left) + LIBSSH2_FREE(session, handle->u.dir.names_packet); } - else { + else if(handle->handle_type == LIBSSH2_SFTP_HANDLE_FILE) { if(handle->u.file.data) LIBSSH2_FREE(session, handle->u.file.data); } @@ -2639,10 +2712,10 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename, unsigned char *s, *data; int rc; - if (sftp->unlink_state == libssh2_NB_state_idle) { + if(sftp->unlink_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename); s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->unlink_packet) { + if(!sftp->unlink_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_REMOVE " "packet"); @@ -2656,12 +2729,13 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename, sftp->unlink_state = libssh2_NB_state_created; } - if (sftp->unlink_state == libssh2_NB_state_created) { + if(sftp->unlink_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, sftp->unlink_packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if ((ssize_t)packet_len != rc) { + } + else if((ssize_t)packet_len != rc) { LIBSSH2_FREE(session, sftp->unlink_packet); sftp->unlink_packet = NULL; sftp->unlink_state = libssh2_NB_state_idle; @@ -2677,17 +2751,17 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename, rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->unlink_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP unlink packet too short"); } - else if (rc) { + else if(rc) { sftp->unlink_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Error waiting for FXP STATUS"); @@ -2698,9 +2772,10 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename, retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) { + if(retcode == LIBSSH2_FX_OK) { return 0; - } else { + } + else { sftp->last_errno = retcode; return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error"); @@ -2744,17 +2819,17 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename, unsigned char *data; ssize_t rc; - if (sftp->version < 2) { + if(sftp->version < 2) { return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Server does not support RENAME"); } - if (sftp->rename_state == libssh2_NB_state_idle) { + if(sftp->rename_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s", source_filename, dest_filename); sftp->rename_s = sftp->rename_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->rename_packet) { + if(!sftp->rename_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_RENAME " "packet"); @@ -2768,18 +2843,19 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename, source_filename_len); _libssh2_store_str(&sftp->rename_s, dest_filename, dest_filename_len); - if (sftp->version >= 5) + if(sftp->version >= 5) _libssh2_store_u32(&sftp->rename_s, flags); sftp->rename_state = libssh2_NB_state_created; } - if (sftp->rename_state == libssh2_NB_state_created) { + if(sftp->rename_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, sftp->rename_packet, sftp->rename_s - sftp->rename_packet); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if ((ssize_t)packet_len != rc) { + } + else if((ssize_t)packet_len != rc) { LIBSSH2_FREE(session, sftp->rename_packet); sftp->rename_packet = NULL; sftp->rename_state = libssh2_NB_state_idle; @@ -2795,17 +2871,17 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename, rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->rename_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP rename packet too short"); } - else if (rc) { + else if(rc) { sftp->rename_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Error waiting for FXP STATUS"); @@ -2820,7 +2896,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename, /* now convert the SFTP error code to libssh2 return code or error message */ - switch (retcode) { + switch(retcode) { case LIBSSH2_FX_OK: retcode = LIBSSH2_ERROR_NONE; break; @@ -2884,11 +2960,11 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) static const unsigned char responses[2] = { SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS }; - if (sftp->fstatvfs_state == libssh2_NB_state_idle) { + if(sftp->fstatvfs_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Getting file system statistics"); s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { + if(!packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_EXTENDED " "packet"); @@ -2907,9 +2983,9 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) packet = sftp->fstatvfs_packet; } - if (sftp->fstatvfs_state == libssh2_NB_state_created) { + if(sftp->fstatvfs_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN || + if(rc == LIBSSH2_ERROR_EAGAIN || (0 <= rc && rc < (ssize_t)packet_len)) { sftp->fstatvfs_packet = packet; return LIBSSH2_ERROR_EAGAIN; @@ -2918,7 +2994,7 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) LIBSSH2_FREE(session, packet); sftp->fstatvfs_packet = NULL; - if (rc < 0) { + if(rc < 0) { sftp->fstatvfs_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "_libssh2_channel_write() failed"); @@ -2929,23 +3005,23 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) rc = sftp_packet_requirev(sftp, 2, responses, sftp->fstatvfs_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP rename packet too short"); } - else if (rc) { + else if(rc) { sftp->fstatvfs_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Error waiting for FXP EXTENDED REPLY"); } - if (data[0] == SSH_FXP_STATUS) { + if(data[0] == SSH_FXP_STATUS) { int retcode = _libssh2_ntohu32(data + 5); sftp->fstatvfs_state = libssh2_NB_state_idle; LIBSSH2_FREE(session, data); @@ -2954,7 +3030,7 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) "SFTP Protocol Error"); } - if (data_len < 93) { + if(data_len < 93) { LIBSSH2_FREE(session, data); sftp->fstatvfs_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, @@ -2994,7 +3070,8 @@ libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) int rc; if(!handle || !st) return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, handle->sftp->channel->session, sftp_fstatvfs(handle, st)); + BLOCK_ADJUST(rc, handle->sftp->channel->session, + sftp_fstatvfs(handle, st)); return rc; } @@ -3019,11 +3096,11 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, static const unsigned char responses[2] = { SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS }; - if (sftp->statvfs_state == libssh2_NB_state_idle) { + if(sftp->statvfs_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Getting file system statistics of %s", path); s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { + if(!packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_EXTENDED " "packet"); @@ -3042,9 +3119,9 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, packet = sftp->statvfs_packet; } - if (sftp->statvfs_state == libssh2_NB_state_created) { + if(sftp->statvfs_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN || + if(rc == LIBSSH2_ERROR_EAGAIN || (0 <= rc && rc < (ssize_t)packet_len)) { sftp->statvfs_packet = packet; return LIBSSH2_ERROR_EAGAIN; @@ -3053,7 +3130,7 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_FREE(session, packet); sftp->statvfs_packet = NULL; - if (rc < 0) { + if(rc < 0) { sftp->statvfs_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "_libssh2_channel_write() failed"); @@ -3063,23 +3140,23 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, rc = sftp_packet_requirev(sftp, 2, responses, sftp->statvfs_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP fstat packet too short"); } - else if (rc) { + else if(rc) { sftp->statvfs_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Error waiting for FXP EXTENDED REPLY"); } - if (data[0] == SSH_FXP_STATUS) { + if(data[0] == SSH_FXP_STATUS) { int retcode = _libssh2_ntohu32(data + 5); sftp->statvfs_state = libssh2_NB_state_idle; LIBSSH2_FREE(session, data); @@ -3088,7 +3165,7 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, "SFTP Protocol Error"); } - if (data_len < 93) { + if(data_len < 93) { LIBSSH2_FREE(session, data); sftp->statvfs_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, @@ -3146,27 +3223,32 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path, LIBSSH2_CHANNEL *channel = sftp->channel; LIBSSH2_SESSION *session = channel->session; LIBSSH2_SFTP_ATTRIBUTES attrs = { - LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0 }; size_t data_len; int retcode; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */ - ssize_t packet_len = path_len + 13 + - sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS); + ssize_t packet_len; unsigned char *packet, *s, *data; int rc; - if (sftp->mkdir_state == libssh2_NB_state_idle) { + if(mode != LIBSSH2_SFTP_DEFAULT_MODE) { + /* Filetype in SFTP 3 and earlier */ + attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; + attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR; + } + + /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */ + packet_len = path_len + 13 + sftp_attrsize(attrs.flags); + + if(sftp->mkdir_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Creating directory %s with mode 0%lo", path, mode); s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { + if(!packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_MKDIR " "packet"); } - /* Filetype in SFTP 3 and earlier */ - attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR; _libssh2_store_u32(&s, packet_len - 4); *(s++) = SSH_FXP_MKDIR; @@ -3182,13 +3264,13 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path, packet = sftp->mkdir_packet; } - if (sftp->mkdir_state == libssh2_NB_state_created) { + if(sftp->mkdir_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { sftp->mkdir_packet = packet; return rc; } - if (packet_len != rc) { + if(packet_len != rc) { LIBSSH2_FREE(session, packet); sftp->mkdir_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, @@ -3201,17 +3283,17 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path, rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP mkdir packet too short"); } - else if (rc) { + else if(rc) { sftp->mkdir_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Error waiting for FXP STATUS"); @@ -3222,10 +3304,11 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path, retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) { + if(retcode == LIBSSH2_FX_OK) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!"); return 0; - } else { + } + else { sftp->last_errno = retcode; return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error"); @@ -3264,11 +3347,11 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path, unsigned char *s, *data; int rc; - if (sftp->rmdir_state == libssh2_NB_state_idle) { + if(sftp->rmdir_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Removing directory: %s", path); s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->rmdir_packet) { + if(!sftp->rmdir_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_RMDIR " "packet"); @@ -3283,12 +3366,13 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path, sftp->rmdir_state = libssh2_NB_state_created; } - if (sftp->rmdir_state == libssh2_NB_state_created) { + if(sftp->rmdir_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, sftp->rmdir_packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (packet_len != rc) { + } + else if(packet_len != rc) { LIBSSH2_FREE(session, sftp->rmdir_packet); sftp->rmdir_packet = NULL; sftp->rmdir_state = libssh2_NB_state_idle; @@ -3303,17 +3387,17 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path, rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->rmdir_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; } - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP rmdir packet too short"); } - else if (rc) { + else if(rc) { sftp->rmdir_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Error waiting for FXP STATUS"); @@ -3324,9 +3408,10 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path, retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) { + if(retcode == LIBSSH2_FX_OK) { return 0; - } else { + } + else { sftp->last_errno = retcode; return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error"); @@ -3368,13 +3453,13 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path, { SSH_FXP_ATTRS, SSH_FXP_STATUS }; int rc; - if (sftp->stat_state == libssh2_NB_state_idle) { + if(sftp->stat_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s", (stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" : (stat_type == LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path); s = sftp->stat_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->stat_packet) { + if(!sftp->stat_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_*STAT " "packet"); @@ -3382,7 +3467,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path, _libssh2_store_u32(&s, packet_len - 4); - switch (stat_type) { + switch(stat_type) { case LIBSSH2_SFTP_SETSTAT: *(s++) = SSH_FXP_SETSTAT; break; @@ -3399,17 +3484,18 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path, _libssh2_store_u32(&s, sftp->stat_request_id); _libssh2_store_str(&s, path, path_len); - if (stat_type == LIBSSH2_SFTP_SETSTAT) + if(stat_type == LIBSSH2_SFTP_SETSTAT) s += sftp_attr2bin(s, attrs); sftp->stat_state = libssh2_NB_state_created; } - if (sftp->stat_state == libssh2_NB_state_created) { + if(sftp->stat_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, sftp->stat_packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return rc; - } else if (packet_len != rc) { + } + else if(packet_len != rc) { LIBSSH2_FREE(session, sftp->stat_packet); sftp->stat_packet = NULL; sftp->stat_state = libssh2_NB_state_idle; @@ -3424,16 +3510,16 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path, rc = sftp_packet_requirev(sftp, 2, stat_responses, sftp->stat_request_id, &data, &data_len, 9); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; - else if (rc == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP stat packet too short"); } - else if (rc) { + else if(rc) { sftp->stat_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Timeout waiting for status message"); @@ -3441,14 +3527,16 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path, sftp->stat_state = libssh2_NB_state_idle; - if (data[0] == SSH_FXP_STATUS) { + if(data[0] == SSH_FXP_STATUS) { int retcode; retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) { + if(retcode == LIBSSH2_FX_OK) { + memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); return 0; - } else { + } + else { sftp->last_errno = retcode; return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error"); @@ -3456,7 +3544,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path, } memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - if (sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) { + if(sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) { LIBSSH2_FREE(session, data); return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Attributes too short in SFTP fstat"); @@ -3502,14 +3590,14 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, { SSH_FXP_NAME, SSH_FXP_STATUS }; int retcode; - if ((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) { + if((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) { return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Server does not support SYMLINK or READLINK"); } - if (sftp->symlink_state == libssh2_NB_state_idle) { + if(sftp->symlink_state == libssh2_NB_state_idle) { s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->symlink_packet) { + if(!sftp->symlink_packet) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "SYMLINK/READLINK/REALPATH packet"); @@ -3523,7 +3611,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, _libssh2_store_u32(&s, packet_len - 4); - switch (link_type) { + switch(link_type) { case LIBSSH2_SFTP_REALPATH: *(s++) = SSH_FXP_REALPATH; break; @@ -3540,18 +3628,18 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, _libssh2_store_u32(&s, sftp->symlink_request_id); _libssh2_store_str(&s, path, path_len); - if (link_type == LIBSSH2_SFTP_SYMLINK) + if(link_type == LIBSSH2_SFTP_SYMLINK) _libssh2_store_str(&s, target, target_len); sftp->symlink_state = libssh2_NB_state_created; } - if (sftp->symlink_state == libssh2_NB_state_created) { + if(sftp->symlink_state == libssh2_NB_state_created) { ssize_t rc = _libssh2_channel_write(channel, 0, sftp->symlink_packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; - else if (packet_len != rc) { + else if(packet_len != rc) { LIBSSH2_FREE(session, sftp->symlink_packet); sftp->symlink_packet = NULL; sftp->symlink_state = libssh2_NB_state_idle; @@ -3567,16 +3655,16 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, retcode = sftp_packet_requirev(sftp, 2, link_responses, sftp->symlink_request_id, &data, &data_len, 9); - if (retcode == LIBSSH2_ERROR_EAGAIN) + if(retcode == LIBSSH2_ERROR_EAGAIN) return retcode; - else if (retcode == LIBSSH2_ERROR_OUT_OF_BOUNDARY) { - if (data_len > 0) { + else if(retcode == LIBSSH2_ERROR_BUFFER_TOO_SMALL) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP symlink packet too short"); } - else if (retcode) { + else if(retcode) { sftp->symlink_state = libssh2_NB_state_idle; return _libssh2_error(session, retcode, "Error waiting for status message"); @@ -3584,12 +3672,10 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, sftp->symlink_state = libssh2_NB_state_idle; - if (data[0] == SSH_FXP_STATUS) { - int retcode; - + if(data[0] == SSH_FXP_STATUS) { retcode = _libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) + if(retcode == LIBSSH2_FX_OK) return LIBSSH2_ERROR_NONE; else { sftp->last_errno = retcode; @@ -3598,15 +3684,15 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, } } - if (_libssh2_ntohu32(data + 5) < 1) { + if(_libssh2_ntohu32(data + 5) < 1) { LIBSSH2_FREE(session, data); return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Invalid READLINK/REALPATH response, " "no name entries"); } - if (data_len < 13) { - if (data_len > 0) { + if(data_len < 13) { + if(data_len > 0) { LIBSSH2_FREE(session, data); } return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, @@ -3615,7 +3701,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, /* this reads a u32 and stores it into a signed 32bit value */ link_len = _libssh2_ntohu32(data + 9); - if (link_len < target_len) { + if(link_len < target_len) { memcpy(target, data + 13, link_len); target[link_len] = 0; retcode = (int)link_len; @@ -3662,7 +3748,7 @@ libssh2_sftp_last_error(LIBSSH2_SFTP *sftp) LIBSSH2_API LIBSSH2_CHANNEL * libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp) { - if (!sftp) + if(!sftp) return NULL; return sftp->channel; diff --git a/libssh2/src/sftp.h b/libssh2/src/sftp.h index 2ed32cea6..ae4162f10 100644 --- a/libssh2/src/sftp.h +++ b/libssh2/src/sftp.h @@ -122,6 +122,7 @@ struct _LIBSSH2_SFTP_HANDLE uint32_t names_left; void *names_packet; char *next_name; + size_t names_packet_len; } dir; } u; diff --git a/libssh2/src/transport.c b/libssh2/src/transport.c index 7317579f3..45e445c74 100644 --- a/libssh2/src/transport.c +++ b/libssh2/src/transport.c @@ -65,16 +65,16 @@ debugdump(LIBSSH2_SESSION * session, unsigned int width = 0x10; char buffer[256]; /* Must be enough for width*4 + about 30 or so */ size_t used; - static const char* hex_chars = "0123456789ABCDEF"; + static const char *hex_chars = "0123456789ABCDEF"; - if (!(session->showmask & LIBSSH2_TRACE_TRANS)) { + if(!(session->showmask & LIBSSH2_TRACE_TRANS)) { /* not asked for, bail out */ return; } used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n", desc, (int) size); - if (session->tracehandler) + if(session->tracehandler) (session->tracehandler)(session, session->tracehandler_context, buffer, used); else @@ -86,9 +86,9 @@ debugdump(LIBSSH2_SESSION * session, /* hex not disabled, show it */ for(c = 0; c < width; c++) { - if (i + c < size) { - buffer[used++] = hex_chars[(ptr[i+c] >> 4) & 0xF]; - buffer[used++] = hex_chars[ptr[i+c] & 0xF]; + if(i + c < size) { + buffer[used++] = hex_chars[(ptr[i + c] >> 4) & 0xF]; + buffer[used++] = hex_chars[ptr[i + c] & 0xF]; } else { buffer[used++] = ' '; @@ -96,7 +96,7 @@ debugdump(LIBSSH2_SESSION * session, } buffer[used++] = ' '; - if ((width/2) - 1 == c) + if((width/2) - 1 == c) buffer[used++] = ' '; } @@ -110,7 +110,7 @@ debugdump(LIBSSH2_SESSION * session, buffer[used++] = '\n'; buffer[used] = 0; - if (session->tracehandler) + if(session->tracehandler) (session->tracehandler)(session, session->tracehandler_context, buffer, used); else @@ -138,8 +138,8 @@ decrypt(LIBSSH2_SESSION * session, unsigned char *source, we risk losing those extra bytes */ assert((len % blocksize) == 0); - while (len >= blocksize) { - if (session->remote.crypt->crypt(session, source, blocksize, + while(len >= blocksize) { + if(session->remote.crypt->crypt(session, source, blocksize, &session->remote.crypt_abstract)) { LIBSSH2_FREE(session, p->payload); return LIBSSH2_ERROR_DECRYPT; @@ -169,11 +169,11 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) int rc; int compressed; - if (session->fullpacket_state == libssh2_NB_state_idle) { + if(session->fullpacket_state == libssh2_NB_state_idle) { session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED; session->fullpacket_payload_len = p->packet_length - 1; - if (encrypted) { + if(encrypted) { /* Calculate MAC hash */ session->remote.mac->hash(session, macbuf, /* store hash here */ @@ -188,7 +188,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) * buffer. Note that 'payload_len' here is the packet_length * field which includes the padding but not the MAC. */ - if (memcmp(macbuf, p->payload + session->fullpacket_payload_len, + if(memcmp(macbuf, p->payload + session->fullpacket_payload_len, session->remote.mac->mac_len)) { session->fullpacket_macstate = LIBSSH2_MAC_INVALID; } @@ -206,7 +206,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) ((session->state & LIBSSH2_STATE_AUTHENTICATED) || session->local.comp->use_in_auth); - if (compressed && session->remote.comp_abstract) { + if(compressed && session->remote.comp_abstract) { /* * The buffer for the decompression (remote.comp_abstract) is * initialised in time when it is needed so as long it is NULL we @@ -237,13 +237,13 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) session->fullpacket_state = libssh2_NB_state_created; } - if (session->fullpacket_state == libssh2_NB_state_created) { + if(session->fullpacket_state == libssh2_NB_state_created) { rc = _libssh2_packet_add(session, p->payload, session->fullpacket_payload_len, session->fullpacket_macstate); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return rc; - if (rc) { + if(rc) { session->fullpacket_state = libssh2_NB_state_idle; return rc; } @@ -281,7 +281,6 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) unsigned char block[MAX_BLOCKSIZE]; int blocksize; int encrypted = 1; - size_t total_num; /* default clear the bit */ session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; @@ -298,7 +297,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) * of packet_read, then don't redirect, as that would be an infinite loop! */ - if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS && + if(session->state & LIBSSH2_STATE_EXCHANGING_KEYS && !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) { /* Whoever wants a packet won't get anything until the key re-exchange @@ -307,7 +306,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the" " key re-exchange from _libssh2_transport_read"); rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); - if (rc) + if(rc) return rc; } @@ -316,20 +315,21 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) * I know this is very ugly and not a really good use of "goto", but * this case statement would be even uglier to do it any other way */ - if (session->readPack_state == libssh2_NB_state_jump1) { + if(session->readPack_state == libssh2_NB_state_jump1) { session->readPack_state = libssh2_NB_state_idle; encrypted = session->readPack_encrypted; goto libssh2_transport_read_point1; } do { - if (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) { + if(session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) { return LIBSSH2_ERROR_NONE; } - if (session->state & LIBSSH2_STATE_NEWKEYS) { + if(session->state & LIBSSH2_STATE_NEWKEYS) { blocksize = session->remote.crypt->blocksize; - } else { + } + else { encrypted = 0; /* not encrypted */ blocksize = 5; /* not strictly true, but we can use 5 here to make the checks below work fine still */ @@ -348,18 +348,19 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) /* if remainbuf turns negative we have a bad internal error */ assert(remainbuf >= 0); - if (remainbuf < blocksize) { + if(remainbuf < blocksize) { /* If we have less than a blocksize left, it is too little data to deal with, read more */ ssize_t nread; /* move any remainder to the start of the buffer so that we can do a full refill */ - if (remainbuf) { + if(remainbuf) { memmove(p->buf, &p->buf[p->readidx], remainbuf); p->readidx = 0; p->writeidx = remainbuf; - } else { + } + else { /* nothing to move, just zero the indexes */ p->readidx = p->writeidx = 0; } @@ -369,10 +370,10 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) LIBSSH2_RECV(session, &p->buf[remainbuf], PACKETBUFSIZE - remainbuf, LIBSSH2_SOCKET_RECV_FLAGS(session)); - if (nread <= 0) { + if(nread <= 0) { /* check if this is due to EAGAIN and return the special return code if so, error out normally otherwise */ - if ((nread < 0) && (nread == -EAGAIN)) { + if((nread < 0) && (nread == -EAGAIN)) { session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_INBOUND; return LIBSSH2_ERROR_EAGAIN; @@ -398,12 +399,14 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) /* how much data to deal with from the buffer */ numbytes = remainbuf; - if (!p->total_num) { + if(!p->total_num) { + size_t total_num; + /* No payload package area allocated yet. To know the size of this payload, we need to decrypt the first blocksize data. */ - if (numbytes < blocksize) { + if(numbytes < blocksize) { /* we can't act on anything less than blocksize, but this check is only done for the initial block since once we have got the start of a block we can in fact deal with fractions @@ -413,15 +416,16 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) return LIBSSH2_ERROR_EAGAIN; } - if (encrypted) { + if(encrypted) { rc = decrypt(session, &p->buf[p->readidx], block, blocksize); - if (rc != LIBSSH2_ERROR_NONE) { + if(rc != LIBSSH2_ERROR_NONE) { return rc; } /* save the first 5 bytes of the decrypted package, to be used in the hash calculation later down. */ - memcpy(p->init, &p->buf[p->readidx], 5); - } else { + memcpy(p->init, block, 5); + } + else { /* the data is plain, just copy it verbatim to the working block buffer */ memcpy(block, &p->buf[p->readidx], blocksize); @@ -434,17 +438,15 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) * and we can extract packet and padding length from it */ p->packet_length = _libssh2_ntohu32(block); - if (p->packet_length < 1) - return LIBSSH2_ERROR_DECRYPT; - - p->padding_length = block[4]; if(p->packet_length < 1) { return LIBSSH2_ERROR_DECRYPT; } else if(p->packet_length > LIBSSH2_PACKET_MAXPAYLOAD) { return LIBSSH2_ERROR_OUT_OF_BOUNDARY; } - else if ( p->padding_length > p->packet_length - 1 ) { + + p->padding_length = block[4]; + if(p->padding_length > p->packet_length - 1) { return LIBSSH2_ERROR_DECRYPT; } @@ -463,28 +465,29 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) * or less (including length, padding length, payload, * padding, and MAC.)." */ - if (total_num > LIBSSH2_PACKET_MAXPAYLOAD) { + if(total_num > LIBSSH2_PACKET_MAXPAYLOAD) { return LIBSSH2_ERROR_OUT_OF_BOUNDARY; } /* Get a packet handle put data into. We get one to hold all data, including padding and MAC. */ p->payload = LIBSSH2_ALLOC(session, total_num); - if (!p->payload) { + if(!p->payload) { return LIBSSH2_ERROR_ALLOC; } p->total_num = total_num; /* init write pointer to start of payload buffer */ p->wptr = p->payload; - if (blocksize > 5) { + if(blocksize > 5) { /* copy the data from index 5 to the end of the blocksize from the temporary buffer to the start of the decrypted buffer */ - if (blocksize - 5 <= total_num) { + if(blocksize - 5 <= (int) total_num) { memcpy(p->wptr, &block[5], blocksize - 5); p->wptr += blocksize - 5; /* advance write pointer */ - } else { + } + else { return LIBSSH2_ERROR_OUT_OF_BOUNDARY; } } @@ -501,13 +504,13 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) package */ remainpack = p->total_num - p->data_num; - if (numbytes > remainpack) { + if(numbytes > remainpack) { /* if we have more data in the buffer than what is going into this particular packet, we limit this round to this packet only */ numbytes = remainpack; } - if (encrypted) { + if(encrypted) { /* At the end of the incoming stream, there is a MAC, and we don't want to decrypt that since we need it "raw". We MUST however decrypt the padding data @@ -517,13 +520,14 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) /* if what we have plus numbytes is bigger than the total minus the skip margin, we should lower the amount to decrypt even more */ - if ((p->data_num + numbytes) > (p->total_num - skip)) { + if((p->data_num + numbytes) > (p->total_num - skip)) { numdecrypt = (p->total_num - skip) - p->data_num; - } else { + } + else { int frac; numdecrypt = numbytes; frac = numdecrypt % blocksize; - if (frac) { + if(frac) { /* not an aligned amount of blocks, align it */ numdecrypt -= frac; @@ -532,16 +536,17 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) numbytes = 0; } } - } else { + } + else { /* unencrypted data should not be decrypted at all */ numdecrypt = 0; } /* if there are bytes to decrypt, do that */ - if (numdecrypt > 0) { + if(numdecrypt > 0) { /* now decrypt the lot */ rc = decrypt(session, &p->buf[p->readidx], p->wptr, numdecrypt); - if (rc != LIBSSH2_ERROR_NONE) { + if(rc != LIBSSH2_ERROR_NONE) { p->total_num = 0; /* no packet buffer available */ return rc; } @@ -559,9 +564,9 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) /* if there are bytes to copy that aren't decrypted, simply copy them as-is to the target buffer */ - if (numbytes > 0) { - - if (numbytes <= total_num - (p->wptr - p->payload)) { + if(numbytes > 0) { + + if(numbytes <= (int)(p->total_num - (p->wptr - p->payload))) { memcpy(p->wptr, &p->buf[p->readidx], numbytes); } else { @@ -580,21 +585,21 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) current packet */ remainpack = p->total_num - p->data_num; - if (!remainpack) { + if(!remainpack) { /* we have a full packet */ libssh2_transport_read_point1: rc = fullpacket(session, encrypted); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { - if (session->packAdd_state != libssh2_NB_state_idle) - { + if(session->packAdd_state != libssh2_NB_state_idle) { /* fullpacket only returns LIBSSH2_ERROR_EAGAIN if - * libssh2_packet_add returns LIBSSH2_ERROR_EAGAIN. If that - * returns LIBSSH2_ERROR_EAGAIN but the packAdd_state is idle, - * then the packet has been added to the brigade, but some - * immediate action that was taken based on the packet - * type (such as key re-exchange) is not yet complete. - * Clear the way for a new packet to be read in. + * libssh2_packet_add returns LIBSSH2_ERROR_EAGAIN. If + * that returns LIBSSH2_ERROR_EAGAIN but the packAdd_state + * is idle, then the packet has been added to the brigade, + * but some immediate action that was taken based on the + * packet type (such as key re-exchange) is not yet + * complete. Clear the way for a new packet to be read + * in. */ session->readPack_encrypted = encrypted; session->readPack_state = libssh2_NB_state_jump1; @@ -607,7 +612,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) return rc; } - } while (1); /* loop */ + } while(1); /* loop */ return LIBSSH2_ERROR_SOCKET_RECV; /* we never reach this point */ } @@ -620,13 +625,13 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data, ssize_t length; struct transportpacket *p = &session->packet; - if (!p->olen) { + if(!p->olen) { *ret = 0; return LIBSSH2_ERROR_NONE; } /* send as much as possible of the existing packet */ - if ((data != p->odata) || (data_len != p->olen)) { + if((data != p->odata) || (data_len != p->olen)) { /* When we are about to complete the sending of a packet, it is vital that the caller doesn't try to send a new/different packet since we don't add this one up until the previous one has been sent. To @@ -642,7 +647,7 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data, rc = LIBSSH2_SEND(session, &p->outbuf[p->osent], length, LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (rc < 0) + if(rc < 0) _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Error sending %d bytes: %d", length, -rc); else { @@ -653,7 +658,7 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data, &p->outbuf[p->osent], rc); } - if (rc == length) { + if(rc == length) { /* the remainder of the package was sent */ p->ototal_num = 0; p->olen = 0; @@ -663,9 +668,9 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data, return LIBSSH2_ERROR_NONE; } - else if (rc < 0) { + else if(rc < 0) { /* nothing was sent */ - if (rc != -EAGAIN) + if(rc != -EAGAIN) /* send failure! */ return LIBSSH2_ERROR_SOCKET_SEND; @@ -725,14 +730,14 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, * * See the similar block in _libssh2_transport_read for more details. */ - if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS && + if(session->state & LIBSSH2_STATE_EXCHANGING_KEYS && !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) { /* Don't write any new packets if we're still in the middle of a key * exchange. */ _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the" " key re-exchange from _libssh2_transport_send"); rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); - if (rc) + if(rc) return rc; } @@ -743,12 +748,12 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, /* FIRST, check if we have a pending write to complete. send_existing only sanity-check data and data_len and not data2 and data2_len!! */ rc = send_existing(session, data, data_len, &ret); - if (rc) + if(rc) return rc; session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND; - if (ret) + if(ret) /* set by send_existing if data was sent */ return rc; @@ -760,7 +765,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, ((session->state & LIBSSH2_STATE_AUTHENTICATED) || session->local.comp->use_in_auth); - if (encrypted && compressed) { + if(encrypted && compressed) { /* the idea here is that these function must fail if the output gets larger than what fits in the assigned buffer so thus they don't check the input size as we don't know how much it compresses */ @@ -781,7 +786,8 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, dest2_len -= dest_len; rc = session->local.comp->comp(session, - &p->outbuf[5+dest_len], &dest2_len, + &p->outbuf[5 + dest_len], + &dest2_len, data2, data2_len, &session->local.comp_abstract); } @@ -801,7 +807,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, /* copy the payload data */ memcpy(&p->outbuf[5], data, data_len); if(data2 && data2_len) - memcpy(&p->outbuf[5+data_len], data2, data2_len); + memcpy(&p->outbuf[5 + data_len], data2, data2_len); data_len += data2_len; /* use the combined length */ } @@ -825,7 +831,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, /* if the padding becomes too small we add another blocksize worth of it (taken from the original libssh2 where it didn't have any real explanation) */ - if (padding_length < 4) { + if(padding_length < 4) { padding_length += blocksize; } #ifdef RANDOM_PADDING @@ -854,7 +860,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, /* fill the padding area with random junk */ _libssh2_random(p->outbuf + 5 + data_len, padding_length); - if (encrypted) { + if(encrypted) { size_t i; /* Calculate MAC hash. Put the output at index packet_length, @@ -870,7 +876,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, The MAC field is not encrypted. */ for(i = 0; i < packet_length; i += session->local.crypt->blocksize) { unsigned char *ptr = &p->outbuf[i]; - if (session->local.crypt->crypt(session, ptr, + if(session->local.crypt->crypt(session, ptr, session->local.crypt->blocksize, &session->local.crypt_abstract)) return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */ @@ -881,7 +887,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, ret = LIBSSH2_SEND(session, p->outbuf, total_length, LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (ret < 0) + if(ret < 0) _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Error sending %d bytes: %d", total_length, -ret); else { @@ -890,8 +896,8 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, debugdump(session, "libssh2_transport_write send()", p->outbuf, ret); } - if (ret != total_length) { - if (ret >= 0 || ret == -EAGAIN) { + if(ret != total_length) { + if(ret >= 0 || ret == -EAGAIN) { /* the whole packet could not be sent, save the rest */ session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND; p->odata = orgdata; diff --git a/libssh2/src/userauth.c b/libssh2/src/userauth.c index c02d81d0e..949dc1c66 100644 --- a/libssh2/src/userauth.c +++ b/libssh2/src/userauth.c @@ -71,7 +71,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, unsigned char *s; int rc; - if (session->userauth_list_state == libssh2_NB_state_idle) { + if(session->userauth_list_state == libssh2_NB_state_idle) { /* Zero the whole thing out */ memset(&session->userauth_list_packet_requirev_state, 0, sizeof(session->userauth_list_packet_requirev_state)); @@ -80,7 +80,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, s = session->userauth_list_data = LIBSSH2_ALLOC(session, session->userauth_list_data_len); - if (!session->userauth_list_data) { + if(!session->userauth_list_data) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for userauth_list"); return NULL; @@ -94,11 +94,11 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, session->userauth_list_state = libssh2_NB_state_created; } - if (session->userauth_list_state == libssh2_NB_state_created) { + if(session->userauth_list_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_list_data, session->userauth_list_data_len, (unsigned char *)"none", 4); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting userauth list"); return NULL; @@ -107,7 +107,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, LIBSSH2_FREE(session, session->userauth_list_data); session->userauth_list_data = NULL; - if (rc) { + if(rc) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-none request"); session->userauth_list_state = libssh2_NB_state_idle; @@ -117,23 +117,24 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, session->userauth_list_state = libssh2_NB_state_sent; } - if (session->userauth_list_state == libssh2_NB_state_sent) { + if(session->userauth_list_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->userauth_list_data, &session->userauth_list_data_len, 0, NULL, 0, - &session->userauth_list_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + &session->userauth_list_packet_requirev_state); + if(rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting userauth list"); return NULL; - } else if (rc || (session->userauth_list_data_len < 1)) { + } + else if(rc || (session->userauth_list_data_len < 1)) { _libssh2_error(session, rc, "Failed getting response"); session->userauth_list_state = libssh2_NB_state_idle; return NULL; } - if (session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) { + if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) { /* Wow, who'dve thought... */ _libssh2_error(session, LIBSSH2_ERROR_NONE, "No error"); LIBSSH2_FREE(session, session->userauth_list_data); @@ -143,7 +144,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, return NULL; } - if(session->userauth_list_data_len < 5) { + if(session->userauth_list_data_len < 5) { LIBSSH2_FREE(session, session->userauth_list_data); session->userauth_list_data = NULL; _libssh2_error(session, LIBSSH2_ERROR_PROTO, @@ -157,6 +158,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, "Unexpected userauth list size"); return NULL; } + /* Do note that the memory areas overlap! */ memmove(session->userauth_list_data, session->userauth_list_data + 5, methods_len); @@ -217,7 +219,7 @@ userauth_password(LIBSSH2_SESSION *session, }; int rc; - if (session->userauth_pswd_state == libssh2_NB_state_idle) { + if(session->userauth_pswd_state == libssh2_NB_state_idle) { /* Zero the whole thing out */ memset(&session->userauth_pswd_packet_requirev_state, 0, sizeof(session->userauth_pswd_packet_requirev_state)); @@ -235,7 +237,7 @@ userauth_password(LIBSSH2_SESSION *session, struct */ s = session->userauth_pswd_data = LIBSSH2_ALLOC(session, session->userauth_pswd_data_len); - if (!session->userauth_pswd_data) { + if(!session->userauth_pswd_data) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "userauth-password request"); @@ -255,11 +257,11 @@ userauth_password(LIBSSH2_SESSION *session, session->userauth_pswd_state = libssh2_NB_state_created; } - if (session->userauth_pswd_state == libssh2_NB_state_created) { + if(session->userauth_pswd_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_pswd_data, session->userauth_pswd_data_len, password, password_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block writing password request"); } @@ -268,7 +270,7 @@ userauth_password(LIBSSH2_SESSION *session, LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; - if (rc) { + if(rc) { session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password request"); @@ -279,10 +281,10 @@ userauth_password(LIBSSH2_SESSION *session, password_response: - if ((session->userauth_pswd_state == libssh2_NB_state_sent) + if((session->userauth_pswd_state == libssh2_NB_state_sent) || (session->userauth_pswd_state == libssh2_NB_state_sent1) || (session->userauth_pswd_state == libssh2_NB_state_sent2)) { - if (session->userauth_pswd_state == libssh2_NB_state_sent) { + if(session->userauth_pswd_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->userauth_pswd_data, &session->userauth_pswd_data_len, @@ -290,8 +292,8 @@ userauth_password(LIBSSH2_SESSION *session, &session-> userauth_pswd_packet_requirev_state); - if (rc) { - if (rc != LIBSSH2_ERROR_EAGAIN) + if(rc) { + if(rc != LIBSSH2_ERROR_EAGAIN) session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, @@ -303,7 +305,7 @@ userauth_password(LIBSSH2_SESSION *session, "Unexpected packet size"); } - if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { + if(session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password authentication successful"); LIBSSH2_FREE(session, session->userauth_pswd_data); @@ -311,7 +313,9 @@ userauth_password(LIBSSH2_SESSION *session, session->state |= LIBSSH2_STATE_AUTHENTICATED; session->userauth_pswd_state = libssh2_NB_state_idle; return 0; - } else if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_FAILURE) { + } + else if(session->userauth_pswd_data[0] == + SSH_MSG_USERAUTH_FAILURE) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password authentication failed"); LIBSSH2_FREE(session, session->userauth_pswd_data); @@ -335,41 +339,48 @@ userauth_password(LIBSSH2_SESSION *session, "Unexpected packet size"); } - if ((session->userauth_pswd_data[0] == + if((session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) || (session->userauth_pswd_data0 == SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)) { session->userauth_pswd_data0 = SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; - if ((session->userauth_pswd_state == libssh2_NB_state_sent1) || + if((session->userauth_pswd_state == libssh2_NB_state_sent1) || (session->userauth_pswd_state == libssh2_NB_state_sent2)) { - if (session->userauth_pswd_state == libssh2_NB_state_sent1) { + if(session->userauth_pswd_state == libssh2_NB_state_sent1) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password change required"); LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; } - if (passwd_change_cb) { - if (session->userauth_pswd_state == libssh2_NB_state_sent1) { + if(passwd_change_cb) { + if(session->userauth_pswd_state == + libssh2_NB_state_sent1) { passwd_change_cb(session, &session->userauth_pswd_newpw, &session->userauth_pswd_newpw_len, &session->abstract); - if (!session->userauth_pswd_newpw) { + if(!session->userauth_pswd_newpw) { return _libssh2_error(session, - LIBSSH2_ERROR_PASSWORD_EXPIRED, + LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password expired, and " "callback failed"); } /* basic data_len + newpw_len(4) */ - session->userauth_pswd_data_len = - username_len + password_len + 44; + if(username_len + password_len + 44 <= UINT_MAX) { + session->userauth_pswd_data_len = + username_len + password_len + 44; + s = session->userauth_pswd_data = + LIBSSH2_ALLOC(session, + session->userauth_pswd_data_len); + } + else { + s = session->userauth_pswd_data = NULL; + session->userauth_pswd_data_len = 0; + } - s = session->userauth_pswd_data = - LIBSSH2_ALLOC(session, - session->userauth_pswd_data_len); - if (!session->userauth_pswd_data) { + if(!session->userauth_pswd_data) { LIBSSH2_FREE(session, session->userauth_pswd_newpw); session->userauth_pswd_newpw = NULL; @@ -394,15 +405,17 @@ userauth_password(LIBSSH2_SESSION *session, session->userauth_pswd_state = libssh2_NB_state_sent2; } - if (session->userauth_pswd_state == libssh2_NB_state_sent2) { + if(session->userauth_pswd_state == + libssh2_NB_state_sent2) { rc = _libssh2_transport_send(session, - session->userauth_pswd_data, - session->userauth_pswd_data_len, - (unsigned char *) - session->userauth_pswd_newpw, - session->userauth_pswd_newpw_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + session->userauth_pswd_data, + session->userauth_pswd_data_len, + (unsigned char *) + session->userauth_pswd_newpw, + session->userauth_pswd_newpw_len); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return _libssh2_error(session, + LIBSSH2_ERROR_EAGAIN, "Would block waiting"); } @@ -412,7 +425,7 @@ userauth_password(LIBSSH2_SESSION *session, LIBSSH2_FREE(session, session->userauth_pswd_newpw); session->userauth_pswd_newpw = NULL; - if (rc) { + if(rc) { return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth " @@ -427,7 +440,8 @@ userauth_password(LIBSSH2_SESSION *session, goto password_response; } } - } else { + } + else { session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password Expired, and no callback " @@ -455,7 +469,8 @@ LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, const char *password, unsigned int password_len, - LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))) + LIBSSH2_PASSWD_CHANGEREQ_FUNC + ((*passwd_change_cb))) { int rc; BLOCK_ADJUST(rc, session, @@ -477,13 +492,13 @@ memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, size_t pubkey_len = pubkeyfiledata_len; unsigned int tmp_len; - if (pubkeyfiledata_len <= 1) { + if(pubkeyfiledata_len <= 1) { return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Invalid data in public key file"); } pubkey = LIBSSH2_ALLOC(session, pubkeyfiledata_len); - if (!pubkey) { + if(!pubkey) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for public key data"); } @@ -493,16 +508,17 @@ memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, /* * Remove trailing whitespace */ - while (pubkey_len && isspace(pubkey[pubkey_len - 1])) + while(pubkey_len && isspace(pubkey[pubkey_len - 1])) pubkey_len--; - if (!pubkey_len) { + if(!pubkey_len) { LIBSSH2_FREE(session, pubkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Missing public key data"); } - if ((sp1 = memchr(pubkey, ' ', pubkey_len)) == NULL) { + sp1 = memchr(pubkey, ' ', pubkey_len); + if(sp1 == NULL) { LIBSSH2_FREE(session, pubkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Invalid public key data"); @@ -510,12 +526,13 @@ memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, sp1++; - if ((sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey - 1))) == NULL) { + sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey)); + if(sp2 == NULL) { /* Assume that the id string is missing, but that it's okay */ sp2 = pubkey + pubkey_len; } - if (libssh2_base64_decode(session, (char **) &tmp, &tmp_len, + if(libssh2_base64_decode(session, (char **) &tmp, &tmp_len, (char *) sp1, sp2 - sp1)) { LIBSSH2_FREE(session, pubkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, @@ -561,29 +578,29 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading public key file: %s", pubkeyfile); /* Read Public Key */ - fd = fopen(pubkeyfile, "r"); - if (!fd) { + fd = fopen(pubkeyfile, FOPEN_READTEXT); + if(!fd) { return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Unable to open public key file"); } - while (!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') { + while(!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') { pubkey_len++; } rewind(fd); - if (pubkey_len <= 1) { + if(pubkey_len <= 1) { fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Invalid data in public key file"); } pubkey = LIBSSH2_ALLOC(session, pubkey_len); - if (!pubkey) { + if(!pubkey) { fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for public key data"); } - if (fread(pubkey, 1, pubkey_len, fd) != pubkey_len) { + if(fread(pubkey, 1, pubkey_len, fd) != pubkey_len) { LIBSSH2_FREE(session, pubkey); fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_FILE, @@ -593,17 +610,18 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, /* * Remove trailing whitespace */ - while (pubkey_len && isspace(pubkey[pubkey_len - 1])) { + while(pubkey_len && isspace(pubkey[pubkey_len - 1])) { pubkey_len--; } - if (!pubkey_len) { + if(!pubkey_len) { LIBSSH2_FREE(session, pubkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Missing public key data"); } - if ((sp1 = memchr(pubkey, ' ', pubkey_len)) == NULL) { + sp1 = memchr(pubkey, ' ', pubkey_len); + if(sp1 == NULL) { LIBSSH2_FREE(session, pubkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Invalid public key data"); @@ -612,12 +630,13 @@ file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, sp1++; sp_len = sp1 > pubkey ? (sp1 - pubkey) - 1 : 0; - if ((sp2 = memchr(sp1, ' ', pubkey_len - sp_len)) == NULL) { + sp2 = memchr(sp1, ' ', pubkey_len - sp_len); + if(sp2 == NULL) { /* Assume that the id string is missing, but that it's okay */ sp2 = pubkey + pubkey_len; } - if (libssh2_base64_decode(session, (char **) &tmp, &tmp_len, + if(libssh2_base64_decode(session, (char **) &tmp, &tmp_len, (char *) sp1, sp2 - sp1)) { LIBSSH2_FREE(session, pubkey); return _libssh2_error(session, LIBSSH2_ERROR_FILE, @@ -649,8 +668,8 @@ memory_read_privatekey(LIBSSH2_SESSION * session, *hostkey_method = NULL; *hostkey_abstract = NULL; - while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) { - if ((*hostkey_methods_avail)->initPEMFromMemory + while(*hostkey_methods_avail && (*hostkey_methods_avail)->name) { + if((*hostkey_methods_avail)->initPEMFromMemory && strncmp((*hostkey_methods_avail)->name, (const char *) method, method_len) == 0) { *hostkey_method = *hostkey_methods_avail; @@ -658,12 +677,12 @@ memory_read_privatekey(LIBSSH2_SESSION * session, } hostkey_methods_avail++; } - if (!*hostkey_method) { + if(!*hostkey_method) { return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, "No handler for specified private key"); } - if ((*hostkey_method)-> + if((*hostkey_method)-> initPEMFromMemory(session, privkeyfiledata, privkeyfiledata_len, (unsigned char *) passphrase, hostkey_abstract)) { @@ -691,8 +710,8 @@ file_read_privatekey(LIBSSH2_SESSION * session, privkeyfile); *hostkey_method = NULL; *hostkey_abstract = NULL; - while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) { - if ((*hostkey_methods_avail)->initPEM + while(*hostkey_methods_avail && (*hostkey_methods_avail)->name) { + if((*hostkey_methods_avail)->initPEM && strncmp((*hostkey_methods_avail)->name, (const char *) method, method_len) == 0) { *hostkey_method = *hostkey_methods_avail; @@ -700,12 +719,12 @@ file_read_privatekey(LIBSSH2_SESSION * session, } hostkey_methods_avail++; } - if (!*hostkey_method) { + if(!*hostkey_method) { return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, "No handler for specified private key"); } - if ((*hostkey_method)-> + if((*hostkey_method)-> initPEM(session, privkeyfile, (unsigned char *) passphrase, hostkey_abstract)) { return _libssh2_error(session, LIBSSH2_ERROR_FILE, @@ -743,15 +762,15 @@ sign_frommemory(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, datavec.iov_base = (void *)data; datavec.iov_len = data_len; - if (privkeyobj->signv(session, sig, sig_len, 1, &datavec, + if(privkeyobj->signv(session, sig, sig_len, 1, &datavec, &hostkey_abstract)) { - if (privkeyobj->dtor) { - privkeyobj->dtor(session, abstract); + if(privkeyobj->dtor) { + privkeyobj->dtor(session, &hostkey_abstract); } return -1; } - if (privkeyobj->dtor) { + if(privkeyobj->dtor) { privkeyobj->dtor(session, &hostkey_abstract); } return 0; @@ -779,15 +798,15 @@ sign_fromfile(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, datavec.iov_base = (void *)data; datavec.iov_len = data_len; - if (privkeyobj->signv(session, sig, sig_len, 1, &datavec, + if(privkeyobj->signv(session, sig, sig_len, 1, &datavec, &hostkey_abstract)) { - if (privkeyobj->dtor) { + if(privkeyobj->dtor) { privkeyobj->dtor(session, &hostkey_abstract); } return -1; } - if (privkeyobj->dtor) { + if(privkeyobj->dtor) { privkeyobj->dtor(session, &hostkey_abstract); } return 0; @@ -809,9 +828,15 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, { int rc; - if (session->userauth_host_state == libssh2_NB_state_idle) { +#if !LIBSSH2_RSA + return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, + "RSA is not supported by crypto backend"); +#endif + + if(session->userauth_host_state == libssh2_NB_state_idle) { const LIBSSH2_HOSTKEY_METHOD *privkeyobj; - unsigned char *pubkeydata, *sig = NULL; + unsigned char *pubkeydata = NULL; + unsigned char *sig = NULL; size_t pubkeydata_len = 0; size_t sig_len = 0; void *abstract; @@ -822,7 +847,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, memset(&session->userauth_host_packet_requirev_state, 0, sizeof(session->userauth_host_packet_requirev_state)); - if (publickey) { + if(publickey) { rc = file_read_publickey(session, &session->userauth_host_method, &session->userauth_host_method_len, &pubkeydata, &pubkeydata_len, publickey); @@ -837,7 +862,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, &session->userauth_host_method_len, &pubkeydata, &pubkeydata_len, privatekey, passphrase); - if (rc) + if(rc) /* libssh2_pub_priv_keyfile calls _libssh2_error() */ return rc; } @@ -862,7 +887,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, session->userauth_host_packet_len + 4 + (4 + session->userauth_host_method_len) + (4 + pubkeydata_len)); - if (!session->userauth_host_packet) { + if(!session->userauth_host_packet) { LIBSSH2_FREE(session, session->userauth_host_method); session->userauth_host_method = NULL; LIBSSH2_FREE(session, pubkeydata); @@ -906,31 +931,31 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, datavec[2].iov_base = (void *)session->userauth_host_packet; datavec[2].iov_len = session->userauth_host_packet_len; - if (privkeyobj && privkeyobj->signv && + if(privkeyobj && privkeyobj->signv && privkeyobj->signv(session, &sig, &sig_len, 3, datavec, &abstract)) { LIBSSH2_FREE(session, session->userauth_host_method); session->userauth_host_method = NULL; LIBSSH2_FREE(session, session->userauth_host_packet); session->userauth_host_packet = NULL; - if (privkeyobj->dtor) { + if(privkeyobj->dtor) { privkeyobj->dtor(session, &abstract); } return -1; } - if (privkeyobj && privkeyobj->dtor) { + if(privkeyobj && privkeyobj->dtor) { privkeyobj->dtor(session, &abstract); } - if (sig_len > pubkeydata_len) { + if(sig_len > pubkeydata_len) { unsigned char *newpacket; /* Should *NEVER* happen, but...well.. better safe than sorry */ newpacket = LIBSSH2_REALLOC(session, session->userauth_host_packet, session->userauth_host_packet_len + 4 + (4 + session->userauth_host_method_len) + (4 + sig_len)); /* PK sigblob */ - if (!newpacket) { + if(!newpacket) { LIBSSH2_FREE(session, sig); LIBSSH2_FREE(session, session->userauth_host_packet); session->userauth_host_packet = NULL; @@ -947,7 +972,8 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, session->userauth_host_packet + session->userauth_host_packet_len; _libssh2_store_u32(&session->userauth_host_s, - 4 + session->userauth_host_method_len + 4 + sig_len); + 4 + session->userauth_host_method_len + + 4 + sig_len); _libssh2_store_str(&session->userauth_host_s, (const char *)session->userauth_host_method, session->userauth_host_method_len); @@ -964,15 +990,16 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, session->userauth_host_state = libssh2_NB_state_created; } - if (session->userauth_host_state == libssh2_NB_state_created) { + if(session->userauth_host_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_host_packet, session->userauth_host_s - session->userauth_host_packet, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + "Would block"); } - else if (rc) { + else if(rc) { LIBSSH2_FREE(session, session->userauth_host_packet); session->userauth_host_packet = NULL; session->userauth_host_state = libssh2_NB_state_idle; @@ -985,7 +1012,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, session->userauth_host_state = libssh2_NB_state_sent; } - if (session->userauth_host_state == libssh2_NB_state_sent) { + if(session->userauth_host_state == libssh2_NB_state_sent) { static const unsigned char reply_codes[3] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; size_t data_len; @@ -994,17 +1021,18 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, &data_len, 0, NULL, 0, &session-> userauth_host_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + "Would block"); } session->userauth_host_state = libssh2_NB_state_idle; - if (rc || data_len < 1) { + if(rc || data_len < 1) { return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Auth failed"); } - if (session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) { + if(session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Hostbased authentication successful"); /* We are us and we've proved it. */ @@ -1055,7 +1083,8 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, unsigned int username_len, const unsigned char *pubkeydata, unsigned long pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), + LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC + ((*sign_callback)), void *abstract) { unsigned char reply_codes[4] = @@ -1065,13 +1094,13 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, int rc; unsigned char *s; - if (session->userauth_pblc_state == libssh2_NB_state_idle) { + if(session->userauth_pblc_state == libssh2_NB_state_idle) { /* * The call to _libssh2_ntohu32 later relies on pubkeydata having at * least 4 valid bytes containing the length of the method name. */ - if (pubkeydata_len < 4) + if(pubkeydata_len < 4) return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid public key, too short"); @@ -1085,10 +1114,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, * allocation/free. * For other uses, we allocate and populate it here. */ - if (!session->userauth_pblc_method) { + if(!session->userauth_pblc_method) { session->userauth_pblc_method_len = _libssh2_ntohu32(pubkeydata); - if(session->userauth_pblc_method_len > pubkeydata_len) + if(session->userauth_pblc_method_len > pubkeydata_len - 4) /* the method length simply cannot be longer than the entire passed in data, so we use this to detect crazy input data */ @@ -1098,10 +1127,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, session->userauth_pblc_method = LIBSSH2_ALLOC(session, session->userauth_pblc_method_len); - if (!session->userauth_pblc_method) { + if(!session->userauth_pblc_method) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for public key " - "data"); + "Unable to allocate memory " + "for public key data"); } memcpy(session->userauth_pblc_method, pubkeydata + 4, session->userauth_pblc_method_len); @@ -1111,7 +1140,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, * file must match length embedded in the key. * TODO: The data should match too but we don't check that. Should we? */ - else if (session->userauth_pblc_method_len != + else if(session->userauth_pblc_method_len != _libssh2_ntohu32(pubkeydata)) return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid public key"); @@ -1140,7 +1169,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, session->userauth_pblc_packet_len + 4 + (4 + session->userauth_pblc_method_len) + (4 + pubkeydata_len)); - if (!session->userauth_pblc_packet) { + if(!session->userauth_pblc_packet) { LIBSSH2_FREE(session, session->userauth_pblc_method); session->userauth_pblc_method = NULL; return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, @@ -1166,13 +1195,14 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, session->userauth_pblc_state = libssh2_NB_state_created; } - if (session->userauth_pblc_state == libssh2_NB_state_created) { + if(session->userauth_pblc_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_pblc_packet, session->userauth_pblc_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - else if (rc) { + if(rc == LIBSSH2_ERROR_EAGAIN) + return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + "Would block"); + else if(rc) { LIBSSH2_FREE(session, session->userauth_pblc_packet); session->userauth_pblc_packet = NULL; LIBSSH2_FREE(session, session->userauth_pblc_method); @@ -1185,17 +1215,18 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, session->userauth_pblc_state = libssh2_NB_state_sent; } - if (session->userauth_pblc_state == libssh2_NB_state_sent) { + if(session->userauth_pblc_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->userauth_pblc_data, &session->userauth_pblc_data_len, 0, NULL, 0, &session-> userauth_pblc_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); + if(rc == LIBSSH2_ERROR_EAGAIN) { + return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + "Would block"); } - else if (rc || (session->userauth_pblc_data_len < 1)) { + else if(rc || (session->userauth_pblc_data_len < 1)) { LIBSSH2_FREE(session, session->userauth_pblc_packet); session->userauth_pblc_packet = NULL; LIBSSH2_FREE(session, session->userauth_pblc_method); @@ -1205,7 +1236,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, "Waiting for USERAUTH response"); } - if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) { + if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Pubkey authentication prematurely successful"); /* @@ -1223,7 +1254,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, return 0; } - if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_FAILURE) { + if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_FAILURE) { /* This public key is not allowed for this user on this server */ LIBSSH2_FREE(session, session->userauth_pblc_data); session->userauth_pblc_data = NULL; @@ -1244,14 +1275,14 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, session->userauth_pblc_state = libssh2_NB_state_sent1; } - if (session->userauth_pblc_state == libssh2_NB_state_sent1) { + if(session->userauth_pblc_state == libssh2_NB_state_sent1) { unsigned char *buf; unsigned char *sig; size_t sig_len; s = buf = LIBSSH2_ALLOC(session, 4 + session->session_id_len + session->userauth_pblc_packet_len); - if (!buf) { + if(!buf) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "userauth-publickey signed data"); @@ -1260,15 +1291,17 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, _libssh2_store_str(&s, (const char *)session->session_id, session->session_id_len); - memcpy (s, session->userauth_pblc_packet, - session->userauth_pblc_packet_len); + memcpy(s, session->userauth_pblc_packet, + session->userauth_pblc_packet_len); s += session->userauth_pblc_packet_len; rc = sign_callback(session, &sig, &sig_len, buf, s - buf, abstract); LIBSSH2_FREE(session, buf); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { + if(rc == LIBSSH2_ERROR_EAGAIN) { + return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + "Would block"); + } + else if(rc) { LIBSSH2_FREE(session, session->userauth_pblc_method); session->userauth_pblc_method = NULL; LIBSSH2_FREE(session, session->userauth_pblc_packet); @@ -1282,7 +1315,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, * If this function was restarted, pubkeydata_len might still be 0 * which will cause an unnecessary but harmless realloc here. */ - if (sig_len > pubkeydata_len) { + if(sig_len > pubkeydata_len) { unsigned char *newpacket; /* Should *NEVER* happen, but...well.. better safe than sorry */ newpacket = LIBSSH2_REALLOC(session, @@ -1290,7 +1323,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, session->userauth_pblc_packet_len + 4 + (4 + session->userauth_pblc_method_len) + (4 + sig_len)); /* PK sigblob */ - if (!newpacket) { + if(!newpacket) { LIBSSH2_FREE(session, sig); LIBSSH2_FREE(session, session->userauth_pblc_packet); session->userauth_pblc_packet = NULL; @@ -1308,7 +1341,8 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, session->userauth_pblc_b = NULL; _libssh2_store_u32(&s, - 4 + session->userauth_pblc_method_len + 4 + sig_len); + 4 + session->userauth_pblc_method_len + 4 + + sig_len); _libssh2_store_str(&s, (const char *)session->userauth_pblc_method, session->userauth_pblc_method_len); @@ -1325,14 +1359,16 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, session->userauth_pblc_state = libssh2_NB_state_sent2; } - if (session->userauth_pblc_state == libssh2_NB_state_sent2) { + if(session->userauth_pblc_state == libssh2_NB_state_sent2) { rc = _libssh2_transport_send(session, session->userauth_pblc_packet, session->userauth_pblc_s - session->userauth_pblc_packet, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { + if(rc == LIBSSH2_ERROR_EAGAIN) { + return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + "Would block"); + } + else if(rc) { LIBSSH2_FREE(session, session->userauth_pblc_packet); session->userauth_pblc_packet = NULL; session->userauth_pblc_state = libssh2_NB_state_idle; @@ -1349,19 +1385,20 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, reply_codes[2] = 0; rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_pblc_data, - &session->userauth_pblc_data_len, 0, NULL, 0, - &session->userauth_pblc_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + &session->userauth_pblc_data, + &session->userauth_pblc_data_len, 0, NULL, 0, + &session->userauth_pblc_packet_requirev_state); + if(rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting userauth list"); - } else if (rc || session->userauth_pblc_data_len < 1) { + } + else if(rc || session->userauth_pblc_data_len < 1) { session->userauth_pblc_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Waiting for publickey USERAUTH response"); } - if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) { + if(session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Publickey authentication successful"); /* We are us and we've proved it. */ @@ -1401,11 +1438,16 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session, void *abstract = &privkey_file; int rc; +#if !LIBSSH2_RSA + return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, + "RSA is not supported by crypto backend"); +#endif + privkey_file.filename = privatekeydata; privkey_file.passphrase = passphrase; - if (session->userauth_pblc_state == libssh2_NB_state_idle) { - if (publickeydata_len && publickeydata) { + if(session->userauth_pblc_state == libssh2_NB_state_idle) { + if(publickeydata_len && publickeydata) { rc = memory_read_publickey(session, &session->userauth_pblc_method, &session->userauth_pblc_method_len, &pubkeydata, &pubkeydata_len, @@ -1413,14 +1455,14 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session, if(rc) return rc; } - else if (privatekeydata_len && privatekeydata) { + else if(privatekeydata_len && privatekeydata) { /* Compute public key from private key. */ - if (_libssh2_pub_priv_keyfilememory(session, - &session->userauth_pblc_method, - &session->userauth_pblc_method_len, - &pubkeydata, &pubkeydata_len, - privatekeydata, privatekeydata_len, - passphrase)) + if(_libssh2_pub_priv_keyfilememory(session, + &session->userauth_pblc_method, + &session->userauth_pblc_method_len, + &pubkeydata, &pubkeydata_len, + privatekeydata, privatekeydata_len, + passphrase)) return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Unable to extract public key " "from private key."); @@ -1458,15 +1500,20 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session, void *abstract = &privkey_file; int rc; +#if !LIBSSH2_RSA + return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, + "RSA is not supported by crypto backend"); +#endif + privkey_file.filename = privatekey; privkey_file.passphrase = passphrase; - if (session->userauth_pblc_state == libssh2_NB_state_idle) { - if (publickey) { + if(session->userauth_pblc_state == libssh2_NB_state_idle) { + if(publickey) { rc = file_read_publickey(session, &session->userauth_pblc_method, &session->userauth_pblc_method_len, - &pubkeydata, &pubkeydata_len,publickey); - if (rc) + &pubkeydata, &pubkeydata_len, publickey); + if(rc) return rc; } else { @@ -1478,7 +1525,7 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session, privatekey, passphrase); /* _libssh2_pub_priv_keyfile calls _libssh2_error() */ - if (rc) + if(rc) return rc; } } @@ -1510,7 +1557,7 @@ libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION *session, if(NULL == passphrase) /* if given a NULL pointer, make it point to a zero-length string to save us from having to check this all over */ - passphrase=""; + passphrase = ""; BLOCK_ADJUST(rc, session, userauth_publickey_frommemory(session, user, user_len, @@ -1538,7 +1585,7 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, if(NULL == passphrase) /* if given a NULL pointer, make it point to a zero-length string to save us from having to check this all over */ - passphrase=""; + passphrase = ""; BLOCK_ADJUST(rc, session, userauth_publickey_fromfile(session, user, user_len, @@ -1555,7 +1602,8 @@ libssh2_userauth_publickey(LIBSSH2_SESSION *session, const char *user, const unsigned char *pubkeydata, size_t pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), + LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC + ((*sign_callback)), void **abstract) { int rc; @@ -1581,7 +1629,8 @@ static int userauth_keyboard_interactive(LIBSSH2_SESSION * session, const char *username, unsigned int username_len, - LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback))) + LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC + ((*response_callback))) { unsigned char *s; int rc; @@ -1593,7 +1642,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, unsigned int language_tag_len; unsigned int i; - if (session->userauth_kybd_state == libssh2_NB_state_idle) { + if(session->userauth_kybd_state == libssh2_NB_state_idle) { session->userauth_kybd_auth_name = NULL; session->userauth_kybd_auth_instruction = NULL; session->userauth_kybd_num_prompts = 0; @@ -1618,7 +1667,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, session->userauth_kybd_data = s = LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len); - if (!s) { + if(!s) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "keyboard-interactive authentication"); @@ -1647,18 +1696,21 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, session->userauth_kybd_state = libssh2_NB_state_created; } - if (session->userauth_kybd_state == libssh2_NB_state_created) { + if(session->userauth_kybd_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_kybd_data, session->userauth_kybd_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { + if(rc == LIBSSH2_ERROR_EAGAIN) { + return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, + "Would block"); + } + else if(rc) { LIBSSH2_FREE(session, session->userauth_kybd_data); session->userauth_kybd_data = NULL; session->userauth_kybd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send keyboard-interactive request"); + "Unable to send keyboard-interactive" + " request"); } LIBSSH2_FREE(session, session->userauth_kybd_data); session->userauth_kybd_data = NULL; @@ -1667,26 +1719,29 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, } for(;;) { - if (session->userauth_kybd_state == libssh2_NB_state_sent) { + if(session->userauth_kybd_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->userauth_kybd_data, &session->userauth_kybd_data_len, 0, NULL, 0, &session-> userauth_kybd_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { + if(rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc || session->userauth_kybd_data_len < 1) { + } + else if(rc || session->userauth_kybd_data_len < 1) { session->userauth_kybd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Waiting for keyboard USERAUTH response"); + "Waiting for keyboard " + "USERAUTH response"); } - if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { + if(session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Keyboard-interactive authentication successful"); + "Keyboard-interactive " + "authentication successful"); LIBSSH2_FREE(session, session->userauth_kybd_data); session->userauth_kybd_data = NULL; session->state |= LIBSSH2_STATE_AUTHENTICATED; @@ -1694,7 +1749,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, return 0; } - if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) { + if(session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Keyboard-interactive authentication failed"); LIBSSH2_FREE(session, session->userauth_kybd_data); @@ -1709,60 +1764,127 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, /* server requested PAM-like conversation */ s = session->userauth_kybd_data + 1; - /* string name (ISO-10646 UTF-8) */ - session->userauth_kybd_auth_name_len = _libssh2_ntohu32(s); - s += 4; + if(session->userauth_kybd_data_len >= 5) { + /* string name (ISO-10646 UTF-8) */ + session->userauth_kybd_auth_name_len = _libssh2_ntohu32(s); + s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too small" + "to get length"); + goto cleanup; + } + if(session->userauth_kybd_auth_name_len) { session->userauth_kybd_auth_name = LIBSSH2_ALLOC(session, session->userauth_kybd_auth_name_len); - if (!session->userauth_kybd_auth_name) { + if(!session->userauth_kybd_auth_name) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "keyboard-interactive 'name' " "request field"); goto cleanup; } - memcpy(session->userauth_kybd_auth_name, s, - session->userauth_kybd_auth_name_len); - s += session->userauth_kybd_auth_name_len; + if(s + session->userauth_list_data_len <= + session->userauth_kybd_data + + session->userauth_kybd_data_len) { + memcpy(session->userauth_kybd_auth_name, s, + session->userauth_kybd_auth_name_len); + s += session->userauth_kybd_auth_name_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too small" + "for auth name"); + goto cleanup; + } + } + + if(s + 4 <= session->userauth_kybd_data + + session->userauth_kybd_data_len) { + /* string instruction (ISO-10646 UTF-8) */ + session->userauth_kybd_auth_instruction_len = + _libssh2_ntohu32(s); + s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too small" + "for auth instruction length"); + goto cleanup; } - /* string instruction (ISO-10646 UTF-8) */ - session->userauth_kybd_auth_instruction_len = _libssh2_ntohu32(s); - s += 4; if(session->userauth_kybd_auth_instruction_len) { session->userauth_kybd_auth_instruction = LIBSSH2_ALLOC(session, session->userauth_kybd_auth_instruction_len); - if (!session->userauth_kybd_auth_instruction) { + if(!session->userauth_kybd_auth_instruction) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "keyboard-interactive 'instruction' " "request field"); goto cleanup; } - memcpy(session->userauth_kybd_auth_instruction, s, - session->userauth_kybd_auth_instruction_len); - s += session->userauth_kybd_auth_instruction_len; + if(s + session->userauth_kybd_auth_instruction_len <= + session->userauth_kybd_data + + session->userauth_kybd_data_len) { + memcpy(session->userauth_kybd_auth_instruction, s, + session->userauth_kybd_auth_instruction_len); + s += session->userauth_kybd_auth_instruction_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too small" + "for auth instruction"); + goto cleanup; + } } - /* string language tag (as defined in [RFC-3066]) */ - language_tag_len = _libssh2_ntohu32(s); - s += 4; + if(s + 4 <= session->userauth_kybd_data + + session->userauth_kybd_data_len) { + /* string language tag (as defined in [RFC-3066]) */ + language_tag_len = _libssh2_ntohu32(s); + s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too small" + "for auth language tag length"); + goto cleanup; + } - /* ignoring this field as deprecated */ - s += language_tag_len; + if(s + language_tag_len <= session->userauth_kybd_data + + session->userauth_kybd_data_len) { + /* ignoring this field as deprecated */ + s += language_tag_len; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too small" + "for auth language tag"); + goto cleanup; + } - /* int num-prompts */ - session->userauth_kybd_num_prompts = _libssh2_ntohu32(s); - s += 4; - if(session->userauth_kybd_num_prompts && - session->userauth_kybd_num_prompts > 100) { - _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, - "Too many replies for " - "keyboard-interactive prompts"); - goto cleanup; + if(s + 4 <= session->userauth_kybd_data + + session->userauth_kybd_data_len) { + /* int num-prompts */ + session->userauth_kybd_num_prompts = _libssh2_ntohu32(s); + s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too small" + "for auth num keyboard prompts"); + goto cleanup; + } + + if(session->userauth_kybd_num_prompts > 100) { + _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Too many replies for " + "keyboard-interactive prompts"); + goto cleanup; } if(session->userauth_kybd_num_prompts) { @@ -1770,7 +1892,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, LIBSSH2_CALLOC(session, sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) * session->userauth_kybd_num_prompts); - if (!session->userauth_kybd_prompts) { + if(!session->userauth_kybd_prompts) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "keyboard-interactive prompts array"); @@ -1781,7 +1903,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, LIBSSH2_CALLOC(session, sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) * session->userauth_kybd_num_prompts); - if (!session->userauth_kybd_responses) { + if(!session->userauth_kybd_responses) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "keyboard-interactive responses array"); @@ -1789,25 +1911,56 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, } for(i = 0; i < session->userauth_kybd_num_prompts; i++) { - /* string prompt[1] (ISO-10646 UTF-8) */ - session->userauth_kybd_prompts[i].length = - _libssh2_ntohu32(s); - s += 4; + if(s + 4 <= session->userauth_kybd_data + + session->userauth_kybd_data_len) { + /* string prompt[1] (ISO-10646 UTF-8) */ + session->userauth_kybd_prompts[i].length = + _libssh2_ntohu32(s); + s += 4; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too " + "small for auth keyboard " + "prompt length"); + goto cleanup; + } + session->userauth_kybd_prompts[i].text = LIBSSH2_CALLOC(session, - session->userauth_kybd_prompts[i].length); - if (!session->userauth_kybd_prompts[i].text) { + session->userauth_kybd_prompts[i]. + length); + if(!session->userauth_kybd_prompts[i].text) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "keyboard-interactive prompt message"); goto cleanup; } - memcpy(session->userauth_kybd_prompts[i].text, s, - session->userauth_kybd_prompts[i].length); - s += session->userauth_kybd_prompts[i].length; - /* boolean echo[1] */ - session->userauth_kybd_prompts[i].echo = *s++; + if(s + session->userauth_kybd_prompts[i].length <= + session->userauth_kybd_data + + session->userauth_kybd_data_len) { + memcpy(session->userauth_kybd_prompts[i].text, s, + session->userauth_kybd_prompts[i].length); + s += session->userauth_kybd_prompts[i].length; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too " + "small for auth keyboard prompt"); + goto cleanup; + } + if(s < session->userauth_kybd_data + + session->userauth_kybd_data_len) { + /* boolean echo[1] */ + session->userauth_kybd_prompts[i].echo = *s++; + } + else { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "userauth keyboard data buffer too " + "small for auth keyboard prompt echo"); + goto cleanup; + } } } @@ -1831,7 +1984,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, for(i = 0; i < session->userauth_kybd_num_prompts; i++) { /* string response[1] (ISO-10646 UTF-8) */ - if(session->userauth_kybd_responses[i].length <= + if(session->userauth_kybd_responses[i].length <= (SIZE_MAX - 4 - session->userauth_kybd_packet_len) ) { session->userauth_kybd_packet_len += 4 + session->userauth_kybd_responses[i].length; @@ -1850,7 +2003,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, session->userauth_kybd_data = s = LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len); - if (!s) { + if(!s) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for keyboard-" "interactive response packet"); @@ -1870,14 +2023,14 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, session->userauth_kybd_state = libssh2_NB_state_sent1; } - if (session->userauth_kybd_state == libssh2_NB_state_sent1) { + if(session->userauth_kybd_state == libssh2_NB_state_sent1) { rc = _libssh2_transport_send(session, session->userauth_kybd_data, session->userauth_kybd_packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) + if(rc == LIBSSH2_ERROR_EAGAIN) return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - if (rc) { + if(rc) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-keyboard-interactive" " request"); @@ -1896,14 +2049,14 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, LIBSSH2_FREE(session, session->userauth_kybd_data); session->userauth_kybd_data = NULL; - if (session->userauth_kybd_prompts) { + if(session->userauth_kybd_prompts) { for(i = 0; i < session->userauth_kybd_num_prompts; i++) { LIBSSH2_FREE(session, session->userauth_kybd_prompts[i].text); session->userauth_kybd_prompts[i].text = NULL; } } - if (session->userauth_kybd_responses) { + if(session->userauth_kybd_responses) { for(i = 0; i < session->userauth_kybd_num_prompts; i++) { LIBSSH2_FREE(session, session->userauth_kybd_responses[i].text); @@ -1928,7 +2081,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, session->userauth_kybd_auth_instruction = NULL; } - if (session->userauth_kybd_auth_failure) { + if(session->userauth_kybd_auth_failure) { session->userauth_kybd_state = libssh2_NB_state_idle; return -1; } @@ -1946,7 +2099,8 @@ LIBSSH2_API int libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session, const char *user, unsigned int user_len, - LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback))) + LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC + ((*response_callback))) { int rc; BLOCK_ADJUST(rc, session, diff --git a/libssh2/src/userauth.h b/libssh2/src/userauth.h index c0442ae15..a7b0a9846 100644 --- a/libssh2/src/userauth.h +++ b/libssh2/src/userauth.h @@ -44,7 +44,8 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, unsigned int username_len, const unsigned char *pubkeydata, unsigned long pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), + LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC + ((*sign_callback)), void *abstract); #endif /* LIBSSH2_USERAUTH_H */ diff --git a/libssh2/src/wincng.c b/libssh2/src/wincng.c index d3271b3e3..4bebc6407 100755 --- a/libssh2/src/wincng.c +++ b/libssh2/src/wincng.c @@ -59,6 +59,7 @@ #include #include #include +#include "misc.h" #ifdef HAVE_STDLIB_H #include @@ -244,34 +245,50 @@ _libssh2_wincng_init(void) ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_CBC, BCRYPT_AES_ALGORITHM, NULL, 0); - if (BCRYPT_SUCCESS(ret)) { - ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_CBC, BCRYPT_CHAINING_MODE, + if(BCRYPT_SUCCESS(ret)) { + ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_CBC, + BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0); } } + ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_ECB, + BCRYPT_AES_ALGORITHM, NULL, 0); + if(BCRYPT_SUCCESS(ret)) { + ret = BCryptSetProperty(_libssh2_wincng.hAlgAES_ECB, + BCRYPT_CHAINING_MODE, + (PBYTE)BCRYPT_CHAIN_MODE_ECB, + sizeof(BCRYPT_CHAIN_MODE_ECB), 0); + if(!BCRYPT_SUCCESS(ret)) { + (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_ECB, 0); + } + } + ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRC4_NA, BCRYPT_RC4_ALGORITHM, NULL, 0); - if (BCRYPT_SUCCESS(ret)) { - ret = BCryptSetProperty(_libssh2_wincng.hAlgRC4_NA, BCRYPT_CHAINING_MODE, + if(BCRYPT_SUCCESS(ret)) { + ret = BCryptSetProperty(_libssh2_wincng.hAlgRC4_NA, + BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_NA, sizeof(BCRYPT_CHAIN_MODE_NA), 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0); } } ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlg3DES_CBC, BCRYPT_3DES_ALGORITHM, NULL, 0); - if (BCRYPT_SUCCESS(ret)) { - ret = BCryptSetProperty(_libssh2_wincng.hAlg3DES_CBC, BCRYPT_CHAINING_MODE, + if(BCRYPT_SUCCESS(ret)) { + ret = BCryptSetProperty(_libssh2_wincng.hAlg3DES_CBC, + BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0); - if (!BCRYPT_SUCCESS(ret)) { - (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC, 0); + if(!BCRYPT_SUCCESS(ret)) { + (void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC, + 0); } } } @@ -314,11 +331,11 @@ _libssh2_wincng_safe_free(void *buf, int len) (void)len; #endif - if (!buf) + if(!buf) return; #ifdef LIBSSH2_CLEAR_MEMORY - if (len > 0) + if(len > 0) SecureZeroMemory(buf, len); #endif @@ -345,7 +362,7 @@ _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx, (unsigned char *)&dwHash, sizeof(dwHash), &cbData, 0); - if ((!BCRYPT_SUCCESS(ret)) || dwHash != hashlen) { + if((!BCRYPT_SUCCESS(ret)) || dwHash != hashlen) { return -1; } @@ -353,12 +370,12 @@ _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx, (unsigned char *)&dwHashObject, sizeof(dwHashObject), &cbData, 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { return -1; } pbHashObject = malloc(dwHashObject); - if (!pbHashObject) { + if(!pbHashObject) { return -1; } @@ -366,7 +383,7 @@ _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx, ret = BCryptCreateHash(hAlg, &hHash, pbHashObject, dwHashObject, key, keylen, 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { _libssh2_wincng_safe_free(pbHashObject, dwHashObject); return -1; } @@ -418,7 +435,7 @@ _libssh2_wincng_hash(unsigned char *data, unsigned long datalen, int ret; ret = _libssh2_wincng_hash_init(&ctx, hAlg, hashlen, NULL, 0); - if (!ret) { + if(!ret) { ret = _libssh2_wincng_hash_update(&ctx, data, datalen); ret |= _libssh2_wincng_hash_final(&ctx, hash); } @@ -476,13 +493,13 @@ _libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx, datalen = m_len; data = malloc(datalen); - if (!data) { + if(!data) { return -1; } hashlen = SHA_DIGEST_LENGTH; hash = malloc(hashlen); - if (!hash) { + if(!hash) { free(data); return -1; } @@ -495,22 +512,23 @@ _libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx, _libssh2_wincng_safe_free(data, datalen); - if (ret) { + if(ret) { _libssh2_wincng_safe_free(hash, hashlen); return -1; } datalen = sig_len; data = malloc(datalen); - if (!data) { + if(!data) { _libssh2_wincng_safe_free(hash, hashlen); return -1; } - if (flags & BCRYPT_PAD_PKCS1) { + if(flags & BCRYPT_PAD_PKCS1) { paddingInfoPKCS1.pszAlgId = BCRYPT_SHA1_ALGORITHM; pPaddingInfo = &paddingInfoPKCS1; - } else + } + else pPaddingInfo = NULL; memcpy(data, sig, datalen); @@ -537,14 +555,13 @@ _libssh2_wincng_load_pem(LIBSSH2_SESSION *session, FILE *fp; int ret; - (void)passphrase; - - fp = fopen(filename, "r"); - if (!fp) { + fp = fopen(filename, FOPEN_READTEXT); + if(!fp) { return -1; } ret = _libssh2_pem_parse(session, headerbegin, headerend, + passphrase, fp, data, datalen); fclose(fp); @@ -564,19 +581,19 @@ _libssh2_wincng_load_private(LIBSSH2_SESSION *session, unsigned int datalen = 0; int ret = -1; - if (ret && tryLoadRSA) { + if(ret && tryLoadRSA) { ret = _libssh2_wincng_load_pem(session, filename, passphrase, PEM_RSA_HEADER, PEM_RSA_FOOTER, &data, &datalen); } - if (ret && tryLoadDSA) { + if(ret && tryLoadDSA) { ret = _libssh2_wincng_load_pem(session, filename, passphrase, PEM_DSA_HEADER, PEM_DSA_FOOTER, &data, &datalen); } - if (!ret) { + if(!ret) { *ppbEncoded = data; *pcbEncoded = datalen; } @@ -599,21 +616,21 @@ _libssh2_wincng_load_private_memory(LIBSSH2_SESSION *session, (void)passphrase; - if (ret && tryLoadRSA) { + if(ret && tryLoadRSA) { ret = _libssh2_pem_parse_memory(session, PEM_RSA_HEADER, PEM_RSA_FOOTER, privatekeydata, privatekeydata_len, &data, &datalen); } - if (ret && tryLoadDSA) { + if(ret && tryLoadDSA) { ret = _libssh2_pem_parse_memory(session, PEM_DSA_HEADER, PEM_DSA_FOOTER, privatekeydata, privatekeydata_len, &data, &datalen); } - if (!ret) { + if(!ret) { *ppbEncoded = data; *pcbEncoded = datalen; } @@ -636,12 +653,12 @@ _libssh2_wincng_asn_decode(unsigned char *pbEncoded, lpszStructType, pbEncoded, cbEncoded, 0, NULL, NULL, &cbDecoded); - if (!ret) { + if(!ret) { return -1; } pbDecoded = malloc(cbDecoded); - if (!pbDecoded) { + if(!pbDecoded) { return -1; } @@ -649,7 +666,7 @@ _libssh2_wincng_asn_decode(unsigned char *pbEncoded, lpszStructType, pbEncoded, cbEncoded, 0, NULL, pbDecoded, &cbDecoded); - if (!ret) { + if(!ret) { _libssh2_wincng_safe_free(pbDecoded, cbDecoded); return -1; } @@ -670,25 +687,25 @@ _libssh2_wincng_bn_ltob(unsigned char *pbInput, unsigned char *pbOutput; unsigned long cbOutput, index, offset, length; - if (cbInput < 1) { + if(cbInput < 1) { return 0; } offset = 0; length = cbInput - 1; cbOutput = cbInput; - if (pbInput[length] & (1 << 7)) { + if(pbInput[length] & (1 << 7)) { offset++; cbOutput += offset; } pbOutput = (unsigned char *)malloc(cbOutput); - if (!pbOutput) { + if(!pbOutput) { return -1; } pbOutput[0] = 0; - for (index = 0; ((index + offset) < cbOutput) + for(index = 0; ((index + offset) < cbOutput) && (index < cbInput); index++) { pbOutput[index + offset] = pbInput[length - index]; } @@ -713,11 +730,11 @@ _libssh2_wincng_asn_decode_bn(unsigned char *pbEncoded, ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded, X509_MULTI_BYTE_UINT, &pbInteger, &cbInteger); - if (!ret) { + if(!ret) { ret = _libssh2_wincng_bn_ltob(((PCRYPT_DATA_BLOB)pbInteger)->pbData, ((PCRYPT_DATA_BLOB)pbInteger)->cbData, &pbDecoded, &cbDecoded); - if (!ret) { + if(!ret) { *ppbDecoded = pbDecoded; *pcbDecoded = cbDecoded; } @@ -742,30 +759,31 @@ _libssh2_wincng_asn_decode_bns(unsigned char *pbEncoded, ret = _libssh2_wincng_asn_decode(pbEncoded, cbEncoded, X509_SEQUENCE_OF_ANY, &pbDecoded, &cbDecoded); - if (!ret) { + if(!ret) { length = ((PCRYPT_DATA_BLOB)pbDecoded)->cbData; rpbDecoded = malloc(sizeof(PBYTE) * length); - if (rpbDecoded) { + if(rpbDecoded) { rcbDecoded = malloc(sizeof(DWORD) * length); - if (rcbDecoded) { - for (index = 0; index < length; index++) { + if(rcbDecoded) { + for(index = 0; index < length; index++) { pBlob = &((PCRYPT_DER_BLOB) ((PCRYPT_DATA_BLOB)pbDecoded)->pbData)[index]; ret = _libssh2_wincng_asn_decode_bn(pBlob->pbData, pBlob->cbData, &rpbDecoded[index], &rcbDecoded[index]); - if (ret) + if(ret) break; } - if (!ret) { + if(!ret) { *prpbDecoded = rpbDecoded; *prcbDecoded = rcbDecoded; *pcbCount = length; - } else { - for (length = 0; length < index; length++) { + } + else { + for(length = 0; length < index; length++) { _libssh2_wincng_safe_free(rpbDecoded[length], rcbDecoded[length]); rpbDecoded[length] = NULL; @@ -774,11 +792,13 @@ _libssh2_wincng_asn_decode_bns(unsigned char *pbEncoded, free(rpbDecoded); free(rcbDecoded); } - } else { + } + else { free(rpbDecoded); ret = -1; } - } else { + } + else { ret = -1; } @@ -795,13 +815,13 @@ _libssh2_wincng_bn_size(const unsigned char *bignum, { unsigned long offset; - if (!bignum) + if(!bignum) return 0; length--; offset = 0; - while (!(*(bignum + offset)) && (offset < length)) + while(!(*(bignum + offset)) && (offset < length)) offset++; length++; @@ -845,7 +865,7 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa, _libssh2_wincng_bn_size(ddata, dlen)); offset = sizeof(BCRYPT_RSAKEY_BLOB); keylen = offset + elen + mlen; - if (ddata && dlen > 0) { + if(ddata && dlen > 0) { p1len = max(_libssh2_wincng_bn_size(pdata, plen), _libssh2_wincng_bn_size(e1data, e1len)); p2len = max(_libssh2_wincng_bn_size(qdata, qlen), @@ -854,7 +874,7 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa, } key = malloc(keylen); - if (!key) { + if(!key) { return -1; } @@ -870,45 +890,45 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa, memcpy(key + offset, edata, elen); offset += elen; - if (nlen < mlen) + if(nlen < mlen) memcpy(key + offset + mlen - nlen, ndata, nlen); else memcpy(key + offset, ndata + nlen - mlen, mlen); - if (ddata && dlen > 0) { + if(ddata && dlen > 0) { offset += mlen; - if (plen < p1len) + if(plen < p1len) memcpy(key + offset + p1len - plen, pdata, plen); else memcpy(key + offset, pdata + plen - p1len, p1len); offset += p1len; - if (qlen < p2len) + if(qlen < p2len) memcpy(key + offset + p2len - qlen, qdata, qlen); else memcpy(key + offset, qdata + qlen - p2len, p2len); offset += p2len; - if (e1len < p1len) + if(e1len < p1len) memcpy(key + offset + p1len - e1len, e1data, e1len); else memcpy(key + offset, e1data + e1len - p1len, p1len); offset += p1len; - if (e2len < p2len) + if(e2len < p2len) memcpy(key + offset + p2len - e2len, e2data, e2len); else memcpy(key + offset, e2data + e2len - p2len, p2len); offset += p2len; - if (coefflen < p1len) + if(coefflen < p1len) memcpy(key + offset + p1len - coefflen, coeffdata, coefflen); else memcpy(key + offset, coeffdata + coefflen - p1len, p1len); offset += p1len; - if (dlen < mlen) + if(dlen < mlen) memcpy(key + offset + mlen - dlen, ddata, dlen); else memcpy(key + offset, ddata + dlen - mlen, mlen); @@ -917,7 +937,8 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa, rsakey->Magic = BCRYPT_RSAFULLPRIVATE_MAGIC; rsakey->cbPrime1 = p1len; rsakey->cbPrime2 = p2len; - } else { + } + else { lpszBlobType = BCRYPT_RSAPUBLIC_BLOB; rsakey->Magic = BCRYPT_RSAPUBLIC_MAGIC; rsakey->cbPrime1 = 0; @@ -927,14 +948,14 @@ _libssh2_wincng_rsa_new(libssh2_rsa_ctx **rsa, ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL, lpszBlobType, &hKey, key, keylen, 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { _libssh2_wincng_safe_free(key, keylen); return -1; } *rsa = malloc(sizeof(libssh2_rsa_ctx)); - if (!(*rsa)) { + if(!(*rsa)) { BCryptDestroyKey(hKey); _libssh2_wincng_safe_free(key, keylen); return -1; @@ -967,7 +988,7 @@ _libssh2_wincng_rsa_new_private_parse(libssh2_rsa_ctx **rsa, _libssh2_wincng_safe_free(pbEncoded, cbEncoded); - if (ret) { + if(ret) { return -1; } @@ -975,14 +996,14 @@ _libssh2_wincng_rsa_new_private_parse(libssh2_rsa_ctx **rsa, ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL, LEGACY_RSAPRIVATE_BLOB, &hKey, pbStructInfo, cbStructInfo, 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { _libssh2_wincng_safe_free(pbStructInfo, cbStructInfo); return -1; } *rsa = malloc(sizeof(libssh2_rsa_ctx)); - if (!(*rsa)) { + if(!(*rsa)) { BCryptDestroyKey(hKey); _libssh2_wincng_safe_free(pbStructInfo, cbStructInfo); return -1; @@ -1012,7 +1033,7 @@ _libssh2_wincng_rsa_new_private(libssh2_rsa_ctx **rsa, ret = _libssh2_wincng_load_private(session, filename, (const char *)passphrase, &pbEncoded, &cbEncoded, 1, 0); - if (ret) { + if(ret) { return -1; } @@ -1046,7 +1067,7 @@ _libssh2_wincng_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa, ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len, (const char *)passphrase, &pbEncoded, &cbEncoded, 1, 0); - if (ret) { + if(ret) { return -1; } @@ -1090,7 +1111,7 @@ _libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session, datalen = (unsigned long)hash_len; data = malloc(datalen); - if (!data) { + if(!data) { return -1; } @@ -1101,20 +1122,22 @@ _libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session, ret = BCryptSignHash(rsa->hKey, &paddingInfo, data, datalen, NULL, 0, &cbData, BCRYPT_PAD_PKCS1); - if (BCRYPT_SUCCESS(ret)) { + if(BCRYPT_SUCCESS(ret)) { siglen = cbData; sig = LIBSSH2_ALLOC(session, siglen); - if (sig) { + if(sig) { ret = BCryptSignHash(rsa->hKey, &paddingInfo, data, datalen, sig, siglen, &cbData, BCRYPT_PAD_PKCS1); - if (BCRYPT_SUCCESS(ret)) { + if(BCRYPT_SUCCESS(ret)) { *signature_len = siglen; *signature = sig; - } else { + } + else { LIBSSH2_FREE(session, sig); } - } else + } + else ret = STATUS_NO_MEMORY; } @@ -1126,7 +1149,7 @@ _libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session, void _libssh2_wincng_rsa_free(libssh2_rsa_ctx *rsa) { - if (!rsa) + if(!rsa) return; BCryptDestroyKey(rsa->hKey); @@ -1168,11 +1191,11 @@ _libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa, _libssh2_wincng_bn_size(ydata, ylen)); offset = sizeof(BCRYPT_DSA_KEY_BLOB); keylen = offset + length * 3; - if (xdata && xlen > 0) + if(xdata && xlen > 0) keylen += 20; key = malloc(keylen); - if (!key) { + if(!key) { return -1; } @@ -1186,39 +1209,40 @@ _libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa, memset(dsakey->Count, -1, sizeof(dsakey->Count)); memset(dsakey->Seed, -1, sizeof(dsakey->Seed)); - if (qlen < 20) + if(qlen < 20) memcpy(dsakey->q + 20 - qlen, qdata, qlen); else memcpy(dsakey->q, qdata + qlen - 20, 20); - if (plen < length) + if(plen < length) memcpy(key + offset + length - plen, pdata, plen); else memcpy(key + offset, pdata + plen - length, length); offset += length; - if (glen < length) + if(glen < length) memcpy(key + offset + length - glen, gdata, glen); else memcpy(key + offset, gdata + glen - length, length); offset += length; - if (ylen < length) + if(ylen < length) memcpy(key + offset + length - ylen, ydata, ylen); else memcpy(key + offset, ydata + ylen - length, length); - if (xdata && xlen > 0) { + if(xdata && xlen > 0) { offset += length; - if (xlen < 20) + if(xlen < 20) memcpy(key + offset + 20 - xlen, xdata, xlen); else memcpy(key + offset, xdata + xlen - 20, 20); lpszBlobType = BCRYPT_DSA_PRIVATE_BLOB; dsakey->dwMagic = BCRYPT_DSA_PRIVATE_MAGIC; - } else { + } + else { lpszBlobType = BCRYPT_DSA_PUBLIC_BLOB; dsakey->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC; } @@ -1226,14 +1250,14 @@ _libssh2_wincng_dsa_new(libssh2_dsa_ctx **dsa, ret = BCryptImportKeyPair(_libssh2_wincng.hAlgDSA, NULL, lpszBlobType, &hKey, key, keylen, 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { _libssh2_wincng_safe_free(key, keylen); return -1; } *dsa = malloc(sizeof(libssh2_dsa_ctx)); - if (!(*dsa)) { + if(!(*dsa)) { BCryptDestroyKey(hKey); _libssh2_wincng_safe_free(key, keylen); return -1; @@ -1264,23 +1288,24 @@ _libssh2_wincng_dsa_new_private_parse(libssh2_dsa_ctx **dsa, _libssh2_wincng_safe_free(pbEncoded, cbEncoded); - if (ret) { + if(ret) { return -1; } - if (length == 6) { + if(length == 6) { ret = _libssh2_wincng_dsa_new(dsa, rpbDecoded[1], rcbDecoded[1], rpbDecoded[2], rcbDecoded[2], rpbDecoded[3], rcbDecoded[3], rpbDecoded[4], rcbDecoded[4], rpbDecoded[5], rcbDecoded[5]); - } else { + } + else { ret = -1; } - for (index = 0; index < length; index++) { + for(index = 0; index < length; index++) { _libssh2_wincng_safe_free(rpbDecoded[index], rcbDecoded[index]); rpbDecoded[index] = NULL; rcbDecoded[index] = 0; @@ -1307,7 +1332,7 @@ _libssh2_wincng_dsa_new_private(libssh2_dsa_ctx **dsa, ret = _libssh2_wincng_load_private(session, filename, (const char *)passphrase, &pbEncoded, &cbEncoded, 0, 1); - if (ret) { + if(ret) { return -1; } @@ -1339,7 +1364,7 @@ _libssh2_wincng_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa, ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len, (const char *)passphrase, &pbEncoded, &cbEncoded, 0, 1); - if (ret) { + if(ret) { return -1; } @@ -1378,7 +1403,7 @@ _libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa, datalen = hash_len; data = malloc(datalen); - if (!data) { + if(!data) { return -1; } @@ -1386,21 +1411,23 @@ _libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa, ret = BCryptSignHash(dsa->hKey, NULL, data, datalen, NULL, 0, &cbData, 0); - if (BCRYPT_SUCCESS(ret)) { + if(BCRYPT_SUCCESS(ret)) { siglen = cbData; - if (siglen == 40) { + if(siglen == 40) { sig = malloc(siglen); - if (sig) { + if(sig) { ret = BCryptSignHash(dsa->hKey, NULL, data, datalen, sig, siglen, &cbData, 0); - if (BCRYPT_SUCCESS(ret)) { + if(BCRYPT_SUCCESS(ret)) { memcpy(sig_fixed, sig, siglen); } _libssh2_wincng_safe_free(sig, siglen); - } else + } + else ret = STATUS_NO_MEMORY; - } else + } + else ret = STATUS_NO_MEMORY; } @@ -1412,7 +1439,7 @@ _libssh2_wincng_dsa_sha1_sign(libssh2_dsa_ctx *dsa, void _libssh2_wincng_dsa_free(libssh2_dsa_ctx *dsa) { - if (!dsa) + if(!dsa) return; BCryptDestroyKey(dsa->hKey); @@ -1466,24 +1493,25 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session, _libssh2_wincng_safe_free(pbEncoded, cbEncoded); - if (ret) { + if(ret) { return -1; } - if (length == 9) { /* private RSA key */ + if(length == 9) { /* private RSA key */ mthlen = 7; mth = LIBSSH2_ALLOC(session, mthlen); - if (mth) { + if(mth) { memcpy(mth, "ssh-rsa", mthlen); - } else { + } + else { ret = -1; } keylen = 4 + mthlen + 4 + rcbDecoded[2] + 4 + rcbDecoded[1]; key = LIBSSH2_ALLOC(session, keylen); - if (key) { + if(key) { offset = _libssh2_wincng_pub_priv_write(key, 0, mth, mthlen); offset = _libssh2_wincng_pub_priv_write(key, offset, @@ -1493,23 +1521,26 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session, _libssh2_wincng_pub_priv_write(key, offset, rpbDecoded[1], rcbDecoded[1]); - } else { + } + else { ret = -1; } - } else if (length == 6) { /* private DSA key */ + } + else if(length == 6) { /* private DSA key */ mthlen = 7; mth = LIBSSH2_ALLOC(session, mthlen); - if (mth) { + if(mth) { memcpy(mth, "ssh-dss", mthlen); - } else { + } + else { ret = -1; } keylen = 4 + mthlen + 4 + rcbDecoded[1] + 4 + rcbDecoded[2] + 4 + rcbDecoded[3] + 4 + rcbDecoded[4]; key = LIBSSH2_ALLOC(session, keylen); - if (key) { + if(key) { offset = _libssh2_wincng_pub_priv_write(key, 0, mth, mthlen); offset = _libssh2_wincng_pub_priv_write(key, offset, @@ -1527,16 +1558,18 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session, _libssh2_wincng_pub_priv_write(key, offset, rpbDecoded[4], rcbDecoded[4]); - } else { + } + else { ret = -1; } - } else { + } + else { ret = -1; } - for (index = 0; index < length; index++) { + for(index = 0; index < length; index++) { _libssh2_wincng_safe_free(rpbDecoded[index], rcbDecoded[index]); rpbDecoded[index] = NULL; rcbDecoded[index] = 0; @@ -1546,12 +1579,13 @@ _libssh2_wincng_pub_priv_keyfile_parse(LIBSSH2_SESSION *session, free(rcbDecoded); - if (ret) { - if (mth) + if(ret) { + if(mth) LIBSSH2_FREE(session, mth); - if (key) + if(key) LIBSSH2_FREE(session, key); - } else { + } + else { *method = mth; *method_len = mthlen; *pubkeydata = key; @@ -1578,7 +1612,7 @@ _libssh2_wincng_pub_priv_keyfile(LIBSSH2_SESSION *session, ret = _libssh2_wincng_load_private(session, privatekey, passphrase, &pbEncoded, &cbEncoded, 1, 1); - if (ret) { + if(ret) { return -1; } @@ -1617,7 +1651,7 @@ _libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session, ret = _libssh2_wincng_load_private_memory(session, privatekeydata, privatekeydata_len, passphrase, &pbEncoded, &cbEncoded, 1, 1); - if (ret) { + if(ret) { return -1; } @@ -1634,8 +1668,8 @@ _libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session, (void)passphrase; return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unable to extract public key from private key in memory: " - "Method unsupported in Windows CNG backend"); + "Unable to extract public key from private key in memory: " + "Method unsupported in Windows CNG backend"); #endif /* HAVE_LIBCRYPT32 */ } @@ -1653,8 +1687,9 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, { BCRYPT_KEY_HANDLE hKey; BCRYPT_KEY_DATA_BLOB_HEADER *header; - unsigned char *pbKeyObject, *pbIV, *key; - unsigned long dwKeyObject, dwIV, dwBlockLength, cbData, keylen; + unsigned char *pbKeyObject, *pbIV, *key, *pbCtr, *pbIVCopy; + unsigned long dwKeyObject, dwIV, dwCtrLength, dwBlockLength, + cbData, keylen; int ret; (void)encrypt; @@ -1663,7 +1698,7 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, (unsigned char *)&dwKeyObject, sizeof(dwKeyObject), &cbData, 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { return -1; } @@ -1671,19 +1706,19 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, (unsigned char *)&dwBlockLength, sizeof(dwBlockLength), &cbData, 0); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { return -1; } pbKeyObject = malloc(dwKeyObject); - if (!pbKeyObject) { + if(!pbKeyObject) { return -1; } keylen = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + type.dwKeyLength; key = malloc(keylen); - if (!key) { + if(!key) { free(pbKeyObject); return -1; } @@ -1702,36 +1737,46 @@ _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, _libssh2_wincng_safe_free(key, keylen); - if (!BCRYPT_SUCCESS(ret)) { + if(!BCRYPT_SUCCESS(ret)) { _libssh2_wincng_safe_free(pbKeyObject, dwKeyObject); return -1; } - if (type.dwUseIV) { - pbIV = malloc(dwBlockLength); - if (!pbIV) { + pbIV = NULL; + pbCtr = NULL; + dwIV = 0; + dwCtrLength = 0; + + if(type.useIV || type.ctrMode) { + pbIVCopy = malloc(dwBlockLength); + if(!pbIVCopy) { BCryptDestroyKey(hKey); _libssh2_wincng_safe_free(pbKeyObject, dwKeyObject); return -1; } - dwIV = dwBlockLength; - memcpy(pbIV, iv, dwIV); - } else { - pbIV = NULL; - dwIV = 0; - } + memcpy(pbIVCopy, iv, dwBlockLength); + if(type.ctrMode) { + pbCtr = pbIVCopy; + dwCtrLength = dwBlockLength; + } + else if(type.useIV) { + pbIV = pbIVCopy; + dwIV = dwBlockLength; + } + } ctx->hKey = hKey; ctx->pbKeyObject = pbKeyObject; ctx->pbIV = pbIV; + ctx->pbCtr = pbCtr; ctx->dwKeyObject = dwKeyObject; ctx->dwIV = dwIV; ctx->dwBlockLength = dwBlockLength; + ctx->dwCtrLength = dwCtrLength; return 0; } - int _libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx, _libssh2_cipher_type(type), @@ -1739,7 +1784,7 @@ _libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx, unsigned char *block, size_t blocklen) { - unsigned char *pbOutput; + unsigned char *pbOutput, *pbInput; unsigned long cbOutput, cbInput; int ret; @@ -1747,31 +1792,47 @@ _libssh2_wincng_cipher_crypt(_libssh2_cipher_ctx *ctx, cbInput = (unsigned long)blocklen; - if (encrypt) { - ret = BCryptEncrypt(ctx->hKey, block, cbInput, NULL, - ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0); - } else { - ret = BCryptDecrypt(ctx->hKey, block, cbInput, NULL, + if(type.ctrMode) { + pbInput = ctx->pbCtr; + } + else { + pbInput = block; + } + + if(encrypt || type.ctrMode) { + ret = BCryptEncrypt(ctx->hKey, pbInput, cbInput, NULL, ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0); } - if (BCRYPT_SUCCESS(ret)) { + else { + ret = BCryptDecrypt(ctx->hKey, pbInput, cbInput, NULL, + ctx->pbIV, ctx->dwIV, NULL, 0, &cbOutput, 0); + } + if(BCRYPT_SUCCESS(ret)) { pbOutput = malloc(cbOutput); - if (pbOutput) { - if (encrypt) { - ret = BCryptEncrypt(ctx->hKey, block, cbInput, NULL, - ctx->pbIV, ctx->dwIV, - pbOutput, cbOutput, &cbOutput, 0); - } else { - ret = BCryptDecrypt(ctx->hKey, block, cbInput, NULL, + if(pbOutput) { + if(encrypt || type.ctrMode) { + ret = BCryptEncrypt(ctx->hKey, pbInput, cbInput, NULL, ctx->pbIV, ctx->dwIV, pbOutput, cbOutput, &cbOutput, 0); } - if (BCRYPT_SUCCESS(ret)) { - memcpy(block, pbOutput, cbOutput); + else { + ret = BCryptDecrypt(ctx->hKey, pbInput, cbInput, NULL, + ctx->pbIV, ctx->dwIV, + pbOutput, cbOutput, &cbOutput, 0); + } + if(BCRYPT_SUCCESS(ret)) { + if(type.ctrMode) { + _libssh2_xor_data(block, block, pbOutput, blocklen); + _libssh2_aes_ctr_increment(ctx->pbCtr, ctx->dwCtrLength); + } + else { + memcpy(block, pbOutput, cbOutput); + } } _libssh2_wincng_safe_free(pbOutput, cbOutput); - } else + } + else ret = STATUS_NO_MEMORY; } @@ -1791,6 +1852,10 @@ _libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx) _libssh2_wincng_safe_free(ctx->pbIV, ctx->dwBlockLength); ctx->pbIV = NULL; ctx->dwBlockLength = 0; + + _libssh2_wincng_safe_free(ctx->pbCtr, ctx->dwCtrLength); + ctx->pbCtr = NULL; + ctx->dwCtrLength = 0; } @@ -1805,7 +1870,7 @@ _libssh2_wincng_bignum_init(void) _libssh2_bn *bignum; bignum = (_libssh2_bn *)malloc(sizeof(_libssh2_bn)); - if (bignum) { + if(bignum) { bignum->bignum = NULL; bignum->length = 0; } @@ -1818,20 +1883,20 @@ _libssh2_wincng_bignum_resize(_libssh2_bn *bn, unsigned long length) { unsigned char *bignum; - if (!bn) + if(!bn) return -1; - if (length == bn->length) + if(length == bn->length) return 0; #ifdef LIBSSH2_CLEAR_MEMORY - if (bn->bignum && bn->length > 0 && length < bn->length) { + if(bn->bignum && bn->length > 0 && length < bn->length) { SecureZeroMemory(bn->bignum + length, bn->length - length); } #endif bignum = realloc(bn->bignum, length); - if (!bignum) + if(!bignum) return -1; bn->bignum = bignum; @@ -1840,22 +1905,22 @@ _libssh2_wincng_bignum_resize(_libssh2_bn *bn, unsigned long length) return 0; } -int +static int _libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom) { unsigned char *bignum; unsigned long length; - if (!rnd) + if(!rnd) return -1; length = (unsigned long)(ceil((float)bits / 8) * sizeof(unsigned char)); - if (_libssh2_wincng_bignum_resize(rnd, length)) + if(_libssh2_wincng_bignum_resize(rnd, length)) return -1; bignum = rnd->bignum; - if (_libssh2_wincng_random(bignum, length)) + if(_libssh2_wincng_random(bignum, length)) return -1; /* calculate significant bits in most significant byte */ @@ -1865,24 +1930,23 @@ _libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom) bignum[0] &= (1 << (8 - bits)) - 1; /* set some special last bits in most significant byte */ - if (top == 0) + if(top == 0) bignum[0] |= (1 << (7 - bits)); - else if (top == 1) + else if(top == 1) bignum[0] |= (3 << (6 - bits)); /* make odd by setting first bit in least significant byte */ - if (bottom) + if(bottom) bignum[length - 1] |= 1; return 0; } -int +static int _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r, _libssh2_bn *a, _libssh2_bn *p, - _libssh2_bn *m, - _libssh2_bn_ctx *bnctx) + _libssh2_bn *m) { BCRYPT_KEY_HANDLE hKey; BCRYPT_RSAKEY_BLOB *rsakey; @@ -1890,16 +1954,14 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r, unsigned long keylen, offset, length; int ret; - (void)bnctx; - - if (!r || !a || !p || !m) + if(!r || !a || !p || !m) return -1; offset = sizeof(BCRYPT_RSAKEY_BLOB); keylen = offset + p->length + m->length; key = malloc(keylen); - if (!key) + if(!key) return -1; @@ -1921,14 +1983,14 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r, BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen, BCRYPT_NO_KEY_VALIDATION); - if (BCRYPT_SUCCESS(ret)) { + if(BCRYPT_SUCCESS(ret)) { ret = BCryptEncrypt(hKey, a->bignum, a->length, NULL, NULL, 0, NULL, 0, &length, BCRYPT_PAD_NONE); - if (BCRYPT_SUCCESS(ret)) { - if (!_libssh2_wincng_bignum_resize(r, length)) { + if(BCRYPT_SUCCESS(ret)) { + if(!_libssh2_wincng_bignum_resize(r, length)) { length = max(a->length, length); bignum = malloc(length); - if (bignum) { + if(bignum) { offset = length - a->length; memset(bignum, 0, offset); memcpy(bignum + offset, a->bignum, a->length); @@ -1939,12 +2001,14 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r, _libssh2_wincng_safe_free(bignum, length); - if (BCRYPT_SUCCESS(ret)) { + if(BCRYPT_SUCCESS(ret)) { _libssh2_wincng_bignum_resize(r, offset); } - } else + } + else ret = STATUS_NO_MEMORY; - } else + } + else ret = STATUS_NO_MEMORY; } @@ -1961,20 +2025,20 @@ _libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word) { unsigned long offset, number, bits, length; - if (!bn) + if(!bn) return -1; bits = 0; number = word; - while (number >>= 1) + while(number >>= 1) bits++; length = (unsigned long) (ceil(((double)(bits + 1)) / 8.0) * sizeof(unsigned char)); - if (_libssh2_wincng_bignum_resize(bn, length)) + if(_libssh2_wincng_bignum_resize(bn, length)) return -1; - for (offset = 0; offset < length; offset++) + for(offset = 0; offset < length; offset++) bn->bignum[offset] = (word >> (offset * 8)) & 0xff; return 0; @@ -1986,19 +2050,19 @@ _libssh2_wincng_bignum_bits(const _libssh2_bn *bn) unsigned char number; unsigned long offset, length, bits; - if (!bn) + if(!bn) return 0; length = bn->length - 1; offset = 0; - while (!(*(bn->bignum + offset)) && (offset < length)) + while(!(*(bn->bignum + offset)) && (offset < length)) offset++; bits = (length - offset) * 8; number = bn->bignum[offset]; - while (number >>= 1) + while(number >>= 1) bits++; bits++; @@ -2013,10 +2077,10 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len, unsigned char *bignum; unsigned long offset, length, bits; - if (!bn || !bin || !len) + if(!bn || !bin || !len) return; - if (_libssh2_wincng_bignum_resize(bn, len)) + if(_libssh2_wincng_bignum_resize(bn, len)) return; memcpy(bn->bignum, bin, len); @@ -2026,7 +2090,7 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len, sizeof(unsigned char)); offset = bn->length - length; - if (offset > 0) { + if(offset > 0) { memmove(bn->bignum, bn->bignum + offset, length); #ifdef LIBSSH2_CLEAR_MEMORY @@ -2034,7 +2098,7 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len, #endif bignum = realloc(bn->bignum, length); - if (bignum) { + if(bignum) { bn->bignum = bignum; bn->length = length; } @@ -2044,7 +2108,7 @@ _libssh2_wincng_bignum_from_bin(_libssh2_bn *bn, unsigned long len, void _libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin) { - if (bin && bn && bn->bignum && bn->length > 0) { + if(bin && bn && bn->bignum && bn->length > 0) { memcpy(bin, bn->bignum, bn->length); } } @@ -2052,8 +2116,8 @@ _libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin) void _libssh2_wincng_bignum_free(_libssh2_bn *bn) { - if (bn) { - if (bn->bignum) { + if(bn) { + if(bn->bignum) { _libssh2_wincng_safe_free(bn->bignum, bn->length); bn->bignum = NULL; } @@ -2064,13 +2128,41 @@ _libssh2_wincng_bignum_free(_libssh2_bn *bn) /* - * Windows CNG backend: other functions + * Windows CNG backend: Diffie-Hellman support. */ -void _libssh2_init_aes_ctr(void) +void +_libssh2_dh_init(_libssh2_dh_ctx *dhctx) { - /* no implementation */ - (void)0; + *dhctx = _libssh2_wincng_bignum_init(); /* Random from client */ +} + +int +_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, + _libssh2_bn *g, _libssh2_bn *p, int group_order) +{ + /* Generate x and e */ + if(_libssh2_wincng_bignum_rand(*dhctx, group_order * 8 - 1, 0, -1)) + return -1; + if(_libssh2_wincng_bignum_mod_exp(public, g, *dhctx, p)) + return -1; + return 0; +} + +int +_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p) +{ + /* Compute the shared secret */ + _libssh2_wincng_bignum_mod_exp(secret, f, *dhctx, p); + return 0; +} + +void +_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx) +{ + _libssh2_wincng_bignum_free(*dhctx); + *dhctx = NULL; } #endif /* LIBSSH2_WINCNG */ diff --git a/libssh2/src/wincng.h b/libssh2/src/wincng.h index 5219db7f8..f5838d0e6 100755 --- a/libssh2/src/wincng.h +++ b/libssh2/src/wincng.h @@ -55,7 +55,7 @@ #define LIBSSH2_HMAC_SHA512 1 #define LIBSSH2_AES 1 -#define LIBSSH2_AES_CTR 0 +#define LIBSSH2_AES_CTR 1 #define LIBSSH2_BLOWFISH 0 #define LIBSSH2_RC4 1 #define LIBSSH2_CAST 0 @@ -63,12 +63,20 @@ #define LIBSSH2_RSA 1 #define LIBSSH2_DSA 1 +#define LIBSSH2_ECDSA 0 +#define LIBSSH2_ED25519 0 #define MD5_DIGEST_LENGTH 16 #define SHA_DIGEST_LENGTH 20 #define SHA256_DIGEST_LENGTH 32 #define SHA512_DIGEST_LENGTH 64 +#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1) + +#if LIBSSH2_ECDSA +#else +#define _libssh2_ec_key void +#endif /*******************************************************************/ /* @@ -88,6 +96,7 @@ struct _libssh2_wincng_ctx { BCRYPT_ALG_HANDLE hAlgRSA; BCRYPT_ALG_HANDLE hAlgDSA; BCRYPT_ALG_HANDLE hAlgAES_CBC; + BCRYPT_ALG_HANDLE hAlgAES_ECB; BCRYPT_ALG_HANDLE hAlgRC4_NA; BCRYPT_ALG_HANDLE hAlg3DES_CBC; }; @@ -285,9 +294,11 @@ struct _libssh2_wincng_cipher_ctx { BCRYPT_KEY_HANDLE hKey; unsigned char *pbKeyObject; unsigned char *pbIV; + unsigned char *pbCtr; unsigned long dwKeyObject; unsigned long dwIV; unsigned long dwBlockLength; + unsigned long dwCtrLength; }; #define _libssh2_cipher_ctx struct _libssh2_wincng_cipher_ctx @@ -299,21 +310,21 @@ struct _libssh2_wincng_cipher_ctx { struct _libssh2_wincng_cipher_type { BCRYPT_ALG_HANDLE *phAlg; unsigned long dwKeyLength; - unsigned long dwUseIV; + int useIV; /* TODO: Convert to bool when a C89 compatible bool type + is defined */ + int ctrMode; }; #define _libssh2_cipher_type(type) struct _libssh2_wincng_cipher_type type -#define _libssh2_cipher_aes256ctr { NULL, 32, 1 } /* not supported */ -#define _libssh2_cipher_aes192ctr { NULL, 24, 1 } /* not supported */ -#define _libssh2_cipher_aes128ctr { NULL, 16, 1 } /* not supported */ -#define _libssh2_cipher_aes256 { &_libssh2_wincng.hAlgAES_CBC, 32, 1 } -#define _libssh2_cipher_aes192 { &_libssh2_wincng.hAlgAES_CBC, 24, 1 } -#define _libssh2_cipher_aes128 { &_libssh2_wincng.hAlgAES_CBC, 16, 1 } -#define _libssh2_cipher_blowfish { NULL, 16, 0 } /* not supported */ -#define _libssh2_cipher_arcfour { &_libssh2_wincng.hAlgRC4_NA, 16, 0 } -#define _libssh2_cipher_cast5 { NULL, 16, 0 } /* not supported */ -#define _libssh2_cipher_3des { &_libssh2_wincng.hAlg3DES_CBC, 24, 1 } +#define _libssh2_cipher_aes256ctr { &_libssh2_wincng.hAlgAES_ECB, 32, 0, 1 } +#define _libssh2_cipher_aes192ctr { &_libssh2_wincng.hAlgAES_ECB, 24, 0, 1 } +#define _libssh2_cipher_aes128ctr { &_libssh2_wincng.hAlgAES_ECB, 16, 0, 1 } +#define _libssh2_cipher_aes256 { &_libssh2_wincng.hAlgAES_CBC, 32, 1, 0 } +#define _libssh2_cipher_aes192 { &_libssh2_wincng.hAlgAES_CBC, 24, 1, 0 } +#define _libssh2_cipher_aes128 { &_libssh2_wincng.hAlgAES_CBC, 16, 1, 0 } +#define _libssh2_cipher_arcfour { &_libssh2_wincng.hAlgRC4_NA, 16, 0, 0 } +#define _libssh2_cipher_3des { &_libssh2_wincng.hAlg3DES_CBC, 24, 1, 0 } /* * Windows CNG backend: Cipher functions @@ -358,10 +369,6 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void); _libssh2_wincng_bignum_init() #define _libssh2_bn_init_from_bin() \ _libssh2_bn_init() -#define _libssh2_bn_rand(bn, bits, top, bottom) \ - _libssh2_wincng_bignum_rand(bn, bits, top, bottom) -#define _libssh2_bn_mod_exp(r, a, p, m, ctx) \ - _libssh2_wincng_bignum_mod_exp(r, a, p, m, ctx) #define _libssh2_bn_set_word(bn, word) \ _libssh2_wincng_bignum_set_word(bn, word) #define _libssh2_bn_from_bin(bn, len, bin) \ @@ -374,6 +381,18 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void); #define _libssh2_bn_free(bn) \ _libssh2_wincng_bignum_free(bn) +/* + * Windows CNG backend: Diffie-Hellman support + */ + +#define _libssh2_dh_ctx struct _libssh2_wincng_bignum * +#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx) +#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \ + _libssh2_dh_key_pair(dhctx, public, g, p, group_order) +#define libssh2_dh_secret(dhctx, secret, f, p, bnctx) \ + _libssh2_dh_secret(dhctx, secret, f, p) +#define libssh2_dh_dtor(dhctx) _libssh2_dh_dtor(dhctx) + /*******************************************************************/ /* * Windows CNG backend: forward declarations @@ -381,7 +400,6 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void); void _libssh2_wincng_init(void); void _libssh2_wincng_free(void); int _libssh2_wincng_random(void *buf, int len); -void _libssh2_init_aes_ctr(void); int _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx, @@ -531,14 +549,6 @@ _libssh2_wincng_cipher_dtor(_libssh2_cipher_ctx *ctx); _libssh2_bn * _libssh2_wincng_bignum_init(void); int -_libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom); -int -_libssh2_wincng_bignum_mod_exp(_libssh2_bn *r, - _libssh2_bn *a, - _libssh2_bn *p, - _libssh2_bn *m, - _libssh2_bn_ctx *bnctx); -int _libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word); unsigned long _libssh2_wincng_bignum_bits(const _libssh2_bn *bn); @@ -549,3 +559,13 @@ void _libssh2_wincng_bignum_to_bin(const _libssh2_bn *bn, unsigned char *bin); void _libssh2_wincng_bignum_free(_libssh2_bn *bn); +extern void +_libssh2_dh_init(_libssh2_dh_ctx *dhctx); +extern int +_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public, + _libssh2_bn *g, _libssh2_bn *p, int group_order); +extern int +_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret, + _libssh2_bn *f, _libssh2_bn *p); +extern void +_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx); diff --git a/libssh2/test-driver b/libssh2/test-driver index 32bf39e83..b8521a482 100755 --- a/libssh2/test-driver +++ b/libssh2/test-driver @@ -1,9 +1,9 @@ #! /bin/sh # test-driver - basic testsuite driver script. -scriptversion=2012-06-27.10; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# Copyright (C) 2011-2018 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 @@ -16,7 +16,7 @@ scriptversion=2012-06-27.10; # UTC # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -44,13 +44,12 @@ print_usage () 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-SCRIPT + [--enable-hard-errors={yes|no}] [--] + TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] The '--test-name', '--log-file' and '--trs-file' options are mandatory. END } -# TODO: better error handling in option parsing (in particular, ensure -# TODO: $log_file, $trs_file and $test_name are defined). test_name= # Used for reporting. log_file= # Where to save the output of the test script. trs_file= # Where to save the metadata of the test run. @@ -69,10 +68,23 @@ while test $# -gt 0; do --enable-hard-errors) enable_hard_errors=$2; shift;; --) shift; break;; -*) usage_error "invalid option: '$1'";; + *) break;; esac shift done +missing_opts= +test x"$test_name" = x && missing_opts="$missing_opts --test-name" +test x"$log_file" = x && missing_opts="$missing_opts --log-file" +test x"$trs_file" = x && missing_opts="$missing_opts --trs-file" +if test x"$missing_opts" != x; then + usage_error "the following mandatory options are missing:$missing_opts" +fi + +if test $# -eq 0; then + usage_error "missing argument" +fi + if test $color_tests = yes; then # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'. red='' # Red. @@ -94,11 +106,14 @@ trap "st=143; $do_exit" 15 # Test script is run here. "$@" >$log_file 2>&1 estatus=$? + if test $enable_hard_errors = no && test $estatus -eq 99; then - estatus=1 + tweaked_estatus=1 +else + tweaked_estatus=$estatus fi -case $estatus:$expect_failure in +case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; @@ -107,6 +122,12 @@ case $estatus:$expect_failure in *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + # Report outcome to console. echo "${col}${res}${std}: $test_name" @@ -119,9 +140,9 @@ echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/libssh2/win32/GNUmakefile b/libssh2/win32/GNUmakefile index 86857513c..0971d891c 100644 --- a/libssh2/win32/GNUmakefile +++ b/libssh2/win32/GNUmakefile @@ -86,11 +86,26 @@ CAT = type ECHONL = $(ComSpec) /c echo. endif +ifeq ($(LIBSSH2_CC),) +LIBSSH2_CC := $(CROSSPREFIX)gcc +endif +ifeq ($(LIBSSH2_AR),) +LIBSSH2_AR := $(CROSSPREFIX)ar +endif +ifeq ($(LIBSSH2_RANLIB),) +LIBSSH2_RANLIB := $(CROSSPREFIX)ranlib +endif +ifeq ($(LIBSSH2_DLL_A_SUFFIX),) +LIBSSH2_DLL_A_SUFFIX := dll +endif + +libssh2_dll_LIBRARY = $(TARGET)$(LIBSSH2_DLL_SUFFIX).dll + # The following line defines your compiler. ifdef METROWERKS CC = mwcc else - CC = $(CROSSPREFIX)gcc + CC = $(LIBSSH2_CC) endif # Set environment var ARCH to your architecture to override autodetection. @@ -110,7 +125,7 @@ endif -include $(OBJDIR)/version.inc # Global flags for all compilers -CFLAGS = $(LIBSSH2_CFLAG_EXTRAS) $(OPT) -D$(DB) -DLIBSSH2_WIN32 # -DHAVE_CONFIG_H +CFLAGS = $(LIBSSH2_CFLAG_EXTRAS) $(OPT) -D$(DB) -DLIBSSH2_WIN32 -DHAVE_WINDOWS_H # -DHAVE_CONFIG_H LDFLAGS = $(LIBSSH2_LDFLAG_EXTRAS) ifeq ($(CC),mwcc) @@ -128,13 +143,13 @@ CFLAGS += -nostdinc -gccinc -msgstyle gcc -inline off -opt nointrinsics -proc 58 CFLAGS += -ir "$(METROWERKS)/MSL" -ir "$(METROWERKS)/Win32-x86 Support" CFLAGS += -w on,nounused,nounusedexpr # -ansi strict else -LD = $(CROSSPREFIX)gcc -RC = $(CROSSPREFIX)windres -LDFLAGS += -s -shared -Wl,--output-def,$(TARGET).def,--out-implib,$(TARGET)dll.a -AR = $(CROSSPREFIX)ar -ARFLAGS = -cq LIBEXT = a -RANLIB = $(CROSSPREFIX)ranlib +LD = $(LIBSSH2_CC) +RC = $(CROSSPREFIX)windres +LDFLAGS += -s -shared -Wl,--output-def,$(libssh2_dll_LIBRARY:.dll=.def),--out-implib,$(TARGET)$(LIBSSH2_DLL_A_SUFFIX).$(LIBEXT) +AR = $(LIBSSH2_AR) +ARFLAGS = cru +RANLIB = $(LIBSSH2_RANLIB) RCFLAGS = -I $(PROOT)/include -O coff CFLAGS += -fno-builtin CFLAGS += -fno-strict-aliasing @@ -223,7 +238,7 @@ OBJL = $(OBJS) $(OBJDIR)/$(TARGET).res all: lib dll -dll: prebuild $(TARGET).dll +dll: prebuild $(libssh2_dll_LIBRARY) lib: prebuild $(TARGET).$(LIBEXT) @@ -248,7 +263,7 @@ dist: all $(DISTDIR) $(DISTDIR)/readme.txt @$(call COPY, $(PROOT)/INSTALL, $(DISTDIR)) @$(call COPY, $(PROOT)/README, $(DISTDIR)) @$(call COPY, $(PROOT)/RELEASE-NOTES, $(DISTDIR)) - @$(call COPY, $(TARGET).dll, $(DISTDIR)/bin) + @$(call COPY, $(libssh2_dll_LIBRARY), $(DISTDIR)/bin) @echo Creating $(DISTARC) @$(ZIP) $(DISTARC) $(DISTDIR)/* < $(DISTDIR)/readme.txt @@ -261,7 +276,7 @@ dev: all $(DEVLDIR) $(DEVLDIR)/readme.txt @$(call COPY, $(PROOT)/INSTALL, $(DEVLDIR)) @$(call COPY, $(PROOT)/README, $(DEVLDIR)) @$(call COPY, $(PROOT)/RELEASE-NOTES, $(DEVLDIR)) - @$(call COPY, $(TARGET).dll, $(DEVLDIR)/bin) + @$(call COPY, $(libssh2_dll_LIBRARY), $(DEVLDIR)/bin) @$(call COPY, $(PROOT)/include/*.h, $(DEVLDIR)/include) @$(call COPY, libssh2_config.h, $(DEVLDIR)/include) @$(call COPY, *.$(LIBEXT), $(DEVLDIR)/win32) @@ -284,7 +299,7 @@ testclean: clean clean: # $(call DEL, libssh2_config.h) - $(call DEL, $(TARGET).dll $(TARGET).def $(TARGET).$(LIBEXT) $(TARGET)dll.$(LIBEXT)) + $(call DEL, $(libssh2_dll_LIBRARY) $(libssh2_dll_LIBRARY:.dll=.def) $(TARGET).$(LIBEXT) $(TARGET)$(LIBSSH2_DLL_A_SUFFIX).$(LIBEXT)) $(call RMDIR, $(OBJDIR)) $(OBJDIR): @@ -304,7 +319,7 @@ ifdef RANLIB @$(RANLIB) $@ endif -$(TARGET).dll $(TARGET)dll.a: $(OBJL) +$(libssh2_dll_LIBRARY) $(TARGET)$(LIBSSH2_DLL_A_SUFFIX).$(LIBEXT): $(OBJL) @echo Linking $@ @$(call DEL, $@) @$(LD) $(LDFLAGS) $^ -o $@ $(LIBPATH) $(LDLIBS) diff --git a/libssh2/win32/libssh2.dsp b/libssh2/win32/libssh2.dsp index eac2b82b1..42a51b949 100644 --- a/libssh2/win32/libssh2.dsp +++ b/libssh2/win32/libssh2.dsp @@ -263,6 +263,14 @@ SOURCE=..\src\agent.c # End Source File # Begin Source File +SOURCE=..\src\bcrypt_pbkdf.c +# End Source File +# Begin Source File + +SOURCE=..\src\blowfish.c +# End Source File +# Begin Source File + SOURCE=..\src\channel.c # End Source File # Begin Source File @@ -355,6 +363,10 @@ SOURCE=..\src\wincng.c # PROP Default_Filter "h;hpp;hxx" # Begin Source File +SOURCE=..\src\blf.h +# End Source File +# Begin Source File + SOURCE=..\src\channel.h # End Source File # Begin Source File diff --git a/libssh2/win32/libssh2.vcxproj b/libssh2/win32/libssh2.vcxproj index c4375ae8f..ecd04a46d 100644 --- a/libssh2/win32/libssh2.vcxproj +++ b/libssh2/win32/libssh2.vcxproj @@ -140,6 +140,8 @@ + + @@ -163,6 +165,7 @@ +