Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libfilezilla for openSUSE:Factory checked in at 2021-12-12 21:27:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libfilezilla (Old) and /work/SRC/openSUSE:Factory/.libfilezilla.new.2520 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libfilezilla" Sun Dec 12 21:27:52 2021 rev:43 rq:940085 version:0.35.0 Changes: -------- --- /work/SRC/openSUSE:Factory/libfilezilla/libfilezilla.changes 2021-11-06 18:21:27.392994574 +0100 +++ /work/SRC/openSUSE:Factory/.libfilezilla.new.2520/libfilezilla.changes 2021-12-12 21:28:39.804378999 +0100 @@ -1,0 +2,16 @@ +Sun Dec 12 13:58:20 UTC 2021 - ecsos <ec...@opensuse.org> + +- Update to 0.35.0 + * New features: + - *nix: Added fz::forkblock which can be used to safely set + FD_CLOEXEC on descriptors even if the system lacks + SOCK_CLOCKEXEC, MSG_CMSG_CLOEXEC, pipe2 or accept4 + - macOS: Impersonation support + - Added fz::tls_layer::set_unexpected_eof_cb, in some + situations it may be desirable that unexpected closure is not + reported as a hard errror + * Bugfixes and minor changes: + - Added various convenience overloads for fz::buffer + - Performance improvement for fz::json::to_string + +------------------------------------------------------------------- Old: ---- libfilezilla-0.34.2.tar.bz2 New: ---- libfilezilla-0.35.0.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libfilezilla.spec ++++++ --- /var/tmp/diff_new_pack.Uo1ybM/_old 2021-12-12 21:28:40.232379253 +0100 +++ /var/tmp/diff_new_pack.Uo1ybM/_new 2021-12-12 21:28:40.236379255 +0100 @@ -16,11 +16,11 @@ # -%define major 22 +%define major 23 %define libname %{name}%{major} %define develname %{name}-devel Name: libfilezilla -Version: 0.34.2 +Version: 0.35.0 Release: 0 Summary: C++ library for filezilla License: GPL-2.0-or-later ++++++ libfilezilla-0.34.2.tar.bz2 -> libfilezilla-0.35.0.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/NEWS new/libfilezilla-0.35.0/NEWS --- old/libfilezilla-0.34.2/NEWS 2021-10-26 13:54:12.000000000 +0200 +++ new/libfilezilla-0.35.0/NEWS 2021-12-08 16:09:44.000000000 +0100 @@ -1,3 +1,11 @@ +0.35.0 (2021-12-08) + ++ *nix: Added fz::forkblock which can be used to safely set FD_CLOEXEC on descriptors even if the system lacks SOCK_CLOCKEXEC, MSG_CMSG_CLOEXEC, pipe2 or accept4 ++ macOS: Impersonation support ++ Added fz::tls_layer::set_unexpected_eof_cb, in some situations it may be desirable that unexpected closure is not reported as a hard errror +- Added various convenience overloads for fz::buffer +- Performance improvement for fz::json::to_string + 0.34.2 (2021-10-26) + fz::file::open now returns fz::result diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/configure new/libfilezilla-0.35.0/configure --- old/libfilezilla-0.34.2/configure 2021-10-26 13:54:27.000000000 +0200 +++ new/libfilezilla-0.35.0/configure 2021-12-08 16:11:25.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libfilezilla 0.34.2. +# Generated by GNU Autoconf 2.69 for libfilezilla 0.35.0. # # Report bugs to <tim.ko...@filezilla-project.org>. # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='libfilezilla' PACKAGE_TARNAME='libfilezilla' -PACKAGE_VERSION='0.34.2' -PACKAGE_STRING='libfilezilla 0.34.2' +PACKAGE_VERSION='0.35.0' +PACKAGE_STRING='libfilezilla 0.35.0' PACKAGE_BUGREPORT='tim.ko...@filezilla-project.org' PACKAGE_URL='https://lib.filezilla-project.org/' @@ -1451,7 +1451,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libfilezilla 0.34.2 to adapt to many kinds of systems. +\`configure' configures libfilezilla 0.35.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1522,7 +1522,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libfilezilla 0.34.2:";; + short | recursive ) echo "Configuration of libfilezilla 0.35.0:";; esac cat <<\_ACEOF @@ -1678,7 +1678,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libfilezilla configure 0.34.2 +libfilezilla configure 0.35.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2123,7 +2123,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libfilezilla $as_me 0.34.2, which was +It was created by libfilezilla $as_me 0.35.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2478,7 +2478,7 @@ # If any interfaces have been added since the last public release, then increment age. # If any interfaces have been removed or changed since the last public release, then set age to 0. # CURRENT:REVISION:AGE -LIBRARY_VERSION=22:0:0 +LIBRARY_VERSION=23:0:0 ac_config_headers="$ac_config_headers config/config.hpp" @@ -2994,7 +2994,7 @@ # Define the identity of the package. PACKAGE='libfilezilla' - VERSION='0.34.2' + VERSION='0.35.0' cat >>confdefs.h <<_ACEOF @@ -22459,7 +22459,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libfilezilla $as_me 0.34.2, which was +This file was extended by libfilezilla $as_me 0.35.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -22526,7 +22526,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libfilezilla config.status 0.34.2 +libfilezilla config.status 0.35.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/configure.ac new/libfilezilla-0.35.0/configure.ac --- old/libfilezilla-0.34.2/configure.ac 2021-10-26 13:54:12.000000000 +0200 +++ new/libfilezilla-0.35.0/configure.ac 2021-12-08 16:09:44.000000000 +0100 @@ -1,4 +1,4 @@ -???AC_INIT([libfilezilla],[0.34.2],[tim.ko...@filezilla-project.org],[],[https://lib.filezilla-project.org/]) +???AC_INIT([libfilezilla],[0.35.0],[tim.ko...@filezilla-project.org],[],[https://lib.filezilla-project.org/]) # Update the version information only immediately before a public release of your software # If the library source code has changed at all since the last update, then increment revision (???c:r:a??? becomes ???c:r+1:a???). @@ -6,7 +6,7 @@ # If any interfaces have been added since the last public release, then increment age. # If any interfaces have been removed or changed since the last public release, then set age to 0. # CURRENT:REVISION:AGE -LIBRARY_VERSION=22:0:0 +LIBRARY_VERSION=23:0:0 AC_CONFIG_HEADERS([config/config.hpp]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/demos/Makefile.am new/libfilezilla-0.35.0/demos/Makefile.am --- old/libfilezilla-0.34.2/demos/Makefile.am 2021-08-31 16:47:29.000000000 +0200 +++ new/libfilezilla-0.35.0/demos/Makefile.am 2021-12-08 16:09:44.000000000 +0100 @@ -55,7 +55,7 @@ list_DEPENDENCIES = ../lib/libfilezilla.la -if FZ_UNIX +if !FZ_WINDOWS noinst_PROGRAMS += impersonation impersonation_SOURCES = impersonation.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/demos/Makefile.in new/libfilezilla-0.35.0/demos/Makefile.in --- old/libfilezilla-0.34.2/demos/Makefile.in 2021-10-26 13:54:26.000000000 +0200 +++ new/libfilezilla-0.35.0/demos/Makefile.in 2021-12-08 16:11:25.000000000 +0100 @@ -91,7 +91,7 @@ host_triplet = @host@ noinst_PROGRAMS = timer_fizzbuzz$(EXEEXT) process$(EXEEXT) \ events$(EXEEXT) list$(EXEEXT) $(am__EXEEXT_1) -@FZ_UNIX_TRUE@am__append_1 = impersonation +@FZ_WINDOWS_FALSE@am__append_1 = impersonation subdir = demos ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \ @@ -122,7 +122,7 @@ CONFIG_HEADER = $(top_builddir)/config/config.hpp CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -@FZ_UNIX_TRUE@am__EXEEXT_1 = impersonation$(EXEEXT) +@FZ_WINDOWS_FALSE@am__EXEEXT_1 = impersonation$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_events_OBJECTS = events-events.$(OBJEXT) events_OBJECTS = $(am_events_OBJECTS) @@ -135,8 +135,8 @@ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(events_LDFLAGS) $(LDFLAGS) -o $@ am__impersonation_SOURCES_DIST = impersonation.cpp -@FZ_UNIX_TRUE@am_impersonation_OBJECTS = \ -@FZ_UNIX_TRUE@ impersonation-impersonation.$(OBJEXT) +@FZ_WINDOWS_FALSE@am_impersonation_OBJECTS = \ +@FZ_WINDOWS_FALSE@ impersonation-impersonation.$(OBJEXT) impersonation_OBJECTS = $(am_impersonation_OBJECTS) impersonation_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -422,12 +422,13 @@ list_LDFLAGS = $(AM_LDFLAGS) -no-install list_LDADD = ../lib/libfilezilla.la $(libdeps) list_DEPENDENCIES = ../lib/libfilezilla.la -@FZ_UNIX_TRUE@impersonation_SOURCES = impersonation.cpp -@FZ_UNIX_TRUE@impersonation_CPPFLAGS = $(AM_CPPFLAGS) \ -@FZ_UNIX_TRUE@ -I$(top_srcdir)/lib -@FZ_UNIX_TRUE@impersonation_LDFLAGS = $(AM_LDFLAGS) -no-install -@FZ_UNIX_TRUE@impersonation_LDADD = ../lib/libfilezilla.la $(libdeps) -@FZ_UNIX_TRUE@impersonation_DEPENDENCIES = ../lib/libfilezilla.la +@FZ_WINDOWS_FALSE@impersonation_SOURCES = impersonation.cpp +@FZ_WINDOWS_FALSE@impersonation_CPPFLAGS = $(AM_CPPFLAGS) \ +@FZ_WINDOWS_FALSE@ -I$(top_srcdir)/lib +@FZ_WINDOWS_FALSE@impersonation_LDFLAGS = $(AM_LDFLAGS) -no-install +@FZ_WINDOWS_FALSE@impersonation_LDADD = ../lib/libfilezilla.la \ +@FZ_WINDOWS_FALSE@ $(libdeps) +@FZ_WINDOWS_FALSE@impersonation_DEPENDENCIES = ../lib/libfilezilla.la dist_noinst_DATA = \ demo_events.vcxproj \ demo_list.vcxproj \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/demos/impersonation.cpp new/libfilezilla-0.35.0/demos/impersonation.cpp --- old/libfilezilla-0.34.2/demos/impersonation.cpp 2021-08-31 16:47:29.000000000 +0200 +++ new/libfilezilla-0.35.0/demos/impersonation.cpp 2021-12-08 16:09:44.000000000 +0100 @@ -45,7 +45,11 @@ assert(recv(sockfd, &v, 1, 0) == 1); std::cerr << "Child: Opening /tmp/test.txt\n"; - auto f = fz::file("/tmp/test.txt", fz::file::writing, fz::file::empty | fz::file::current_user_only); + fz::file f; + if (!f.open("/tmp/test.txt", fz::file::writing, fz::file::empty | fz::file::current_user_only)) { + std::cerr << "Could not open /tmp/test.txt\n"; + abort(); + } int fd = f.detach(); fz::buffer b; b.append("okay\n"); @@ -56,7 +60,9 @@ if (res < 0) { abort(); } - close(fd); + if (fd != 1) { + close(fd); + } fd = -1; } @@ -94,6 +100,10 @@ // Drop privileges fz::impersonation_token nobody("nobody", fz::impersonation_flag::pwless); + if (!nobody) { + std::cerr << "Parent: Could not get token for \"nobody\"\n"; + abort(); + } if (!fz::set_process_impersonation(nobody)) { std::cerr << "Parent: Could not drop privileges to \"nobody\"\n"; abort(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/buffer.cpp new/libfilezilla-0.35.0/lib/buffer.cpp --- old/libfilezilla-0.34.2/lib/buffer.cpp 2021-09-14 14:31:26.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/buffer.cpp 2021-12-08 16:09:44.000000000 +0100 @@ -176,11 +176,22 @@ append(reinterpret_cast<unsigned char const*>(data.data()), data.size()); } +void buffer::append(fz::buffer const& b) +{ + append(b.get(), b.size()); +} + void buffer::append(unsigned char v) { append(&v, 1); } +void buffer::append(size_t len, unsigned char c) +{ + memset(get(len), c, len); + add(len); +} + void buffer::reserve(size_t capacity) { if (capacity_ >= capacity) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/encode.cpp new/libfilezilla-0.35.0/lib/encode.cpp --- old/libfilezilla-0.34.2/lib/encode.cpp 2021-07-02 11:04:19.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/encode.cpp 2021-12-08 16:09:44.000000000 +0100 @@ -1,3 +1,4 @@ +#include "libfilezilla/buffer.hpp" #include "libfilezilla/encode.hpp" namespace fz { @@ -67,6 +68,13 @@ return ret; } +std::string base64_encode(fz::buffer const& in, base64_type type, bool pad) +{ + std::string ret; + base64_encode_impl(ret, in.to_view(), type, pad); + return ret; +} + void base64_encode_append(std::string& result, std::string_view const& in, base64_type type, bool pad) { base64_encode_impl(result, in, type, pad); @@ -172,6 +180,11 @@ return base64_decode_impl<std::vector<uint8_t>>(in); } +std::vector<uint8_t> base64_decode(fz::buffer const& in) +{ + return base64_decode_impl<std::vector<uint8_t>>(in.to_view()); +} + std::string base64_decode_s(std::string_view const& in) { return base64_decode_impl<std::string>(in); @@ -182,6 +195,11 @@ return base64_decode_impl<std::string>(in); } +std::string base64_decode_s(fz::buffer const& in) +{ + return base64_decode_impl<std::string>(in.to_view()); +} + namespace { template<typename DataContainer> @@ -275,6 +293,10 @@ return base32_encode_impl(in, type, pad); } +std::string base32_encode(fz::buffer const& in, base32_type type, bool pad) +{ + return base32_encode_impl(in.to_view(), type, pad); +} namespace { template<typename Ret, typename View> @@ -435,6 +457,11 @@ return base32_decode_impl<std::vector<uint8_t>>(in, type); } +std::vector<uint8_t> base32_decode(fz::buffer const& in, base32_type type) +{ + return base32_decode_impl<std::vector<uint8_t>>(in.to_view(), type); +} + std::string base32_decode_s(std::string_view const& in, base32_type type) { return base32_decode_impl<std::string>(in, type); @@ -445,6 +472,11 @@ return base32_decode_impl<std::string>(in, type); } +std::string base32_decode_s(fz::buffer const& in, base32_type type) +{ + return base32_decode_impl<std::string>(in.to_view(), type); +} + std::string percent_encode(std::string_view const& s, bool keep_slashes) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/glue/unix.cpp new/libfilezilla-0.35.0/lib/glue/unix.cpp --- old/libfilezilla-0.34.2/lib/glue/unix.cpp 2021-10-19 11:51:29.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/glue/unix.cpp 2021-12-08 16:09:44.000000000 +0100 @@ -1,5 +1,6 @@ #include "../libfilezilla/buffer.hpp" #include "../libfilezilla/glue/unix.hpp" +#include "../libfilezilla/process.hpp" #include <errno.h> #include <fcntl.h> @@ -28,7 +29,7 @@ return false; } -bool create_pipe(int fds[2], bool require_atomic_creation) +bool create_pipe(int fds[2]) { disable_sigpipe(); @@ -46,10 +47,7 @@ else #endif { - if (require_atomic_creation) { - return false; - } - + forkblock b; if (pipe(fds) != 0) { return false; } @@ -67,16 +65,28 @@ std::call_once(flag, [](){ signal(SIGPIPE, SIG_IGN); }); } -#if FZ_UNIX bool create_socketpair(int fds[2]) { disable_sigpipe(); - bool ret = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds) == 0; + int flags = SOCK_STREAM; +#ifdef SOCK_CLOEXEC + flags |= SOCK_CLOEXEC; +#else + forkblock b; +#endif + bool ret = socketpair(AF_UNIX, flags, 0, fds) == 0; if (!ret) { fds[0] = -1; fds[1] = -1; } +#ifndef SOCK_CLOEXEC + if (ret) { + set_cloexec(fds[0]); + set_cloexec(fds[1]); + } +#endif + return ret; } @@ -87,7 +97,7 @@ return -1; } if (socket < 0) { - error = EBADFD; + error = EBADF; return -1; } @@ -144,14 +154,18 @@ { fd = -1; if (socket < 0) { - error = EBADFD; + error = EBADF; return -1; } + int flags{}; #ifdef MSG_NOSIGNAL - const int flags = MSG_NOSIGNAL|MSG_CMSG_CLOEXEC; + flags |= MSG_NOSIGNAL; +#endif +#ifdef MSG_CMSG_CLOEXEC + flags |= MSG_CMSG_CLOEXEC; #else - const int flags = MSG_CMSG_CLOEXEC; + forkblock b; #endif struct msghdr msg{}; @@ -184,6 +198,9 @@ struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg); if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { memcpy(&fd, CMSG_DATA(cmsg), sizeof(int)); +#ifndef MSG_CMSG_CLOEXEC + set_cloexec(fd); +#endif }; } else { @@ -192,6 +209,5 @@ return res; } -#endif } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/impersonation.cpp new/libfilezilla-0.35.0/lib/impersonation.cpp --- old/libfilezilla-0.34.2/lib/impersonation.cpp 2021-10-19 11:51:29.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/impersonation.cpp 2021-12-08 16:10:58.000000000 +0100 @@ -1,20 +1,26 @@ #include "libfilezilla/impersonation.hpp" -#if FZ_UNIX +#if FZ_UNIX || FZ_MAC #include "libfilezilla/buffer.hpp" #include <optional> #include <tuple> +#if FZ_UNIX #include <crypt.h> +#include <shadow.h> +#endif #include <grp.h> #include <pwd.h> -#include <shadow.h> #include <string.h> #include <sys/types.h> #include <unistd.h> +#if FZ_MAC +#include <CoreServices/CoreServices.h> +#endif + namespace fz { namespace { struct passwd_holder { @@ -52,7 +58,7 @@ return ret; } - +#if FZ_UNIX struct shadow_holder { shadow_holder() = default; shadow_holder(shadow_holder const&) = delete; @@ -87,6 +93,7 @@ return ret; } +#endif } class impersonation_token_impl final @@ -119,7 +126,14 @@ int size = 100; while (true) { ret.resize(size); - int res = getgrouplist(username.c_str(), primary, ret.data(), &size); +#if FZ_MAC + typedef int glt; + static_assert(sizeof(gid_t) == sizeof(glt)); +#else + typedef gid_t glt; +#endif + + int res = getgrouplist(username.c_str(), primary, reinterpret_cast<glt*>(ret.data()), &size); if (size < 0 || (res < 0 && static_cast<size_t>(size) <= ret.size())) { // Something went wrong ret.clear(); @@ -133,26 +147,65 @@ } return ret; } + +bool check_auth(fz::native_string const& username, fz::native_string const& password) +{ +#if FZ_UNIX + auto shadow = get_shadow(username); + if (shadow.shadow_) { + struct crypt_data data{}; + char* encrypted = crypt_r(password.c_str(), shadow.shadow_->sp_pwdp, &data); + if (encrypted && !strcmp(encrypted, shadow.shadow_->sp_pwdp)) { + return true; + } + } +#elif FZ_MAC + bool ret{}; + + CFStringRef cfu = CFStringCreateWithCString(NULL, username.c_str(), kCFStringEncodingUTF8); + if (cfu) { + CSIdentityQueryRef q = CSIdentityQueryCreateForName(kCFAllocatorDefault, cfu, kCSIdentityQueryStringEquals, kCSIdentityClassUser, CSGetDefaultIdentityAuthority()); + if (q) { + if (CSIdentityQueryExecute(q, kCSIdentityQueryGenerateUpdateEvents, NULL)) { + CFArrayRef users = CSIdentityQueryCopyResults(q); + if (users) { + if (CFArrayGetCount(users) == 1) { + CSIdentityRef user = (CSIdentityRef)(CFArrayGetValueAtIndex(users, 0)); + if (user) { + CFStringRef pw = CFStringCreateWithCString(NULL, password.c_str(), kCFStringEncodingUTF8); + if (pw) { + ret = CSIdentityAuthenticateUsingPassword(user, pw); + CFRelease(pw); + } + } + } + CFRelease(users); + } + } + CFRelease(q); + } + CFRelease(cfu); + } + + return ret; +#endif + return false; +} } -impersonation_token::impersonation_token(fz::native_string const& username, fz::native_string const& passwd) +impersonation_token::impersonation_token(fz::native_string const& username, fz::native_string const& password) { auto pwd = get_passwd(username); if (pwd.pwd_) { - auto shadow = get_shadow(username); - if (shadow.shadow_) { - struct crypt_data data{}; - char* encrypted = crypt_r(passwd.c_str(), shadow.shadow_->sp_pwdp, &data); - if (encrypted && !strcmp(encrypted, shadow.shadow_->sp_pwdp)) { - impl_ = std::make_unique<impersonation_token_impl>(); - impl_->name_ = username; - if (pwd.pwd_->pw_dir) { - impl_->home_ = pwd.pwd_->pw_dir; - } - impl_->uid_ = pwd.pwd_->pw_uid; - impl_->gid_ = pwd.pwd_->pw_gid; - impl_->sup_groups_ = get_supplementary(username, pwd.pwd_->pw_gid); + if (check_auth(username, password)) { + impl_ = std::make_unique<impersonation_token_impl>(); + impl_->name_ = username; + if (pwd.pwd_->pw_dir) { + impl_->home_ = pwd.pwd_->pw_dir; } + impl_->uid_ = pwd.pwd_->pw_uid; + impl_->gid_ = pwd.pwd_->pw_gid; + impl_->sup_groups_ = get_supplementary(username, pwd.pwd_->pw_gid); } } } @@ -284,14 +337,14 @@ impersonation_token& impersonation_token::operator=(impersonation_token&&) noexcept = default; -impersonation_token::impersonation_token(fz::native_string const& username, fz::native_string const& passwd) +impersonation_token::impersonation_token(fz::native_string const& username, fz::native_string const& password) { if (username.find_first_of(L"\"/\\[]:;|=,+*?<>") != fz::native_string::npos) { return; } HANDLE token{INVALID_HANDLE_VALUE}; - DWORD res = LogonUserW(username.c_str(), nullptr, passwd.c_str(), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token); + DWORD res = LogonUserW(username.c_str(), nullptr, password.c_str(), LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token); if (!res) { return; } @@ -385,14 +438,28 @@ #elif 0 namespace fz { struct impersonation_token_impl{}; + impersonation_token::impersonation_token() {} +impersonation_token::impersonation_token(impersonation_token&&) noexcept {} +impersonation_token& impersonation_token::operator=(impersonation_token&&) noexcept { return *this; } + impersonation_token::impersonation_token(fz::native_string const&, fz::native_string const&) {} -impersonation_token::impersonation_token(fz::native_string const&, impersonation_flag) {} impersonation_token::~impersonation_token() noexcept {} +bool impersonation_token::operator==(impersonation_token const&) const { return true; } +bool impersonation_token::operator<(impersonation_token const&) const { return false; } + +fz::native_string impersonation_token::username() const { return {}; } +fz::native_string impersonation_token::home() const { return {}; } +std::size_t impersonation_token::hash() const noexcept { return {}; } + +#if FZ_UNIX +impersonation_token::impersonation_token(fz::native_string const&, impersonation_flag) {} bool set_process_impersonation(impersonation_token const&) { return false; } +#endif + } #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/json.cpp new/libfilezilla-0.35.0/lib/json.cpp --- old/libfilezilla-0.34.2/lib/json.cpp 2021-09-29 14:07:07.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/json.cpp 2021-12-08 16:09:45.000000000 +0100 @@ -113,9 +113,8 @@ } namespace { -void json_append_escaped(std::string& out, std::string const& s) +void json_append_escaped(std::string & out, std::string const& s) { - out.reserve(s.size()); for (auto & c : s) { switch (c) { case '\r': @@ -147,8 +146,13 @@ } std::string json::to_string(bool pretty, size_t depth) const +{ std::string ret; + to_string(ret, pretty, depth); + return ret; +} + +void json::to_string(std::string & ret, bool pretty, size_t depth) const { - std::string ret; switch (type_) { case json_type::object: { ret += '{'; @@ -177,7 +181,7 @@ if (pretty) { ret += ' '; } - ret += c.second.to_string(pretty, depth + 1); + c.second.to_string(ret, pretty, depth + 1); } if (pretty) { ret += '\n'; @@ -208,7 +212,7 @@ ret += "null"; } else { - ret += c.to_string(pretty, depth + 1); + c.to_string(ret, pretty, depth + 1); } } if (pretty) { @@ -219,24 +223,22 @@ break; } case json_type::boolean: - ret = std::get<3>(value_) ? "true" : "false"; + ret += std::get<3>(value_) ? "true" : "false"; break; case json_type::number: - ret = std::get<0>(value_); + ret += std::get<0>(value_); break; case json_type::null: - ret = "null"; + ret += "null"; break; case json_type::string: - ret = '"'; + ret += '"'; json_append_escaped(ret, std::get<0>(value_)); ret += '"'; break; case json_type::none: break; } - - return ret; } json json::parse(std::string_view const& s, size_t max_depth) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/buffer.hpp new/libfilezilla-0.35.0/lib/libfilezilla/buffer.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/buffer.hpp 2021-07-28 15:59:29.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/buffer.hpp 2021-12-08 16:09:45.000000000 +0100 @@ -4,6 +4,7 @@ #include "libfilezilla.hpp" #include <vector> +#include <type_traits> /** \file * \brief Declares fz::buffer @@ -65,6 +66,19 @@ /// Increase size by the passed amount. Call this after having obtained a writable buffer with get(size_t write_size) void add(size_t added); + /** + * \brief Overload of add for signed types, only adds if value is positive. + * + * Does nothing on values <= 0, useful for directly passing the ssize_t result of + * the system's recv() or read() functions. + */ + template<typename T, std::enable_if_t<std::is_signed_v<T>, int> = 0> + void add(T added) { + if (added > 0) { + add(static_cast<size_t>(added)); + } + } + /** \brief Removes consumed bytes from the beginning of the buffer. * * Undefined if consumed > size() @@ -85,7 +99,26 @@ void append(unsigned char const* data, size_t len); void append(std::string_view const& str); void append(std::vector<uint8_t> const& data); + void append(fz::buffer const& b); void append(unsigned char v); + void append(size_t len, unsigned char c); + + buffer& operator+=(unsigned char v) { + append(v); + return *this; + } + buffer& operator+=(std::string_view const& str) { + append(str); + return *this; + } + buffer& operator+=(std::vector<uint8_t> const& data) { + append(data); + return *this; + } + buffer& operator+=(fz::buffer const& b) { + append(b); + return *this; + } bool empty() const { return size_ == 0; } explicit operator bool() const { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/encode.hpp new/libfilezilla-0.35.0/lib/libfilezilla/encode.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/encode.hpp 2021-05-04 10:46:55.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/encode.hpp 2021-12-08 16:09:45.000000000 +0100 @@ -13,6 +13,7 @@ */ namespace fz { +class buffer; /** \brief Converts a hex digit to decimal int * @@ -112,6 +113,7 @@ /// \brief Encodes raw input string to base64 std::string FZ_PUBLIC_SYMBOL base64_encode(std::string_view const& in, base64_type type = base64_type::standard, bool pad = true); std::string FZ_PUBLIC_SYMBOL base64_encode(std::vector<uint8_t> const& in, base64_type type = base64_type::standard, bool pad = true); +std::string FZ_PUBLIC_SYMBOL base64_encode(fz::buffer const& in, base64_type type = base64_type::standard, bool pad = true); /** * \brief base64-encodes input and appends it to result. @@ -128,8 +130,10 @@ */ std::vector<uint8_t> FZ_PUBLIC_SYMBOL base64_decode(std::string_view const& in); std::vector<uint8_t> FZ_PUBLIC_SYMBOL base64_decode(std::wstring_view const& in); +std::vector<uint8_t> FZ_PUBLIC_SYMBOL base64_decode(fz::buffer const& in); std::string FZ_PUBLIC_SYMBOL base64_decode_s(std::string_view const& in); std::string FZ_PUBLIC_SYMBOL base64_decode_s(std::wstring_view const& in); +std::string FZ_PUBLIC_SYMBOL base64_decode_s(fz::buffer const& in); /** @@ -147,6 +151,7 @@ /// \brief Encodes raw input string to base32 std::string FZ_PUBLIC_SYMBOL base32_encode(std::string_view const& in, base32_type type = base32_type::standard, bool pad = true); std::string FZ_PUBLIC_SYMBOL base32_encode(std::vector<uint8_t> const& in, base32_type type = base32_type::standard, bool pad = true); +std::string FZ_PUBLIC_SYMBOL base32_encode(fz::buffer const& in, base32_type type = base32_type::standard, bool pad = true); /** * \brief Decodes base32, ignores whitespace. Returns empty string on invalid input. @@ -155,8 +160,10 @@ */ std::vector<uint8_t> FZ_PUBLIC_SYMBOL base32_decode(std::string_view const& in, base32_type type = base32_type::standard); std::vector<uint8_t> FZ_PUBLIC_SYMBOL base32_decode(std::wstring_view const& in, base32_type type = base32_type::standard); +std::vector<uint8_t> FZ_PUBLIC_SYMBOL base32_decode(fz::buffer const& in, base32_type type = base32_type::standard); std::string FZ_PUBLIC_SYMBOL base32_decode_s(std::string_view const& in, base32_type type = base32_type::standard); std::string FZ_PUBLIC_SYMBOL base32_decode_s(std::wstring_view const& in, base32_type type = base32_type::standard); +std::string FZ_PUBLIC_SYMBOL base32_decode_s(fz::buffer const& in, base32_type type = base32_type::standard); /** * \brief Percent-encodes string. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/glue/unix.hpp new/libfilezilla-0.35.0/lib/libfilezilla/glue/unix.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/glue/unix.hpp 2021-08-31 16:47:29.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/glue/unix.hpp 2021-12-08 16:09:45.000000000 +0100 @@ -11,7 +11,11 @@ namespace fz { -/// Sets FD_CLOEXEC on file descriptor +/** + * \brief Sets FD_CLOEXEC on file descriptor + * + * If you use this function, you probably also want to use \ref fz::forkblock + */ bool FZ_PUBLIC_SYMBOL set_cloexec(int fd); /** @@ -22,7 +26,7 @@ * * On failure sets fds to -1. */ -bool FZ_PUBLIC_SYMBOL create_pipe(int fds[2], bool require_atomic_creation = false); +bool FZ_PUBLIC_SYMBOL create_pipe(int fds[2]); /** \brief Disables SIGPIPE * @@ -30,7 +34,6 @@ */ void FZ_PUBLIC_SYMBOL disable_sigpipe(); -#if FZ_UNIX /// Creates a connected pair of unix domain sockets of SOCK_STREAM type bool FZ_PUBLIC_SYMBOL create_socketpair(int fds[2]); @@ -61,8 +64,6 @@ * fd is set to -1. */ int FZ_PUBLIC_SYMBOL read_fd(int socket, fz::buffer & buf, int &fd, int & error); -#endif - } #else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/impersonation.hpp new/libfilezilla-0.35.0/lib/libfilezilla/impersonation.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/impersonation.hpp 2021-09-29 14:07:07.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/impersonation.hpp 2021-12-08 16:09:59.000000000 +0100 @@ -7,14 +7,12 @@ #include "string.hpp" -#if FZ_UNIX || FZ_WINDOWS - #include <memory> #include <functional> namespace fz { -#if FZ_UNIX +#if !FZ_WINDOWS enum class impersonation_flag { pwless /// Impersonate as any user without checking credentials @@ -42,7 +40,7 @@ /// Creates an impersonation token, verifying credentials in the proceess explicit impersonation_token(fz::native_string const& username, fz::native_string const& password); -#if FZ_UNIX +#if !FZ_WINDOWS /// Doesn't verify credentials explicit impersonation_token(fz::native_string const& username, impersonation_flag flag); #endif @@ -70,7 +68,7 @@ std::unique_ptr<impersonation_token_impl> impl_; }; -#if FZ_UNIX +#if !FZ_WINDOWS /// Applies to the entire current process, calls setuid/setgid bool FZ_PUBLIC_SYMBOL set_process_impersonation(impersonation_token const& token); #endif @@ -90,6 +88,5 @@ }; } -#endif #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/json.hpp new/libfilezilla-0.35.0/lib/libfilezilla/json.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/json.hpp 2021-08-31 16:47:29.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/json.hpp 2021-12-08 16:09:45.000000000 +0100 @@ -128,13 +128,22 @@ explicit operator bool() const { return type_ != json_type::none; } - /** \brief Serializes JSONS structure + /** \brief Serializes JSON structure * * Children of objects with none type are ignored. * Children of arrays with none type are serialized as null. */ std::string to_string(bool pretty = false, size_t depth = 0) const; + /** \brief Serializes JSON structure + * + * Children of objects with none type are ignored. + * Children of arrays with none type are serialized as null. + * + * Does not clear output string + */ + void to_string(std::string & ret, bool pretty = false, size_t depth = 0) const; + /** \brief Parses JSON structure from input. * * Returns none if there is any null-byte in the input diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/local_filesys.hpp new/libfilezilla-0.35.0/lib/libfilezilla/local_filesys.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/local_filesys.hpp 2021-10-26 13:54:12.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/local_filesys.hpp 2021-12-08 16:10:13.000000000 +0100 @@ -86,7 +86,7 @@ * Takes ownership of the HANDLE. */ result begin_find_files(HANDLE dir, bool dirs_only = false, bool query_symlink_targets = true); -#elif FZ_UNIX +#else /** * \brief Begin enumerating a directory represented by a file descriptor. * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/optional.hpp new/libfilezilla-0.35.0/lib/libfilezilla/optional.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/optional.hpp 2020-10-13 14:16:49.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/optional.hpp 2021-12-08 16:09:45.000000000 +0100 @@ -19,11 +19,11 @@ class sparse_optional final { public: - sparse_optional(); + sparse_optional() noexcept = default; explicit sparse_optional(T const& v); /// Takes ownership of pointer. - explicit sparse_optional(T * v); + explicit sparse_optional(T * v) noexcept; sparse_optional(sparse_optional<T> const& v); sparse_optional(sparse_optional<T> && v) noexcept; @@ -46,16 +46,9 @@ sparse_optional<T>& operator=(sparse_optional<T> const& v); sparse_optional<T>& operator=(sparse_optional<T> && v) noexcept; private: - T* v_; + T* v_{}; }; - -template<typename T> -sparse_optional<T>::sparse_optional() - : v_() -{ -} - template<typename T> sparse_optional<T>::sparse_optional(T const& v) : v_(new T(v)) @@ -63,7 +56,7 @@ } template<typename T> -sparse_optional<T>::sparse_optional(T * v) +sparse_optional<T>::sparse_optional(T * v) noexcept : v_(v) { } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/process.hpp new/libfilezilla-0.35.0/lib/libfilezilla/process.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/process.hpp 2021-09-29 14:07:07.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/process.hpp 2021-12-08 16:09:45.000000000 +0100 @@ -118,6 +118,27 @@ */ bool FZ_PUBLIC_SYMBOL spawn_detached_process(std::vector<native_string> const& cmd_with_args); +#if !FZ_WINDOWS +/** \brief Temporarily suppress fork() if CLOEXEC cannot be set atomically at creation + * + * fz::process::spawn() will wait until there is no forkblock. + * + * In case of a wild fork() in third-party code, pthread_atfork handlers will enforce a wait. + * This may deadlock. Behavior is undefined if fork is called from a signal handler. + * + * If you fork while the current thread holds a forklock, the child will immediately exit. + */ +class FZ_PUBLIC_SYMBOL forkblock final +{ +public: + forkblock(); + ~forkblock(); + + forkblock(forkblock const&) = delete; + forkblock& operator=(forkblock const&) = delete; +}; +#endif + } #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/libfilezilla/tls_layer.hpp new/libfilezilla-0.35.0/lib/libfilezilla/tls_layer.hpp --- old/libfilezilla-0.34.2/lib/libfilezilla/tls_layer.hpp 2021-09-14 14:31:26.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/libfilezilla/tls_layer.hpp 2021-12-08 16:09:45.000000000 +0100 @@ -211,6 +211,22 @@ */ int new_session_ticket(); + /** \brief Sets a callback to control whether unexpected eof is seen as error + * + * With TLS, an EOF on the socket prior to receiving a closure alert normally is an error. + * In many cases this is harmless though, e.g. if the connection is idle. + * + * If this callback is set, premature termination is no longer seen as error if the + * callback returns false. + * + * Callback must not call any tls_layer function. + * + * Only controls the layer's own logging. Functions such as read will still return + * ECONNABORTED. + */ + void set_unexpected_eof_cb(std::function<bool()> const& cb); + void set_unexpected_eof_cb(std::function<bool()> && cb); + virtual socket_state get_state() const override; virtual int connect(native_string const& host, unsigned int port, address_type family = address_type::unknown) override; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/local_filesys.cpp new/libfilezilla-0.35.0/lib/local_filesys.cpp --- old/libfilezilla-0.34.2/lib/local_filesys.cpp 2021-10-26 13:54:12.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/local_filesys.cpp 2021-11-02 15:59:45.000000000 +0100 @@ -438,7 +438,7 @@ buffer_.resize(64 * 1024); return {result::ok}; } -#elif FZ_UNIX +#else result local_filesys::begin_find_files(int fd, bool dirs_only, bool query_symlink_targets) { end_find_files(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/process.cpp new/libfilezilla-0.35.0/lib/process.cpp --- old/libfilezilla-0.34.2/lib/process.cpp 2021-10-11 10:03:36.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/process.cpp 2021-12-08 16:09:45.000000000 +0100 @@ -263,6 +263,7 @@ #else #include "libfilezilla/glue/unix.hpp" +#include "libfilezilla/mutex.hpp" #include <errno.h> #include <fcntl.h> @@ -271,6 +272,7 @@ #include <string.h> #include <unistd.h> +#include <atomic> #include <memory> #include <vector> @@ -308,12 +310,12 @@ pipe(pipe const&) = delete; pipe& operator=(pipe const&) = delete; - bool create(bool require_atomic_creation = false) + bool create() { reset(); int fds[2]; - if (!create_pipe(fds, require_atomic_creation)) { + if (!create_pipe(fds)) { return false; } @@ -359,6 +361,9 @@ } *v = nullptr; } + +std::atomic<unsigned int> forkblocks_{}; +mutex forkblock_mtx_; } class process::impl @@ -395,6 +400,7 @@ std::unique_ptr<char *[]> argV; get_argv(cmd, begin, end, argList, argV); + scoped_lock l(forkblock_mtx_); pid_t pid = fork(); if (pid < 0) { return false; @@ -429,15 +435,11 @@ } } -#if FZ_UNIX if (it && *it) { if (!set_process_impersonation(*it)) { _exit(1); } } -#else - (void)it; -#endif // Execute process execv(cmd.c_str(), argV.get()); // noreturn on success @@ -777,12 +779,14 @@ pid_t const parent = getppid(); pid_t const ppgid = getpgid(parent); + scoped_lock l(forkblock_mtx_); + // We're using a pipe created with O_CLOEXEC to signal failure from execv. - // Note that this flags must be set atomically, setting FD_CLOEXEC after creation - // leads to a deadlock if a different thread calls exec in-between. - // Unfortunately even in early 2020, macOS does not have pipe2. + // Fortunately the forkblock avoids a deadlock if the cloexec flag isn't set + // atomically and another threa execs in-between, as even in 2022, macOS + // doesn't have pipe2. pipe errpipe; - errpipe.create(true); + errpipe.create(); pid_t pid = fork(); if (!pid) { @@ -838,4 +842,52 @@ } #endif } + +#if !FZ_WINDOWS +forkblock::forkblock() +{ + forkblock_mtx_.lock(); + ++forkblocks_; +} + +forkblock::~forkblock() +{ + --forkblocks_; + forkblock_mtx_.unlock(); +} + +namespace { +bool forked_child_{}; +void atfork_lock_forkblock() +{ + // Unsafe if fork is called from a signal handler + if (!forked_child_) { + forkblock_mtx_.lock(); + } +} + +void atfork_unlock_forkblock() +{ + // Unsafe if fork is called from a signal handler + if (!forked_child_) { + forkblock_mtx_.unlock(); + } +} + +void atfork_check_forkblocks() +{ + // Last line of defense. + if (forkblocks_) { + _exit(1); + } + forked_child_ = true; +} + + +int const atfork_registered = []() { + return pthread_atfork(&atfork_lock_forkblock, &atfork_unlock_forkblock, &atfork_check_forkblocks); +}(); +} +#endif + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/socket.cpp new/libfilezilla-0.35.0/lib/socket.cpp --- old/libfilezilla-0.34.2/lib/socket.cpp 2021-09-14 14:31:27.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/socket.cpp 2021-12-08 16:09:45.000000000 +0100 @@ -14,6 +14,7 @@ #ifndef FZ_WINDOWS #include "libfilezilla/glue/unix.hpp" + #include "libfilezilla/process.hpp" #define mutex mutex_override // Sadly on some platforms system headers include conflicting names #include <sys/types.h> @@ -582,6 +583,9 @@ if (fd == -1 && errno == EINVAL) #endif { +#if !defined(FZ_WINDOWS) + forkblock b; +#endif fd = ::socket(addr.ai_family, addr.ai_socktype, addr.ai_protocol); #if !defined(FZ_WINDOWS) @@ -1587,6 +1591,9 @@ if (fd == -1 && errno == ENOSYS) #endif { +#if !defined(FZ_WINDOWS) + forkblock b; +#endif fd = ::accept(fd_, nullptr, nullptr); #if !defined(FZ_WINDOWS) set_cloexec(fd); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/tls_layer.cpp new/libfilezilla-0.35.0/lib/tls_layer.cpp --- old/libfilezilla-0.34.2/lib/tls_layer.cpp 2021-09-14 14:31:27.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/tls_layer.cpp 2021-12-08 16:09:45.000000000 +0100 @@ -208,4 +208,19 @@ { return impl_ ? impl_->new_session_ticket() : false; } + +void tls_layer::set_unexpected_eof_cb(std::function<bool()> const& cb) +{ + if (impl_) { + std::function<bool()> f = cb; + impl_->set_unexpected_eof_cb(std::move(f)); + } +} + +void tls_layer::set_unexpected_eof_cb(std::function<bool()> && cb) +{ + if (impl_) { + impl_->set_unexpected_eof_cb(std::move(cb)); + } +} } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/tls_layer_impl.cpp new/libfilezilla-0.35.0/lib/tls_layer_impl.cpp --- old/libfilezilla-0.34.2/lib/tls_layer_impl.cpp 2021-10-26 13:54:12.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/tls_layer_impl.cpp 2021-12-08 16:09:45.000000000 +0100 @@ -1182,19 +1182,21 @@ { logger_.log(logmsg::debug_debug, L"tls_layer_impl::failure(%d)", code); if (code) { - log_error(code, function); - if (socket_eof_) { - if (code == GNUTLS_E_UNEXPECTED_PACKET_LENGTH -#ifdef GNUTLS_E_PREMATURE_TERMINATION - || code == GNUTLS_E_PREMATURE_TERMINATION -#endif - ) - { - if (state_ != socket_state::shut_down || !shutdown_silence_read_errors_) { - logger_.log(logmsg::status, server_ ? fztranslate("Client did not properly shut down TLS connection") : fztranslate("Server did not properly shut down TLS connection")); - } + bool suppress{}; + auto level = logmsg::error; + if (socket_eof_ && code == (GNUTLS_E_UNEXPECTED_PACKET_LENGTH || code == GNUTLS_E_PREMATURE_TERMINATION)) { + suppress = state_ == socket_state::shut_down && shutdown_silence_read_errors_; + if (!suppress && state_ == socket_state::connected && unexpected_eof_cb_) { + suppress = !unexpected_eof_cb_(); + } + if (suppress) { + level = logmsg::debug_warning; } } + log_error(code, function, level); + if (!suppress && socket_eof_ && (code == GNUTLS_E_UNEXPECTED_PACKET_LENGTH || code == GNUTLS_E_PREMATURE_TERMINATION)) { + logger_.log(logmsg::status, server_ ? fztranslate("Client did not properly shut down TLS connection") : fztranslate("Server did not properly shut down TLS connection")); + } } auto const oldState = state_; @@ -1281,8 +1283,10 @@ void tls_layer_impl::set_verification_result(bool trusted) { + logger_.log(logmsg::debug_verbose, L"set_verification_result(%s)", trusted ? "true"sv : "false"sv); + if (state_ != socket_state::connecting && !handshake_successful_) { - logger_.log(logmsg::debug_warning, L"TrustCurrentCert called at wrong time."); + logger_.log(logmsg::debug_warning, L"set_verification_result called at wrong time."); return; } @@ -1822,6 +1826,7 @@ } systemTrust = true; } + logger_.log(logmsg::debug_verbose, L"System trust store decision: %s", systemTrust ? "true"sv : "false"sv); } else { std::get<1>(lease).unlock(); @@ -1886,8 +1891,6 @@ } } - logger_.log(logmsg::status, fztranslate("Verifying certificate...")); - std::vector<x509_certificate> certificates; certificates.reserve(certs.certs_size); for (unsigned int i = 0; i < certs.certs_size; ++i) { @@ -1954,6 +1957,7 @@ hostnameMismatch ); + logger_.log(logmsg::debug_verbose, L"Sending certificate_verification_event"); verification_handler_->send_event<certificate_verification_event>(&tls_layer_, std::move(session_info)); return EAGAIN; @@ -2597,4 +2601,9 @@ return socket_error_ ? socket_error_ : ECONNABORTED; } +void tls_layer_impl::set_unexpected_eof_cb(std::function<bool()> && cb) +{ + unexpected_eof_cb_ = std::move(cb); +} + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libfilezilla-0.34.2/lib/tls_layer_impl.hpp new/libfilezilla-0.35.0/lib/tls_layer_impl.hpp --- old/libfilezilla-0.34.2/lib/tls_layer_impl.hpp 2021-09-14 14:31:27.000000000 +0200 +++ new/libfilezilla-0.35.0/lib/tls_layer_impl.hpp 2021-12-08 16:09:45.000000000 +0100 @@ -99,6 +99,8 @@ void set_min_tls_ver(tls_ver ver); void set_max_tls_ver(tls_ver ver); + void set_unexpected_eof_cb(std::function<bool()> && cb); + private: bool init(); void deinit(); @@ -145,6 +147,8 @@ logger_interface & logger_; + std::function<bool()> unexpected_eof_cb_; + gnutls_session_t session_{}; std::vector<uint8_t> ticket_key_;