Compare commits

...

No commits in common. "c8" and "c8-beta" have entirely different histories.
c8 ... c8-beta

3 changed files with 1 additions and 357 deletions

View File

@ -1,126 +0,0 @@
From 2784cae1d18370acdc13f2bf660c59cd15764d7b Mon Sep 17 00:00:00 2001
From: Michal Ruprich <mruprich@redhat.com>
Date: Thu, 25 Sep 2025 17:28:54 +0200
Subject: [PATCH] Improving TLS communication with a timer
---
src/buffer_ssl.h | 1 +
src/ftpclass.cc | 4 +++-
src/lftp_ssl.cc | 20 +++++++++++++++-----
src/lftp_ssl.h | 2 ++
src/network.cc | 5 +++++
src/network.h | 1 +
6 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/src/buffer_ssl.h b/src/buffer_ssl.h
index 8915066dc..51080b268 100644
--- a/src/buffer_ssl.h
+++ b/src/buffer_ssl.h
@@ -21,6 +21,7 @@
#define BUFFER_SSL_H
#include "buffer.h"
+#include "Timer.h"
#if USE_SSL
#include "lftp_ssl.h"
diff --git a/src/ftpclass.cc b/src/ftpclass.cc
index eb5d0186b..0321a1347 100644
--- a/src/ftpclass.cc
+++ b/src/ftpclass.cc
@@ -4872,8 +4872,10 @@ void Ftp::Reconfig(const char *name)
if(conn && conn->control_sock!=-1)
SetSocketBuffer(conn->control_sock);
- if(conn && conn->data_sock!=-1)
+ if(conn && conn->data_sock!=-1) {
SetSocketBuffer(conn->data_sock);
+ SetTCPNodelay(conn->data_sock);
+ }
if(conn && conn->data_iobuf && rate_limit)
rate_limit->SetBufferSize(conn->data_iobuf,max_buf);
}
diff --git a/src/lftp_ssl.cc b/src/lftp_ssl.cc
index f53edf249..74f3e390e 100644
--- a/src/lftp_ssl.cc
+++ b/src/lftp_ssl.cc
@@ -356,16 +356,26 @@ int lftp_ssl_gnutls::shutdown()
{
int res;
if(handshake_done) {
+ // Certain SSL implementations do not reply us with
+ // close_notify that is why we must not wait for it
+ // indefinetely
+ if (ssl_shutdown_timer && ssl_shutdown_timer->Stopped()) {
+ Log::global->Format(9,"TLS Timer ran out, considering channel closed\n");
+ goodbye_done = true;
+ return DONE;
+ }
res = gnutls_bye(session,GNUTLS_SHUT_RDWR);
if (res == GNUTLS_E_SUCCESS) {
+ if (ssl_shutdown_timer) {
+ ssl_shutdown_timer->Stop();
+ Log::global->Format(9,"Stopping TLS close timer\n");
+ }
goodbye_done = true;
return DONE;
} else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) {
- /* In ideal world we would not need this if, but windows does not
- * send close-notify, so do not wait on server close-notify */
- if (gnutls_record_get_direction(session) == 0) {
- goodbye_done = true;
- return DONE;
+ if (!ssl_shutdown_timer) {
+ ssl_shutdown_timer = new Timer(0, 200);
+ Log::global->Format(9,"Starting TLS close timer\n");
}
return RETRY;
}
diff --git a/src/lftp_ssl.h b/src/lftp_ssl.h
index 9b2a615fb..c8492e45f 100644
--- a/src/lftp_ssl.h
+++ b/src/lftp_ssl.h
@@ -33,6 +33,7 @@
#include "Ref.h"
#include "xstring.h"
+#include "Timer.h"
class lftp_ssl_base
{
@@ -92,6 +93,7 @@ class lftp_ssl_gnutls : public lftp_ssl_base
static Ref<lftp_ssl_gnutls_instance> instance;
gnutls_session_t session;
gnutls_certificate_credentials_t cred;
+ Ref<Timer> ssl_shutdown_timer;
void verify_certificate_chain(const gnutls_datum_t *cert_chain,int cert_chain_length);
int do_handshake();
bool check_fatal(int res);
diff --git a/src/network.cc b/src/network.cc
index cf26089eb..454e6609a 100644
--- a/src/network.cc
+++ b/src/network.cc
@@ -264,6 +264,11 @@ void Networker::SetSocketMaxseg(int sock,int socket_maxseg)
ProtoLog::LogError(1,"setsockopt(TCP_MAXSEG,%d): %s",socket_maxseg,strerror(errno));
#endif
}
+void Networker::SetTCPNodelay(int sock)
+{
+ if(-1==setsockopt(sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)))
+ ProtoLog::LogError(1,"setsockopt(TCP_NODELAY): %s", strerror(errno));
+}
int Networker::SocketCreateUnbound(int af,int type,int proto,const char *hostname)
{
diff --git a/src/network.h b/src/network.h
index 10d99227d..0e84edb99 100644
--- a/src/network.h
+++ b/src/network.h
@@ -132,6 +132,7 @@ class Networker
static int SocketAccept(int fd,sockaddr_u *u,const char *hostname=0);
static void SetSocketBuffer(int sock,int socket_buffer);
static void SetSocketMaxseg(int sock,int socket_maxseg);
+ static void SetTCPNodelay(int sock);
static void SocketBindStd(int s,int af,const char *hostname,int port=0);
static int SocketCreate(int af,int type,int proto,const char *hostname);
static void SocketTuneTCP(int s,const char *hostname);

View File

@ -1,210 +0,0 @@
commit 4156522476192bd9a90aa747cdb8193ffc3a1f24
Author: Tomas Korbar <tkorbar@redhat.com>
Date: Fri Jul 4 11:15:42 2025 +0200
Ensure close-notify is sent on end of TLS connection
diff --git a/src/buffer.cc b/src/buffer.cc
index 9ee6580..e54e20e 100644
--- a/src/buffer.cc
+++ b/src/buffer.cc
@@ -491,23 +491,31 @@ int IOBuffer::Do()
if(Done() || Error())
return STALL;
int res=0;
+ int remaining_size;
switch(mode)
{
case PUT:
- if(Size()==0)
- return STALL;
- res=Put_LL(buffer+buffer_ptr,Size());
- if(res>0)
- {
- RateAdd(res);
- buffer_ptr+=res;
- event_time=now;
- if(eof)
- PutEOF_LL();
- return MOVED;
+ remaining_size = Size();
+ if (remaining_size > 0) {
+ res=Put_LL(buffer+buffer_ptr, remaining_size);
+ if (res <= 0) {
+ return STALL;
+ }
+ RateAdd(res);
+ buffer_ptr+=res;
+ event_time=now;
+ if (eof) {
+ /* We do not have to check for return value of PutEOF_LL here as
+ * We MOVED anyway and find out whether it was a success in next Do */
+ PutEOF_LL();
+ }
+ return MOVED;
+ }
+ if (eof && PutEOF_LL()) {
+ event_time=now;
+ return MOVED;
}
break;
-
case GET:
if(eof)
return STALL;
diff --git a/src/buffer_ssl.cc b/src/buffer_ssl.cc
index 9e701c2..6dd8680 100644
--- a/src/buffer_ssl.cc
+++ b/src/buffer_ssl.cc
@@ -39,10 +39,11 @@ int IOBufferSSL::Do()
// nothing to write, but may need to do handshake
if(!ssl->handshake_done)
{
- if(Put_LL("",0)<0)
- return MOVED;
- if(ssl->handshake_done && eof)
- ssl->shutdown();
+ if(Put_LL("",0)<0)
+ return MOVED;
+ }
+ if(ssl->handshake_done && eof && IOBufferSSL::PutEOF_LL()) {
+ return MOVED;
}
if(ssl->handshake_done && !eof)
return m;
@@ -103,8 +104,17 @@ int IOBufferSSL::Put_LL(const char *buf,int size)
int IOBufferSSL::PutEOF_LL()
{
- if(Size()==0)
- ssl->shutdown();
+ int res;
+ if(Size()==0) {
+ res = ssl->shutdown();
+ if (res == ssl->RETRY) {
+ SetNotReady(ssl->fd,want_mask());
+ return 1;
+ } else if (res == ssl->ERROR) {
+ SetError(ssl->error,ssl->fatal);
+ return -1;
+ }
+ }
return 0;
}
diff --git a/src/buffer_ssl.h b/src/buffer_ssl.h
index d3cf7f0..8915066 100644
--- a/src/buffer_ssl.h
+++ b/src/buffer_ssl.h
@@ -42,7 +42,7 @@ public:
IOBufferSSL(const Ref<lftp_ssl>& s,dir_t m) : IOBuffer(m), ssl(s) {}
~IOBufferSSL();
int Do();
- bool Done() { return IOBuffer::Done() && ssl->handshake_done; }
+ bool Done() { return IOBuffer::Done() && ssl->handshake_done && ssl->goodbye_done; }
};
#endif
diff --git a/src/lftp_ssl.cc b/src/lftp_ssl.cc
index 0a0078a..19870da 100644
--- a/src/lftp_ssl.cc
+++ b/src/lftp_ssl.cc
@@ -45,6 +45,7 @@ lftp_ssl_base::lftp_ssl_base(int fd1,handshake_mode_t m,const char *h)
{
fd=fd1;
handshake_done=false;
+ goodbye_done=false;
handshake_mode=m;
fatal=false;
cert_error=false;
@@ -347,10 +348,30 @@ void lftp_ssl_gnutls::load_keys()
Log::global->Format(9, "Loaded %d CRLs\n", res);
gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
}
-void lftp_ssl_gnutls::shutdown()
+/* Try to shutdown the tls connection, return 1 if needed to call again otherwise 0*/
+int lftp_ssl_gnutls::shutdown()
{
- if(handshake_done)
- gnutls_bye(session,GNUTLS_SHUT_RDWR); // FIXME - E_AGAIN
+ int res;
+ if(handshake_done) {
+ res = gnutls_bye(session,GNUTLS_SHUT_RDWR);
+ if (res == GNUTLS_E_SUCCESS) {
+ goodbye_done = true;
+ return DONE;
+ } else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) {
+ /* In ideal world we would not need this if, but windows does not
+ * send close-notify, so do not wait on server close-notify */
+ if (gnutls_record_get_direction(session) == 0) {
+ goodbye_done = true;
+ return DONE;
+ }
+ return RETRY;
+ }
+ fatal=check_fatal(res);
+ set_error("gnutls_bye",gnutls_strerror(res));
+ return ERROR;
+ }
+ goodbye_done = true;
+ return DONE;
}
lftp_ssl_gnutls::~lftp_ssl_gnutls()
{
@@ -849,10 +870,23 @@ void lftp_ssl_openssl::load_keys()
}
}
}
-void lftp_ssl_openssl::shutdown()
+int lftp_ssl_openssl::shutdown()
{
- if(handshake_done)
- SSL_shutdown(ssl);
+ int res;
+ if(handshake_done) {
+ res = SSL_shutdown(ssl);
+ if (res == 1) {
+ goodbye_done = true;
+ return DONE;
+ } else if (res == 0) {
+ return RETRY;
+ }
+ fatal=check_fatal(res);
+ set_error("SSL_shutdown",strerror());
+ return ERROR;
+ }
+ goodbye_done = true;
+ return DONE;
}
lftp_ssl_openssl::~lftp_ssl_openssl()
{
diff --git a/src/lftp_ssl.h b/src/lftp_ssl.h
index 17a91b0..8e0cc85 100644
--- a/src/lftp_ssl.h
+++ b/src/lftp_ssl.h
@@ -37,6 +37,7 @@ class lftp_ssl_base
{
public:
bool handshake_done;
+ bool goodbye_done;
int fd;
xstring_c hostname;
enum handshake_mode_t { CLIENT, SERVER } handshake_mode;
@@ -107,7 +108,7 @@ public:
bool want_out();
void copy_sid(const lftp_ssl_gnutls *);
void load_keys();
- void shutdown();
+ int shutdown();
};
typedef lftp_ssl_gnutls lftp_ssl;
#elif USE_OPENSSL
@@ -143,7 +144,7 @@ public:
bool want_out();
void copy_sid(const lftp_ssl_openssl *);
void load_keys();
- void shutdown();
+ int shutdown();
};
typedef lftp_ssl_openssl lftp_ssl;
#endif

View File

@ -1,7 +1,7 @@
Summary: A sophisticated file transfer program
Name: lftp
Version: 4.8.4
Release: 7%{?dist}
Release: 3%{?dist}
License: GPLv3+
Group: Applications/Internet
Source0: http://lftp.yar.ru/ftp/%{name}-%{version}.tar.xz
@ -14,8 +14,6 @@ BuildRequires: desktop-file-utils
Patch1: lftp-4.0.9-date_fmt.patch
Patch2: lftp-4.8.4-ssh-prompt.patch
Patch3: lftp-4.8.4-re-newed-cert.patch
Patch4: lftp-4.8.4-tls-close.patch
Patch5: lftp-4.8.4-tls-close-timer.patch
%description
LFTP is a sophisticated ftp/http file transfer program. Like bash, it has job
@ -38,8 +36,6 @@ Utility scripts for use with lftp.
%patch1 -p1 -b .date_fmt
%patch2 -p1 -b .ssh-prompt
%patch3 -p1 -b .re-newed-cert
%patch4 -p1 -b .tls-close
%patch5 -p1 -b .tls-close-timer
#sed -i.rpath -e '/lftp_cv_openssl/s|-R.*lib||' configure
sed -i.norpath -e \
@ -109,22 +105,6 @@ rm -rf $RPM_BUILD_ROOT
%changelog
* Thu Oct 02 2025 Michal Ruprich <mruprich@redhat.com> - 4.8.4-7
- Adding a timeout for TLS close
- Resolves: RHEL-108115 - "cannot seek on data source" in TLS lftp sessions
* Fri Jul 04 2025 Tomas Korbar <tkorbar@redhat.com> - 4.8.4-6
- Do not wait for server close-notify on TLS close
- Resolves: RHEL-99571
* Thu Jun 26 2025 Tomas Korbar <tkorbar@redhat.com> - 4.8.4-5
- Improve fix for close of TLS connection
- Resolves: RHEL-99571
* Tue May 06 2025 Tomas Korbar <tkorbar@redhat.com> - 4.8.4-4
- Ensure proper closing of TLS connection
- Resolves: RHEL-88955
* Mon Jul 24 2023 Michal Ruprich <mruprich@redhat.com> - 4.8.4-3
- Resolves: #2182418 - Connection to site fails with certificate verification error