[Git][debian-proftpd-team/proftpd][master] [skip-ci] Remove obsolete upstream patches.
Hilmar Preuße (@hilmar-guest)
gitlab at salsa.debian.org
Mon Mar 6 19:31:56 GMT 2023
Hilmar Preuße pushed to branch master at Debian ProFTPD Team / proftpd
Commits:
7c4d3644 by Hilmar Preusse at 2023-03-06T20:30:53+01:00
[skip-ci] Remove obsolete upstream patches.
- - - - -
18 changed files:
- − debian/patches/0d932cf9c39071d3c053b811e9ca5f6c9823fe6e.diff
- − debian/patches/2eadd82f392573235432a9cb60266f6472d08884.diff
- − debian/patches/3c73f39f0db6724db597646eb6e476278f76edf5.diff
- − debian/patches/bug_4467
- − debian/patches/cd9036f4ef7a05c107f0ffcb19a018b20267c531.patch
- − debian/patches/pr_1094.diff
- debian/patches/series
- − debian/patches/spelling_error_in_contrib_mod_tls.c
- − debian/patches/spelling_errors
- − debian/patches/upstream_1061
- − debian/patches/upstream_1063
- − debian/patches/upstream_1070
- − debian/patches/upstream_1284
- − debian/patches/upstream_1322
- − debian/patches/upstream_1325
- − debian/patches/upstream_1346
- − debian/patches/upstream_1450.diff
- − debian/patches/upstream_long_AuthGroupFile_lines
Changes:
=====================================
debian/patches/0d932cf9c39071d3c053b811e9ca5f6c9823fe6e.diff deleted
=====================================
@@ -1,32 +0,0 @@
-From 0d932cf9c39071d3c053b811e9ca5f6c9823fe6e Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sat, 14 May 2022 05:45:30 -0700
-Subject: [PATCH] Backport of fix for Issue #1445 to the 1.3.7 branch.
-
----
- contrib/mod_ban.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/contrib/mod_ban.c b/contrib/mod_ban.c
-index 25f4625e32..3d3a088b1c 100644
---- a/contrib/mod_ban.c
-+++ b/contrib/mod_ban.c
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD: mod_ban -- a module implementing ban lists using the Controls API
-- * Copyright (c) 2004-2020 TJ Saunders
-+ * Copyright (c) 2004-2022 TJ Saunders
- *
- * 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
-@@ -3163,8 +3163,8 @@ static void ban_anonrejectpasswords_ev(const void *event_data,
-
- static void ban_badprotocol_ev(const void *event_data, void *user_data) {
-
-- /* For this event, event_data is the client. */
-- conn_t *c = (conn_t *) event_data;
-+ /* For this event, event_data is the bad command in question. */
-+ conn_t *c = session.c;
- const char *ipstr;
-
- /* user_data is a template of the ban event entry. */
=====================================
debian/patches/2eadd82f392573235432a9cb60266f6472d08884.diff deleted
=====================================
@@ -1,140 +0,0 @@
-From 2eadd82f392573235432a9cb60266f6472d08884 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sun, 16 Aug 2020 08:51:10 -0700
-Subject: [PATCH] Issue #1074: Properly handle the `TLSCertificateChainFile`
- directive when SNI is used.
-
----
- contrib/mod_tls.c | 56 ++++++++++++++++++++++++++++++++++++++++-------
- src/main.c | 4 ++++
- 2 files changed, 52 insertions(+), 8 deletions(-)
-
-Index: proftpd/contrib/mod_tls.c
-===================================================================
---- proftpd.orig/contrib/mod_tls.c 2020-09-10 23:48:30.260677792 +0200
-+++ proftpd/contrib/mod_tls.c 2020-09-10 23:48:30.228662195 +0200
-@@ -16172,6 +16172,30 @@
-
- /* SSL setters */
-
-+static int tls_ssl_set_cert_chain(SSL *ssl) {
-+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
-+ !defined(HAVE_LIBRESSL)
-+ int res;
-+
-+ if (tls_ca_chain == NULL) {
-+ return 0;
-+ }
-+
-+ tls_log("adding certs from '%s' to SSL certificate chain", tls_ca_chain);
-+ PRIVS_ROOT
-+ res = SSL_use_certificate_chain_file(ssl, tls_ca_chain);
-+ PRIVS_RELINQUISH
-+
-+ if (res != 1) {
-+ tls_log("unable to read certificate chain '%s': %s", tls_ca_chain,
-+ tls_get_errors());
-+ return -1;
-+ }
-+#endif /* OpenSSL 1.1.x and later */
-+
-+ return 0;
-+}
-+
- static int tls_ssl_set_ciphers(SSL *ssl) {
- SSL_set_cipher_list(ssl, tls_cipher_suite);
- return 0;
-@@ -16689,6 +16713,13 @@
- return -1;
- }
-
-+ /* Inexplicable OpenSSL errors occur if the cert chain is updated after
-+ * calling SSL_set_SSL_CTX, so we do it beforehand.
-+ */
-+ if (tls_ssl_set_cert_chain(ssl) < 0) {
-+ return -1;
-+ }
-+
- #if OPENSSL_VERSION_NUMBER > 0x009080cfL
- /* Note that it is important that we update the SSL with the new SSL_CTX
- * AFTER it has been provisioned. That way, the new/changed certs in the
-@@ -17333,10 +17364,10 @@
-
- static int tls_ctx_set_cert_chain(SSL_CTX *ctx, X509 *dsa_cert, X509 *ec_cert,
- X509 *rsa_cert) {
-+#if defined(SSL_CTRL_CHAIN_CERT)
- BIO *bio;
- X509 *cert;
- unsigned int count = 0;
-- int res;
-
- if (tls_ca_chain == NULL) {
- return 0;
-@@ -17344,14 +17375,20 @@
-
- PRIVS_ROOT
- bio = BIO_new_file(tls_ca_chain, "r");
-- if (bio == NULL) {
-- PRIVS_RELINQUISH
-+ PRIVS_RELINQUISH
-
-+ if (bio == NULL) {
- tls_log("unable to read certificate chain '%s': %s", tls_ca_chain,
- tls_get_errors());
- return 0;
- }
-
-+ if (SSL_CTX_clear_chain_certs(ctx) != 1) {
-+ tls_log("error clearing SSL_CTX chain certs: %s", tls_get_errors());
-+ BIO_free(bio);
-+ return -1;
-+ }
-+
- cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- while (cert != NULL) {
- pr_signals_handle();
-@@ -17383,9 +17420,9 @@
- }
- }
-
-- res = SSL_CTX_add_extra_chain_cert(ctx, cert);
-- if (res != 1) {
-- tls_log("error adding cert to certificate chain: %s", tls_get_errors());
-+ if (SSL_CTX_add1_chain_cert(ctx, cert) != 1) {
-+ tls_log("error adding cert to SSL_CTX certificate chain: %s",
-+ tls_get_errors());
- X509_free(cert);
- break;
- }
-@@ -17394,10 +17431,13 @@
- cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- }
-
-- PRIVS_RELINQUISH
- BIO_free(bio);
-+ ERR_clear_error();
-+
-+ tls_log("added %u certs from '%s' to SSL_CTX certificate chain", count,
-+ tls_ca_chain);
-+#endif /* SSL_CTRL_CHAIN_CERT */
-
-- tls_log("added %u certs from '%s' to certificate chain", count, tls_ca_chain);
- return 0;
- }
-
-Index: proftpd/src/main.c
-===================================================================
---- proftpd.orig/src/main.c 2020-09-10 23:48:30.260677792 +0200
-+++ proftpd/src/main.c 2020-09-10 23:48:30.244669994 +0200
-@@ -2102,7 +2102,11 @@
- # ifdef PR_USE_OPENSSL_FIPS
- printf(" + OpenSSL support (%s, FIPS enabled)\n", OPENSSL_VERSION_TEXT);
- # else
-+# ifdef LIBRESSL_VERSION_NUMBER
-+ printf(" + OpenSSL support (%s, LibreSSL)\n", OPENSSL_VERSION_TEXT);
-+# else
- printf(" + OpenSSL support (%s)\n", OPENSSL_VERSION_TEXT);
-+# endif /* Have LibreSSL */
- # endif /* PR_USE_OPENSSL_FIPS */
- #else
- printf("%s", " - OpenSSL support\n");
=====================================
debian/patches/3c73f39f0db6724db597646eb6e476278f76edf5.diff deleted
=====================================
@@ -1,163 +0,0 @@
-From 3c73f39f0db6724db597646eb6e476278f76edf5 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sat, 8 Aug 2020 09:18:58 -0700
-Subject: [PATCH] Bug #4405: Allocate the algorithm name strings for ciphers,
- MACs out of pools other than the KEX pool, as the strings have different
- lifetimes.
-
----
- contrib/mod_sftp/cipher.c | 35 +++++++++++++++++++++++++++++------
- contrib/mod_sftp/mac.c | 37 ++++++++++++++++++++++++++++++-------
- 2 files changed, 59 insertions(+), 13 deletions(-)
-
-diff --git a/contrib/mod_sftp/cipher.c b/contrib/mod_sftp/cipher.c
-index c3b51efe2..77c79e067 100644
---- a/contrib/mod_sftp/cipher.c
-+++ b/contrib/mod_sftp/cipher.c
-@@ -32,6 +32,7 @@
- #include "interop.h"
-
- struct sftp_cipher {
-+ pool *pool;
- const char *algo;
- const EVP_CIPHER *cipher;
-
-@@ -51,14 +52,14 @@ struct sftp_cipher {
- */
-
- static struct sftp_cipher read_ciphers[2] = {
-- { NULL, NULL, NULL, 0, NULL, 0, 0 },
-- { NULL, NULL, NULL, 0, NULL, 0, 0 }
-+ { NULL, NULL, NULL, NULL, 0, NULL, 0, 0 },
-+ { NULL, NULL, NULL, NULL, 0, NULL, 0, 0 }
- };
- static EVP_CIPHER_CTX *read_ctxs[2];
-
- static struct sftp_cipher write_ciphers[2] = {
-- { NULL, NULL, NULL, 0, NULL, 0, 0 },
-- { NULL, NULL, NULL, 0, NULL, 0, 0 }
-+ { NULL, NULL, NULL, NULL, 0, NULL, 0, 0 },
-+ { NULL, NULL, NULL, NULL, 0, NULL, 0, 0 }
- };
- static EVP_CIPHER_CTX *write_ctxs[2];
-
-@@ -387,7 +388,18 @@ int sftp_cipher_set_read_algo(const char *algo) {
- (unsigned long) discard_len);
- }
-
-- read_ciphers[idx].algo = algo;
-+ /* Note that we use a new pool, each time the algorithm is set (which
-+ * happens during key exchange) to prevent undue memory growth for
-+ * long-lived sessions with many rekeys.
-+ */
-+ if (read_ciphers[idx].pool != NULL) {
-+ destroy_pool(read_ciphers[idx].pool);
-+ }
-+
-+ read_ciphers[idx].pool = make_sub_pool(sftp_pool);
-+ pr_pool_tag(read_ciphers[idx].pool, "SFTP cipher read pool");
-+ read_ciphers[idx].algo = pstrdup(read_ciphers[idx].pool, algo);
-+
- read_ciphers[idx].key_len = (uint32_t) key_len;
- read_ciphers[idx].discard_len = discard_len;
- return 0;
-@@ -586,7 +598,18 @@ int sftp_cipher_set_write_algo(const char *algo) {
- (unsigned long) discard_len);
- }
-
-- write_ciphers[idx].algo = algo;
-+ /* Note that we use a new pool, each time the algorithm is set (which
-+ * happens during key exchange) to prevent undue memory growth for
-+ * long-lived sessions with many rekeys.
-+ */
-+ if (write_ciphers[idx].pool != NULL) {
-+ destroy_pool(write_ciphers[idx].pool);
-+ }
-+
-+ write_ciphers[idx].pool = make_sub_pool(sftp_pool);
-+ pr_pool_tag(write_ciphers[idx].pool, "SFTP cipher write pool");
-+ write_ciphers[idx].algo = pstrdup(write_ciphers[idx].pool, algo);
-+
- write_ciphers[idx].key_len = (uint32_t) key_len;
- write_ciphers[idx].discard_len = discard_len;
- return 0;
-diff --git a/contrib/mod_sftp/mac.c b/contrib/mod_sftp/mac.c
-index d78e1e775..d5e1ef505 100644
---- a/contrib/mod_sftp/mac.c
-+++ b/contrib/mod_sftp/mac.c
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - mod_sftp MACs
-- * Copyright (c) 2008-2017 TJ Saunders
-+ * Copyright (c) 2008-2020 TJ Saunders
- *
- * 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
-@@ -34,6 +34,7 @@
- #include "umac.h"
-
- struct sftp_mac {
-+ pool *pool;
- const char *algo;
- int algo_type;
-
-@@ -64,15 +65,15 @@ struct sftp_mac {
- */
-
- static struct sftp_mac read_macs[] = {
-- { NULL, 0, NULL, NULL, 0 },
-- { NULL, 0, NULL, NULL, 0 }
-+ { NULL, NULL, 0, NULL, NULL, 0, 0, 0 },
-+ { NULL, NULL, 0, NULL, NULL, 0, 0, 0 }
- };
- static HMAC_CTX *hmac_read_ctxs[2];
- static struct umac_ctx *umac_read_ctxs[2];
-
- static struct sftp_mac write_macs[] = {
-- { NULL, 0, NULL, NULL, 0 },
-- { NULL, 0, NULL, NULL, 0 }
-+ { NULL, NULL, 0, NULL, NULL, 0, 0, 0 },
-+ { NULL, NULL, 0, NULL, NULL, 0, 0, 0 }
- };
- static HMAC_CTX *hmac_write_ctxs[2];
- static struct umac_ctx *umac_write_ctxs[2];
-@@ -687,7 +688,18 @@ int sftp_mac_set_read_algo(const char *algo) {
- return -1;
- }
-
-- read_macs[idx].algo = algo;
-+ /* Note that we use a new pool, each time the algorithm is set (which
-+ * happens during key exchange) to prevent undue memory growth for
-+ * long-lived sessions with many rekeys.
-+ */
-+ if (read_macs[idx].pool != NULL) {
-+ destroy_pool(read_macs[idx].pool);
-+ }
-+
-+ read_macs[idx].pool = make_sub_pool(sftp_pool);
-+ pr_pool_tag(read_macs[idx].pool, "SFTP MAC read pool");
-+ read_macs[idx].algo = pstrdup(read_macs[idx].pool, algo);
-+
- if (strncmp(read_macs[idx].algo, "umac-64 at openssh.com", 12) == 0) {
- read_macs[idx].algo_type = SFTP_MAC_ALGO_TYPE_UMAC64;
- umac_read_ctxs[idx] = umac_alloc();
-@@ -820,7 +832,18 @@ int sftp_mac_set_write_algo(const char *algo) {
- return -1;
- }
-
-- write_macs[idx].algo = algo;
-+ /* Note that we use a new pool, each time the algorithm is set (which
-+ * happens during key exchange) to prevent undue memory growth for
-+ * long-lived sessions with many rekeys.
-+ */
-+ if (write_macs[idx].pool != NULL) {
-+ destroy_pool(write_macs[idx].pool);
-+ }
-+
-+ write_macs[idx].pool = make_sub_pool(sftp_pool);
-+ pr_pool_tag(write_macs[idx].pool, "SFTP MAC write pool");
-+ write_macs[idx].algo = pstrdup(write_macs[idx].pool, algo);
-+
- if (strncmp(write_macs[idx].algo, "umac-64 at openssh.com", 12) == 0) {
- write_macs[idx].algo_type = SFTP_MAC_ALGO_TYPE_UMAC64;
- umac_write_ctxs[idx] = umac_alloc();
=====================================
debian/patches/bug_4467 deleted
=====================================
@@ -1,34 +0,0 @@
-From ed101eed833bdb53d6bcecdb4448040bd4ce9b5f Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sat, 29 Jan 2022 11:20:14 -0800
-Subject: [PATCH] Backport of fix for Bug#4467 to the 1.3.7 branch.
-
----
- NEWS | 2 ++
- modules/mod_xfer.c | 5 ++---
- 2 files changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/modules/mod_xfer.c b/modules/mod_xfer.c
-index 9348118c00..b7fcf74e94 100644
---- a/modules/mod_xfer.c
-+++ b/modules/mod_xfer.c
-@@ -2,7 +2,7 @@
- * ProFTPD - FTP server daemon
- * Copyright (c) 1997, 1998 Public Flood Software
- * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver at tos.net>
-- * Copyright (c) 2001-2020 The ProFTPD Project team
-+ * Copyright (c) 2001-2022 The ProFTPD Project team
- *
- * 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
-@@ -1014,9 +1014,8 @@ static void stor_abort(pool *p) {
- }
- }
- }
-- }
-
-- if (session.xfer.path != NULL) {
-+ } else if (session.xfer.path != NULL) {
- if (delete_stores != NULL &&
- *delete_stores == TRUE) {
- pr_log_debug(DEBUG5, "removing aborted file '%s'", session.xfer.path);
=====================================
debian/patches/cd9036f4ef7a05c107f0ffcb19a018b20267c531.patch deleted
=====================================
@@ -1,24 +0,0 @@
-From cd9036f4ef7a05c107f0ffcb19a018b20267c531 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sat, 22 Feb 2020 09:40:32 -0800
-Subject: [PATCH] Issue #903: We want to remove the data transfer command pool,
- but we _do_ want some memory pool, lest we regress the %{transfer-status}
- LogFormat functionality.
-
----
- src/data.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/data.c b/src/data.c
-index 6ef6d420e..e7b03e231 100644
---- a/src/data.c
-+++ b/src/data.c
-@@ -897,7 +897,7 @@ void pr_data_abort(int err, int quiet) {
- /* Forcibly clear the data-transfer instigating command pool from the
- * Response API.
- */
-- pr_response_set_pool(NULL);
-+ pr_response_set_pool(session.pool);
- }
-
- if (true_abort) {
=====================================
debian/patches/pr_1094.diff deleted
=====================================
@@ -1,57 +0,0 @@
-From dfd5abe7b47648311c8bca4e9a3f6e90582b5143 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sun, 30 Aug 2020 09:07:07 -0700
-Subject: [PATCH] Issue #1079: Improve prxs detection of `configure` scripts
- for modules.
-
----
- src/prxs.in | 15 ++++++++++-----
- 1 file changed, 10 insertions(+), 5 deletions(-)
-
-Index: proftpd/src/prxs.in
-===================================================================
---- proftpd.orig/src/prxs.in 2020-09-06 19:53:55.818043780 +0200
-+++ proftpd/src/prxs.in 2020-09-06 19:53:55.802035781 +0200
-@@ -1,7 +1,7 @@
- #!/usr/bin/perl
-
- # ---------------------------------------------------------------------------
--# Copyright (C) 2008-2012 TJ Saunders <tj at castaglia.org>
-+# Copyright (C) 2008-2020 TJ Saunders <tj at castaglia.org>
- #
- # 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,8 +16,6 @@
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
--#
--# $Id: prxs.in,v 1.10 2012-09-19 00:11:39 castaglia Exp $
- # ---------------------------------------------------------------------------
-
- use strict;
-@@ -101,7 +99,11 @@
-
- if ($file =~ /\/?mod_[^\/]+\.c$/) {
- $configure_script = $file;
-- $configure_script =~ s/\/?mod_[^\/]+\.c$/\/configure/;
-+ $configure_script =~ s/(\/?)mod_[^\/]+\.c$/\1configure/;
-+
-+ if ($configure_script !~ /^\//) {
-+ $configure_script = './' . $configure_script;
-+ }
- }
-
- my $obj = $file;
-@@ -123,7 +125,10 @@
- # Check for any configure script for this module. If present, error out
- # for now.
- if (-f $configure_script) {
-- print STDERR "Cannot compile $mod_name using prxs; use $configure_script instead\n";
-+ print STDERR "Cannot compile $mod_name using prxs; use existing $configure_script script instead:\n\n";
-+ print STDERR " $configure_script\n";
-+ print STDERR " make\n";
-+ print STDERR " make install\n";
- exit 1;
- }
- }
=====================================
debian/patches/series
=====================================
@@ -7,23 +7,6 @@ ftpstats
#mod_cap
odbc
#reproducible_build
-#spelling_errors
#wrong-path-for-interpreter_perl.diff
-#cd9036f4ef7a05c107f0ffcb19a018b20267c531.patch
#proftpd-mysql-password-backend.diff
-#upstream_1063
-#upstream_1070
-#upstream_1061
-#3c73f39f0db6724db597646eb6e476278f76edf5.diff
-#pr_1094.diff
-#2eadd82f392573235432a9cb60266f6472d08884.diff
-#upstream_1284
-#spelling_error_in_contrib_mod_tls.c
-#upstream_1322
-#upstream_1325
-#upstream_1346
-#upstream_long_AuthGroupFile_lines
-#bug_4467
-#0d932cf9c39071d3c053b811e9ca5f6c9823fe6e.diff
-#upstream_1450.diff
upstream_1592.diff
=====================================
debian/patches/spelling_error_in_contrib_mod_tls.c deleted
=====================================
@@ -1,15 +0,0 @@
-Author: Hilmar Preusse <hille42 at web.de>
-Last-Update: 20220111
-Forwarded: https://github.com/proftpd/proftpd/issues/1375
-
---- proftpd.orig/contrib/mod_tls.c
-+++ proftpd/contrib/mod_tls.c
-@@ -16592,7 +16592,7 @@
- data[datalen] = '\0';
-
- } else {
-- data = "UKNOWN";
-+ data = "UNKNOWN";
- }
-
- return data;
=====================================
debian/patches/spelling_errors deleted
=====================================
@@ -1,107 +0,0 @@
-Description: Fixed some spelling errors in sources
-Author: Francesco Paolo Lovergine <frankie at debian.org>
-Last-Update: 2017-01-09
-Forwarded: https://github.com/proftpd/proftpd/pull/666
-
---- proftpd-dfsg-1.3.6c.orig/contrib/mod_sftp/date.c
-+++ proftpd-dfsg-1.3.6c/contrib/mod_sftp/date.c
-@@ -124,7 +124,7 @@
- case '?':
- /* Ignore unsupported options */
- (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-- "ingoring supported date(1) option '%c'", (char) optopt);
-+ "ignoring supported date(1) option '%c'", (char) optopt);
- break;
- }
- }
---- proftpd-dfsg-1.3.6c.orig/contrib/mod_sftp/keys.c
-+++ proftpd-dfsg-1.3.6c/contrib/mod_sftp/keys.c
-@@ -1121,7 +1121,7 @@
-
- if (sftp_keys_validate_ecdsa_params(curve, point) < 0) {
- (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-- "erorr validating EC public key: %s", strerror(errno));
-+ "error validating EC public key: %s", strerror(errno));
- EC_POINT_free(point);
- EC_KEY_free(ec);
- return NULL;
-@@ -2101,7 +2101,7 @@
- if (sftp_keys_validate_ecdsa_params(EC_KEY_get0_group(ec),
- EC_KEY_get0_public_key(ec)) < 0) {
- (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-- "erorr validating EC public key: %s", strerror(errno));
-+ "error validating EC public key: %s", strerror(errno));
- EC_KEY_free(ec);
- EVP_PKEY_free(pkey);
- return -1;
-@@ -2109,7 +2109,7 @@
-
- if (validate_ecdsa_private_key(ec)) {
- (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-- "erorr validating EC private key: %s", strerror(errno));
-+ "error validating EC private key: %s", strerror(errno));
- EC_KEY_free(ec);
- EVP_PKEY_free(pkey);
- return -1;
---- proftpd-dfsg-1.3.6c.orig/contrib/mod_tls.c
-+++ proftpd-dfsg-1.3.6c/contrib/mod_tls.c
-@@ -2172,7 +2172,7 @@
- if (idx < 0) {
- pr_trace_msg(trace_channel, 12,
- "unable to check certificate CommonName against '%s': "
-- "no CommoName atribute found", name);
-+ "no CommoName attribute found", name);
- return 0;
- }
-
-@@ -2180,7 +2180,7 @@
- if (cn_entry == NULL) {
- pr_trace_msg(trace_channel, 12,
- "unable to check certificate CommonName against '%s': "
-- "error obtaining CommoName atribute found: %s", name, tls_get_errors());
-+ "error obtaining CommoName attribute found: %s", name, tls_get_errors());
- return 0;
- }
-
-@@ -2189,7 +2189,7 @@
- if (cn_asn1 == NULL) {
- pr_trace_msg(trace_channel, 12,
- "unable to check certificate CommonName against '%s': "
-- "error converting CommoName atribute to ASN.1: %s", name,
-+ "error converting CommoName attribute to ASN.1: %s", name,
- tls_get_errors());
- return 0;
- }
---- proftpd-dfsg-1.3.6c.orig/doc/utils/ftpwho.html
-+++ proftpd-dfsg-1.3.6c/doc/utils/ftpwho.html
-@@ -14,7 +14,7 @@
-
- The <B>ftpwho</B> command shows process information for all active proftpd
- connections, and a count of all connected users off of each server. Proftpd
--sesssions spawned from inetd are counted seperately from those created by a
-+sessions spawned from inetd are counted seperately from those created by a
- master proftpd <I>standalone</I> server.
-
- <H2>OPTIONS</H2>
---- proftpd-dfsg-1.3.6c.orig/utils/ftpwho.1.in
-+++ proftpd-dfsg-1.3.6c/utils/ftpwho.1.in
-@@ -10,7 +10,7 @@
- The
- .BI ftpwho
- command shows process information for all active proftpd connections,
--and a count of all connected users off of each server. Proftpd sesssions
-+and a count of all connected users off of each server. Proftpd sessions
- spawned from inetd are counted separately from those created by a
- master proftpd
- .I standalone
---- proftpd-dfsg-1.3.6c.orig/contrib/mod_ldap.c
-+++ proftpd-dfsg-1.3.6c/contrib/mod_ldap.c
-@@ -930,7 +930,7 @@
- cached_quota->nelts = 1;
-
- (void) pr_log_writefile(ldap_logfd, MOD_LDAP_VERSION,
-- "parsing ftpQuota atribute value '%s'", str);
-+ "parsing ftpQuota attribute value '%s'", str);
-
- while ((token = strsep(&str, ","))) {
- pr_signals_handle();
=====================================
debian/patches/upstream_1061 deleted
=====================================
@@ -1,50 +0,0 @@
-From 1117b003fa25c2e29e3a679ba3a1a3b92b5a4587 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sat, 25 Jul 2020 16:51:26 -0700
-Subject: [PATCH] Issue #1061: While investigating some reported issues with
- Ed25519 keys and mod_sftp, I reproduced one segfault when verifying such keys
- during publickey authentication.
-
----
- contrib/mod_sftp/kex.c | 2 +-
- contrib/mod_sftp/keys.c | 7 +++++--
- 2 files changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/contrib/mod_sftp/kex.c b/contrib/mod_sftp/kex.c
-index 17e853fe2..59c76f3c0 100644
---- a/contrib/mod_sftp/kex.c
-+++ b/contrib/mod_sftp/kex.c
-@@ -2869,7 +2869,7 @@ static int write_ext_info_server_sig_algs(struct ssh2_packet *pkt, char **buf,
- char *sig_algs = "";
-
- #if defined(PR_USE_SODIUM)
-- sig_algs = pstrcat(pkt->pool, sig_algs, *sig_algs ? "," : "", "ssh-ec25519",
-+ sig_algs = pstrcat(pkt->pool, sig_algs, *sig_algs ? "," : "", "ssh-ed25519",
- NULL);
- #endif /* PR_USE_SODIUM */
-
-diff --git a/contrib/mod_sftp/keys.c b/contrib/mod_sftp/keys.c
-index b2e03f722..c94a3b201 100644
---- a/contrib/mod_sftp/keys.c
-+++ b/contrib/mod_sftp/keys.c
-@@ -4453,7 +4453,7 @@ const unsigned char *sftp_keys_sign_data(pool *p,
-
- int sftp_keys_verify_pubkey_type(pool *p, unsigned char *pubkey_data,
- uint32_t pubkey_len, enum sftp_key_type_e pubkey_type) {
-- EVP_PKEY *pkey;
-+ EVP_PKEY *pkey = NULL;
- int res = FALSE;
- uint32_t len;
-
-@@ -4542,7 +4542,10 @@ int sftp_keys_verify_pubkey_type(pool *p, unsigned char *pubkey_data,
- break;
- }
-
-- EVP_PKEY_free(pkey);
-+ if (pkey != NULL) {
-+ EVP_PKEY_free(pkey);
-+ }
-+
- return res;
- }
-
=====================================
debian/patches/upstream_1063 deleted
=====================================
@@ -1,45 +0,0 @@
-From adf43dd4ddaab0332e74abc86bbcef9cf27ee54a Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sat, 25 Jul 2020 11:10:07 -0700
-Subject: [PATCH] Issue #1063: Avoid segfaults for TLSv1.3 data transfers in
- our session tickey callback by checking the status before using SSL_SESSION
- pointer.
-
----
- contrib/mod_tls.c | 21 +++++++++++++++------
- 1 file changed, 15 insertions(+), 6 deletions(-)
-
-diff --git a/contrib/mod_tls.c b/contrib/mod_tls.c
-index c4e3a2f18..3cab789c9 100644
---- a/contrib/mod_tls.c
-+++ b/contrib/mod_tls.c
-@@ -6833,14 +6833,23 @@ static SSL_TICKET_RETURN tls_decrypt_session_ticket_data_upload_cb(SSL *ssl,
- SSL_SESSION *ssl_session, const unsigned char *key_name, size_t key_namelen,
- SSL_TICKET_STATUS status, void *user_data) {
- SSL_TICKET_RETURN res;
-- int ssl_version, renew_tickets = TRUE;
-+ int renew_tickets = TRUE;
-
-- ssl_version = SSL_SESSION_get_protocol_version(ssl_session);
-+ /* Avoid using the given SSL_SESSION pointer unless the status indicates that
-+ * that pointer is valid (Issue #1063).
-+ */
-+
-+ if (status != SSL_TICKET_EMPTY &&
-+ status != SSL_TICKET_NO_DECRYPT) {
-+ int ssl_version;
-+
-+ ssl_version = SSL_SESSION_get_protocol_version(ssl_session);
- # if defined(TLS1_3_VERSION)
-- if (ssl_version == TLS1_3_VERSION) {
-- pr_trace_msg(trace_channel, 29,
-- "suppressing renewal of TLSv1.3 tickets for data transfers");
-- renew_tickets = FALSE;
-+ if (ssl_version == TLS1_3_VERSION) {
-+ pr_trace_msg(trace_channel, 29,
-+ "suppressing renewal of TLSv1.3 tickets for data transfers");
-+ renew_tickets = FALSE;
-+ }
- }
- # endif /* TLS1_3_VERSION */
-
=====================================
debian/patches/upstream_1070 deleted
=====================================
@@ -1,705 +0,0 @@
-From 3fe77bd7088af1e0f5822e12555a4f4221301dbe Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sun, 26 Jul 2020 13:38:42 -0700
-Subject: [PATCH] Issue #1070: Implement support for Redis 6.x AUTH semantics.
-
----
- include/redis.h | 10 ++-
- src/redis.c | 128 +++++++++++++++++++++++++--
- tests/api/env.c | 8 +-
- tests/api/redis.c | 210 ++++++++++++++++++++++++++++++++++++++-------
- tests/api/sets.c | 24 +++---
- tests/api/str.c | 8 +-
- tests/api/timers.c | 2 +-
- 7 files changed, 334 insertions(+), 56 deletions(-)
-
-diff --git a/include/redis.h b/include/redis.h
-index 27f71e454..eae519bfb 100644
---- a/include/redis.h
-+++ b/include/redis.h
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - FTP server daemon
-- * Copyright (c) 2017 The ProFTPD Project team
-+ * Copyright (c) 2017-2020 The ProFTPD Project team
- *
- * 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
-@@ -55,8 +55,14 @@ int pr_redis_conn_destroy(pr_redis_t *redis);
- int pr_redis_conn_set_namespace(pr_redis_t *redis, module *m,
- const void *prefix, size_t prefixsz);
-
-+/* Redis server version. */
-+int pr_redis_conn_get_version(pr_redis_t *redis, unsigned int *major_version,
-+ unsigned int *minor_version, unsigned int *patch_version);
-+
- /* Authenticate to a password-protected Redis server. */
- int pr_redis_auth(pr_redis_t *redis, const char *password);
-+int pr_redis_auth2(pr_redis_t *redis, const char *username,
-+ const char *password);
-
- /* Select the database used by the Redis server. */
- int pr_redis_select(pr_redis_t *redis, const char *db_idx);
-@@ -304,6 +310,8 @@ int pr_redis_sentinel_get_masters(pool *p, pr_redis_t *redis,
- /* For internal use only */
- int redis_set_server(const char *server, int port, unsigned long flags,
- const char *password, const char *db_idx);
-+int redis_set_server2(const char *server, int port, unsigned long flags,
-+ const char *username, const char *password, const char *db_idx);
- int redis_set_sentinels(array_header *sentinels, const char *name);
- int redis_set_timeouts(unsigned long connect_millis, unsigned long io_millis);
-
-diff --git a/src/redis.c b/src/redis.c
-index 5bd99623f..cca05bd3f 100644
---- a/src/redis.c
-+++ b/src/redis.c
-@@ -49,6 +49,11 @@ struct redis_rec {
- */
- unsigned int refcount;
-
-+ /* Redis server version. */
-+ unsigned int major_version;
-+ unsigned int minor_version;
-+ unsigned int patch_version;
-+
- /* Table mapping modules to their namespaces */
- pr_table_t *namespace_tab;
- };
-@@ -59,6 +64,7 @@ static const char *redis_sentinel_master = NULL;
- static const char *redis_server = NULL;
- static int redis_port = -1;
- static unsigned long redis_flags = 0UL;
-+static const char *redis_username = NULL;
- static const char *redis_password = NULL;
- static const char *redis_db_idx = NULL;
-
-@@ -69,6 +75,8 @@ static unsigned long redis_io_millis = 500;
-
- static const char *trace_channel = "redis";
-
-+static const char *get_reply_type(int reply_type);
-+
- static void millis2timeval(struct timeval *tv, unsigned long millis) {
- tv->tv_sec = (millis / 1000);
- tv->tv_usec = (millis - (tv->tv_sec * 1000)) * 1000;
-@@ -194,6 +202,48 @@ static int ping_server(pr_redis_t *redis) {
- return 0;
- }
-
-+static void parse_redis_version(pr_redis_t *redis, redisReply *info) {
-+ pool *tmp_pool;
-+ unsigned int major, minor, patch;
-+ char *text, *version_text;
-+
-+ if (info->type != REDIS_REPLY_STRING) {
-+ pr_trace_msg(trace_channel, 1, "expected STRING reply for INFO, got %s",
-+ get_reply_type(info->type));
-+ return;
-+ }
-+
-+ tmp_pool = make_sub_pool(redis->pool);
-+ pr_pool_tag(tmp_pool, "Redis version parsing pool");
-+ text = pstrndup(tmp_pool, info->str, info->len);
-+
-+ /* Scan the entire INFO string for "redis_version:N.N.N". */
-+
-+ version_text = strstr(text, "redis_version:");
-+ if (version_text == NULL) {
-+ pr_trace_msg(trace_channel, 1, "no `redis_version` found in INFO reply");
-+ destroy_pool(tmp_pool);
-+ return;
-+ }
-+
-+ if (sscanf(version_text, "redis_version:%u.%u.%u", &major, &minor,
-+ &patch) == 3) {
-+ redis->major_version = major;
-+ redis->minor_version = minor;
-+ redis->patch_version = patch;
-+
-+ pr_trace_msg(trace_channel, 9,
-+ "parsed Redis version %u (major), %u (minor), %u (patch) out of INFO",
-+ redis->major_version, redis->minor_version, redis->patch_version);
-+
-+ } else {
-+ pr_trace_msg(trace_channel, 1, "failed to scan Redis version '%s'",
-+ version_text);
-+ }
-+
-+ destroy_pool(tmp_pool);
-+}
-+
- static int stat_server(pr_redis_t *redis, const char *section) {
- const char *cmd;
- redisReply *reply;
-@@ -214,6 +264,18 @@ static int stat_server(pr_redis_t *redis, const char *section) {
- (unsigned long) reply->len);
- }
-
-+ if (redis->major_version == 0 &&
-+ (strcmp(section, "server") == 0 || strcmp(section, "") == 0)) {
-+ /* We are particularly interested in the Redis server version; we key
-+ * off of this version to detect when to change our command semantics,
-+ * such as for AUTH.
-+ *
-+ * Thus we parse the server version out of the "server" info, unless
-+ * the version is already known.
-+ */
-+ parse_redis_version(redis, reply);
-+ }
-+
- freeReplyObject(reply);
- return 0;
- }
-@@ -508,7 +570,13 @@ pr_redis_t *pr_redis_conn_new(pool *p, module *m, unsigned long flags) {
- }
-
- if (redis_password != NULL) {
-- res = pr_redis_auth(redis, redis_password);
-+ if (redis_username != NULL) {
-+ res = pr_redis_auth2(redis, redis_username, redis_password);
-+
-+ } else {
-+ res = pr_redis_auth(redis, redis_password);
-+ }
-+
- if (res < 0) {
- xerrno = errno;
-
-@@ -682,6 +750,36 @@ int pr_redis_conn_set_namespace(pr_redis_t *redis, module *m,
- return 0;
- }
-
-+int pr_redis_conn_get_version(pr_redis_t *redis, unsigned int *major_version,
-+ unsigned int *minor_version, unsigned int *patch_version) {
-+
-+ if (redis == NULL) {
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
-+ if (major_version == NULL &&
-+ minor_version == NULL &&
-+ patch_version == NULL) {
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
-+ if (major_version != NULL) {
-+ *major_version = redis->major_version;
-+ }
-+
-+ if (minor_version != NULL) {
-+ *minor_version = redis->minor_version;
-+ }
-+
-+ if (patch_version != NULL) {
-+ *patch_version = redis->patch_version;
-+ }
-+
-+ return 0;
-+}
-+
- int pr_redis_add(pr_redis_t *redis, module *m, const char *key, void *value,
- size_t valuesz, time_t expires) {
- int res;
-@@ -2003,12 +2101,14 @@ int pr_redis_command(pr_redis_t *redis, const array_header *args,
- return 0;
- }
-
--int pr_redis_auth(pr_redis_t *redis, const char *password) {
-+int pr_redis_auth2(pr_redis_t *redis, const char *username,
-+ const char *password) {
- const char *cmd;
- pool *tmp_pool;
- redisReply *reply;
-
- if (redis == NULL ||
-+ username == NULL ||
- password == NULL) {
- errno = EINVAL;
- return -1;
-@@ -2019,7 +2119,15 @@ int pr_redis_auth(pr_redis_t *redis, const char *password) {
-
- cmd = "AUTH";
- pr_trace_msg(trace_channel, 7, "sending command: %s", cmd);
-- reply = redisCommand(redis->ctx, "%s %s", cmd, password);
-+
-+ /* Redis 6.x changed the AUTH semantics, now requiring a username. */
-+ if (redis->major_version >= 6) {
-+ reply = redisCommand(redis->ctx, "%s %s %s", cmd, username, password);
-+
-+ } else {
-+ reply = redisCommand(redis->ctx, "%s %s", cmd, password);
-+ }
-+
- reply = handle_reply(redis, cmd, reply);
- if (reply == NULL) {
- pr_trace_msg(trace_channel, 2,
-@@ -2053,6 +2161,10 @@ int pr_redis_auth(pr_redis_t *redis, const char *password) {
- return 0;
- }
-
-+int pr_redis_auth(pr_redis_t *redis, const char *password) {
-+ return pr_redis_auth2(redis, "default", password);
-+}
-+
- int pr_redis_select(pr_redis_t *redis, const char *db_idx) {
- const char *cmd;
- pool *tmp_pool;
-@@ -5632,8 +5744,8 @@ int pr_redis_sentinel_get_masters(pool *p, pr_redis_t *redis,
- return res;
- }
-
--int redis_set_server(const char *server, int port, unsigned long flags,
-- const char *password, const char *db_idx) {
-+int redis_set_server2(const char *server, int port, unsigned long flags,
-+ const char *username, const char *password, const char *db_idx) {
-
- if (server == NULL) {
- /* By using a port of -2 specifically, we can use this function to
-@@ -5649,12 +5761,18 @@ int redis_set_server(const char *server, int port, unsigned long flags,
- redis_server = server;
- redis_port = port;
- redis_flags = flags;
-+ redis_username = username;
- redis_password = password;
- redis_db_idx = db_idx;
-
- return 0;
- }
-
-+int redis_set_server(const char *server, int port, unsigned long flags,
-+ const char *password, const char *db_idx) {
-+ return redis_set_server2(server, port, flags, "default", password, db_idx);
-+}
-+
- int redis_set_sentinels(array_header *sentinels, const char *name) {
-
- if (sentinels != NULL &&
-diff --git a/tests/api/env.c b/tests/api/env.c
-index ad126385e..b839f2ea4 100644
---- a/tests/api/env.c
-+++ b/tests/api/env.c
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - FTP server testsuite
-- * Copyright (c) 2008-2015 The ProFTPD Project team
-+ * Copyright (c) 2008-2020 The ProFTPD Project team
- *
- * 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
-@@ -61,11 +61,13 @@ START_TEST (env_get_test) {
- pr_env_unset(p, key);
-
- res = pr_env_get(p, key);
-- fail_unless(res == NULL);
-+ fail_unless(res == NULL, "Unexpectedly found value '%s' for key '%s'",
-+ res, key);
-
- /* XXX PATH should always be set in the environment, right? */
- res = pr_env_get(p, "PATH");
-- fail_unless(res != NULL);
-+ fail_unless(res != NULL, "Failed to get value for 'PATH': %s",
-+ strerror(errno));
-
- #else
- res = pr_env_get(p, key);
-diff --git a/tests/api/redis.c b/tests/api/redis.c
-index 7e95893ee..e44d5a4bd 100644
---- a/tests/api/redis.c
-+++ b/tests/api/redis.c
-@@ -222,11 +222,44 @@ START_TEST (redis_conn_set_namespace_test) {
- }
- END_TEST
-
-+START_TEST (redis_conn_get_version_test) {
-+ int res;
-+ pr_redis_t *redis;
-+ unsigned int major = 0, minor = 0, patch = 0;
-+
-+ mark_point();
-+ res = pr_redis_conn_get_version(NULL, NULL, NULL, NULL);
-+ fail_unless(res < 0, "Failed to handle null redis");
-+ fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
-+ strerror(errno), errno);
-+
-+ mark_point();
-+ redis = pr_redis_conn_new(p, NULL, 0);
-+ fail_unless(redis != NULL, "Failed to open connection to Redis: %s",
-+ strerror(errno));
-+
-+ mark_point();
-+ res = pr_redis_conn_get_version(redis, NULL, NULL, NULL);
-+ fail_unless(res < 0, "Failed to handle null version arguments");
-+ fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
-+ strerror(errno), errno);
-+
-+ mark_point();
-+ res = pr_redis_conn_get_version(redis, &major, &minor, &patch);
-+ fail_unless(res == 0, "Failed to get Redis version: %s", strerror(errno));
-+
-+ mark_point();
-+ res = pr_redis_conn_destroy(redis);
-+ fail_unless(res == TRUE, "Failed to close redis: %s", strerror(errno));
-+}
-+END_TEST
-+
- START_TEST (redis_conn_auth_test) {
- int res;
- pr_redis_t *redis;
- const char *text;
- array_header *args;
-+ unsigned int major_version = 0;
-
- mark_point();
- res = pr_redis_auth(NULL, NULL);
-@@ -245,52 +278,167 @@ START_TEST (redis_conn_auth_test) {
- fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
- strerror(errno), errno);
-
-- text = "password";
--
- /* What happens if we try to AUTH to a non-password-protected Redis?
- * Answer: Redis returns an error indicating that no password is required.
-+ *
-+ * Note that this behavior changed with Redis 6.x. In particular, any
-+ * "AUTH default ..." command automatically succeeds with Redis 6.x,
-+ * regardless of the actual password given. Sigh.
- */
-+
-+ mark_point();
-+ res = pr_redis_conn_get_version(redis, &major_version, NULL, NULL);
-+ fail_unless(res == 0, "Failed to get Redis version: %s", strerror(errno));
-+
- mark_point();
-+ text = "password";
- res = pr_redis_auth(redis, text);
-- fail_unless(res < 0, "Failed to handle lack of need for authentication");
-+
-+ if (major_version < 6) {
-+ fail_unless(res < 0, "Failed to handle lack of need for authentication");
-+ fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
-+ strerror(errno), errno);
-+
-+ /* Use CONFIG SET to require a password. */
-+ args = make_array(p, 0, sizeof(char *));
-+ *((char **) push_array(args)) = pstrdup(p, "CONFIG");
-+ *((char **) push_array(args)) = pstrdup(p, "SET");
-+ *((char **) push_array(args)) = pstrdup(p, "requirepass");
-+ *((char **) push_array(args)) = pstrdup(p, text);
-+
-+ mark_point();
-+ res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_STATUS);
-+ fail_unless(res == 0, "Failed to enable authentication: %s",
-+ strerror(errno));
-+
-+ args = make_array(p, 0, sizeof(char *));
-+ *((char **) push_array(args)) = pstrdup(p, "TIME");
-+
-+ mark_point();
-+ res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_ARRAY);
-+ fail_unless(res < 0, "Failed to handle required authentication");
-+ fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
-+ strerror(errno), errno);
-+
-+ mark_point();
-+ res = pr_redis_auth(redis, text);
-+ fail_unless(res == 0, "Failed to authenticate client: %s", strerror(errno));
-+
-+ /* Don't forget to remove the password. */
-+ args = make_array(p, 0, sizeof(char *));
-+ *((char **) push_array(args)) = pstrdup(p, "CONFIG");
-+ *((char **) push_array(args)) = pstrdup(p, "SET");
-+ *((char **) push_array(args)) = pstrdup(p, "requirepass");
-+ *((char **) push_array(args)) = pstrdup(p, "");
-+
-+ mark_point();
-+ res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_STATUS);
-+ fail_unless(res == 0, "Failed to remove password authentication: %s",
-+ strerror(errno));
-+
-+ } else {
-+ fail_unless(res == 0, "Failed to handle AUTH command: %s",
-+ strerror(errno));
-+ }
-+
-+ mark_point();
-+ res = pr_redis_conn_destroy(redis);
-+ fail_unless(res == TRUE, "Failed to close redis: %s", strerror(errno));
-+}
-+END_TEST
-+
-+START_TEST (redis_conn_auth2_test) {
-+ int res;
-+ pr_redis_t *redis;
-+ const char *username, *password;
-+ array_header *args;
-+ unsigned int major_version = 0;
-+
-+ mark_point();
-+ res = pr_redis_auth2(NULL, NULL, NULL);
-+ fail_unless(res < 0, "Failed to handle null redis");
- fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
- strerror(errno), errno);
-
-- /* Use CONFIG SET to require a password. */
-- args = make_array(p, 0, sizeof(char *));
-- *((char **) push_array(args)) = pstrdup(p, "CONFIG");
-- *((char **) push_array(args)) = pstrdup(p, "SET");
-- *((char **) push_array(args)) = pstrdup(p, "requirepass");
-- *((char **) push_array(args)) = pstrdup(p, text);
-+ mark_point();
-+ redis = pr_redis_conn_new(p, NULL, 0);
-+ fail_unless(redis != NULL, "Failed to open connection to Redis: %s",
-+ strerror(errno));
-
- mark_point();
-- res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_STATUS);
-- fail_unless(res == 0, "Failed to enable authentication: %s", strerror(errno));
-+ res = pr_redis_auth2(redis, NULL, NULL);
-+ fail_unless(res < 0, "Failed to handle null username");
-+ fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
-+ strerror(errno), errno);
-
-- args = make_array(p, 0, sizeof(char *));
-- *((char **) push_array(args)) = pstrdup(p, "TIME");
-+ /* Note: Do NOT use "default" as the initial username; that name has
-+ * specific semantics for Redis 6.x and later.
-+ */
-+ username = "foobar";
-
- mark_point();
-- res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_ARRAY);
-- fail_unless(res < 0, "Failed to handle required authentication");
-+ res = pr_redis_auth2(redis, username, NULL);
-+ fail_unless(res < 0, "Failed to handle null password");
- fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
- strerror(errno), errno);
-
-- mark_point();
-- res = pr_redis_auth(redis, text);
-- fail_unless(res == 0, "Failed to authenticate client: %s", strerror(errno));
-+ /* What happens if we try to AUTH to a non-password-protected Redis?
-+ * Answer: Redis returns an error indicating that no password is required.
-+ *
-+ * Note that this behavior changed with Redis 6.x. In particular, any
-+ * "AUTH default ..." command automatically succeeds with Redis 6.x,
-+ * regardless of the actual password given. Sigh.
-+ */
-
-- /* Don't forget to remove the password. */
-- args = make_array(p, 0, sizeof(char *));
-- *((char **) push_array(args)) = pstrdup(p, "CONFIG");
-- *((char **) push_array(args)) = pstrdup(p, "SET");
-- *((char **) push_array(args)) = pstrdup(p, "requirepass");
-- *((char **) push_array(args)) = pstrdup(p, "");
-+ mark_point();
-+ res = pr_redis_conn_get_version(redis, &major_version, NULL, NULL);
-+ fail_unless(res == 0, "Failed to get Redis version: %s", strerror(errno));
-
- mark_point();
-- res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_STATUS);
-- fail_unless(res == 0, "Failed to remove password authentication: %s",
-- strerror(errno));
-+ password = "password";
-+ res = pr_redis_auth2(redis, username, password);
-+ fail_unless(res < 0, "Failed to handle lack of need for authentication");
-+ fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
-+ strerror(errno), errno);
-+
-+ if (major_version < 6) {
-+ /* Use CONFIG SET to require a password. */
-+ args = make_array(p, 0, sizeof(char *));
-+ *((char **) push_array(args)) = pstrdup(p, "CONFIG");
-+ *((char **) push_array(args)) = pstrdup(p, "SET");
-+ *((char **) push_array(args)) = pstrdup(p, "requirepass");
-+ *((char **) push_array(args)) = pstrdup(p, password);
-+
-+ mark_point();
-+ res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_STATUS);
-+ fail_unless(res == 0, "Failed to enable authentication: %s",
-+ strerror(errno));
-+
-+ args = make_array(p, 0, sizeof(char *));
-+ *((char **) push_array(args)) = pstrdup(p, "TIME");
-+
-+ mark_point();
-+ res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_ARRAY);
-+ fail_unless(res < 0, "Failed to handle required authentication");
-+ fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
-+ strerror(errno), errno);
-+
-+ mark_point();
-+ res = pr_redis_auth2(redis, username, password);
-+ fail_unless(res == 0, "Failed to authenticate client: %s", strerror(errno));
-+
-+ /* Don't forget to remove the password. */
-+ args = make_array(p, 0, sizeof(char *));
-+ *((char **) push_array(args)) = pstrdup(p, "CONFIG");
-+ *((char **) push_array(args)) = pstrdup(p, "SET");
-+ *((char **) push_array(args)) = pstrdup(p, "requirepass");
-+ *((char **) push_array(args)) = pstrdup(p, "");
-+
-+ mark_point();
-+ res = pr_redis_command(redis, args, PR_REDIS_REPLY_TYPE_STATUS);
-+ fail_unless(res == 0, "Failed to remove password authentication: %s",
-+ strerror(errno));
-+ }
-
- mark_point();
- res = pr_redis_conn_destroy(redis);
-@@ -1987,7 +2135,7 @@ START_TEST (redis_hash_keys_test) {
- mark_point();
- res = pr_redis_hash_keys(p, redis, &m, key, &fields);
- fail_unless(res == 0, "Failed to handle existing fields: %s", strerror(errno));
-- fail_unless(fields != NULL);
-+ fail_unless(fields != NULL, "Failed to get hash fields");
- fail_unless(fields->nelts == 2, "Expected 2, got %u", fields->nelts);
-
- (void) pr_redis_remove(redis, &m, key);
-@@ -2074,7 +2222,7 @@ START_TEST (redis_hash_values_test) {
- mark_point();
- res = pr_redis_hash_values(p, redis, &m, key, &values);
- fail_unless(res == 0, "Failed to handle existing values: %s", strerror(errno));
-- fail_unless(values != NULL);
-+ fail_unless(values != NULL, "Failed to get hash values");
- fail_unless(values->nelts == 2, "Expected 2, got %u", values->nelts);
-
- (void) pr_redis_remove(redis, &m, key);
-@@ -2161,7 +2309,7 @@ START_TEST (redis_hash_getall_test) {
- mark_point();
- res = pr_redis_hash_getall(p, redis, &m, key, &hash);
- fail_unless(res == 0, "Failed to handle existing fields: %s", strerror(errno));
-- fail_unless(hash != NULL);
-+ fail_unless(hash != NULL, "Failed to get hash");
- res = pr_table_count(hash);
- fail_unless(res == 2, "Expected 2, got %d", res);
-
-@@ -4743,7 +4891,9 @@ Suite *tests_get_redis_suite(void) {
- tcase_add_test(testcase, redis_conn_new_test);
- tcase_add_test(testcase, redis_conn_get_test);
- tcase_add_test(testcase, redis_conn_set_namespace_test);
-+ tcase_add_test(testcase, redis_conn_get_version_test);
- tcase_add_test(testcase, redis_conn_auth_test);
-+ tcase_add_test(testcase, redis_conn_auth2_test);
- tcase_add_test(testcase, redis_conn_select_test);
- tcase_add_test(testcase, redis_conn_reconnect_test);
- tcase_add_test(testcase, redis_command_test);
-diff --git a/tests/api/sets.c b/tests/api/sets.c
-index 9f3deafc2..9459454f2 100644
---- a/tests/api/sets.c
-+++ b/tests/api/sets.c
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - FTP server testsuite
-- * Copyright (c) 2008-2011 The ProFTPD Project team
-+ * Copyright (c) 2008-2020 The ProFTPD Project team
- *
- * 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
-@@ -97,20 +97,20 @@ START_TEST (set_create_test) {
- fail_unless(errno == EPERM, "Failed to set errno to EPERM");
-
- res = xaset_create(p, NULL);
-- fail_unless(res != NULL);
-+ fail_unless(res != NULL, "Expected non-null result");
- fail_unless(res->pool == p, "Expected %p, got %p", p, res->pool);
-
- permanent_pool = make_sub_pool(p);
-
- res = xaset_create(NULL, NULL);
-- fail_unless(res != NULL);
-+ fail_unless(res != NULL, "Expected non-null result");
- fail_unless(res->pool == permanent_pool, "Expected %p, got %p",
- permanent_pool, res->pool);
- fail_unless(res->xas_compare == NULL, "Expected NULL, got %p",
- res->xas_compare);
-
- res = xaset_create(p, (XASET_COMPARE) item_cmp);
-- fail_unless(res != NULL);
-+ fail_unless(res != NULL, "Expected non-null result");
- fail_unless(res->pool == p, "Expected %p, got %p", p, res->pool);
- fail_unless(res->xas_compare == (XASET_COMPARE) item_cmp,
- "Expected %p, got %p", item_cmp, res->xas_compare);
-@@ -355,12 +355,12 @@ START_TEST (set_remove_test) {
- fail_unless(res == 0, "Failed to add item2");
-
- member = (xasetmember_t *) item1;
-- fail_unless(member->next == NULL);
-- fail_unless(member->prev != NULL);
-+ fail_unless(member->next == NULL, "Expected member->next to be null");
-+ fail_unless(member->prev != NULL, "Expected member->prev to not be null");
-
- member = (xasetmember_t *) item2;
-- fail_unless(member->next != NULL);
-- fail_unless(member->prev == NULL);
-+ fail_unless(member->next != NULL, "Expected member->next to not be null");
-+ fail_unless(member->prev == NULL, "Expected member->prev to be null");
-
- member = set->xas_list;
- fail_unless(member == (xasetmember_t *) item2,
-@@ -371,8 +371,8 @@ START_TEST (set_remove_test) {
- strerror(errno));
-
- member = (xasetmember_t *) item2;
-- fail_unless(member->next == NULL);
-- fail_unless(member->prev == NULL);
-+ fail_unless(member->next == NULL, "Expected member->next to be null");
-+ fail_unless(member->prev == NULL, "Expected member->prev to be null");
-
- member = set->xas_list;
- fail_unless(member == (xasetmember_t *) item1,
-@@ -383,8 +383,8 @@ START_TEST (set_remove_test) {
- strerror(errno));
-
- member = (xasetmember_t *) item1;
-- fail_unless(member->next == NULL);
-- fail_unless(member->prev == NULL);
-+ fail_unless(member->next == NULL, "Expected member->next to be null");
-+ fail_unless(member->prev == NULL, "Expected member->prev to be null");
-
- member = set->xas_list;
- fail_unless(member == NULL, "Expected list to be empty, got %p", member);
-diff --git a/tests/api/str.c b/tests/api/str.c
-index 9dce95820..050f5c563 100644
---- a/tests/api/str.c
-+++ b/tests/api/str.c
-@@ -1539,10 +1539,10 @@ START_TEST (uid2str_test) {
- const char *res;
-
- res = pr_uid2str(NULL, (uid_t) 1);
-- fail_unless(strcmp(res, "1") == 0);
-+ fail_unless(strcmp(res, "1") == 0, "Expected '1', got '%s'", res);
-
- res = pr_uid2str(NULL, (uid_t) -1);
-- fail_unless(strcmp(res, "-1") == 0);
-+ fail_unless(strcmp(res, "-1") == 0, "Expected '-1', got '%s'", res);
- }
- END_TEST
-
-@@ -1550,10 +1550,10 @@ START_TEST (gid2str_test) {
- const char *res;
-
- res = pr_gid2str(NULL, (gid_t) 1);
-- fail_unless(strcmp(res, "1") == 0);
-+ fail_unless(strcmp(res, "1") == 0, "Expected '1', got '%s'", res);
-
- res = pr_gid2str(NULL, (gid_t) -1);
-- fail_unless(strcmp(res, "-1") == 0);
-+ fail_unless(strcmp(res, "-1") == 0, "Expected '-1', got '%s'", res);
- }
- END_TEST
-
-diff --git a/tests/api/timers.c b/tests/api/timers.c
-index 99b6348e9..0616a7989 100644
---- a/tests/api/timers.c
-+++ b/tests/api/timers.c
-@@ -157,7 +157,7 @@ START_TEST (timer_remove_test) {
- int res;
-
- res = pr_timer_remove(0, NULL);
-- fail_unless(res == 0);
-+ fail_unless(res == 0, "Failed to remove timer: %s", strerror(errno));
-
- res = pr_timer_add(1, 0, NULL, timers_test_cb, "test");
- fail_unless(res == 0, "Failed to add timer (%d): %s", res, strerror(errno));
=====================================
debian/patches/upstream_1284 deleted
=====================================
@@ -1,43 +0,0 @@
-From 10a227b4d50e0a2cd2faf87926f58d865da44e43 Mon Sep 17 00:00:00 2001
-From: Chris Hofstaedtler <chris.hofstaedtler at deduktiva.com>
-Date: Tue, 3 Aug 2021 21:53:28 +0200
-Subject: [PATCH] mod_radius: copy _only_ the password
-
----
- contrib/mod_radius.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
-Index: proftpd/contrib/mod_radius.c
-===================================================================
---- proftpd.orig/contrib/mod_radius.c 2021-08-28 16:10:46.810595478 +0200
-+++ proftpd/contrib/mod_radius.c 2021-08-28 16:10:46.782595919 +0200
-@@ -2319,21 +2319,26 @@
-
- pwlen = strlen((const char *) passwd);
-
-+ /* Clear the buffers. */
-+ memset(pwhash, '\0', sizeof(pwhash));
-+
- if (pwlen == 0) {
- pwlen = RADIUS_PASSWD_LEN;
-
- } if ((pwlen & (RADIUS_PASSWD_LEN - 1)) != 0) {
-+ /* pwlen is not a multiple of RADIUS_PASSWD_LEN, need to prepare a proper buffer */
-+ memcpy(pwhash, passwd, pwlen);
-
- /* Round up the length. */
- pwlen += (RADIUS_PASSWD_LEN - 1);
-
- /* Truncate the length, as necessary. */
- pwlen &= ~(RADIUS_PASSWD_LEN - 1);
-+ } else {
-+ /* pwlen is a multiple of RADIUS_PASSWD_LEN, we can just use it. */
-+ memcpy(pwhash, passwd, pwlen);
- }
-
-- /* Clear the buffers. */
-- memset(pwhash, '\0', sizeof(pwhash));
-- memcpy(pwhash, passwd, pwlen);
-
- /* Find the password attribute. */
- attrib = radius_get_attrib(packet, RADIUS_PASSWORD);
=====================================
debian/patches/upstream_1322 deleted
=====================================
@@ -1,154 +0,0 @@
-From e428a379fc97db8400a497045a57a69468666901 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sat, 4 Sep 2021 10:19:01 -0700
-Subject: [PATCH] Issue #1321: When processing very long lines from an
- `AuthGroupFile`, allocate larger buffers in smaller increments, as
- `fgetgrent(3)` does.
-
----
- modules/mod_auth_file.c | 11 ++-
- tests/t/lib/ProFTPD/TestSuite/Utils.pm | 4 +-
- .../ProFTPD/Tests/Modules/mod_auth_file.pm | 80 +++++++++++++++++++
- 3 files changed, 92 insertions(+), 3 deletions(-)
-
---- proftpd.orig/modules/mod_auth_file.c
-+++ proftpd/modules/mod_auth_file.c
-@@ -332,6 +332,9 @@
- static char *af_getgrentline(char **buf, int *buflen, pr_fh_t *fh,
- unsigned int *lineno) {
- char *cp = *buf;
-+ int original_buflen;
-+
-+ original_buflen = *buflen;
-
- while (pr_fsio_gets(cp, (*buflen) - (cp - *buf), fh) != NULL) {
- pr_signals_handle();
-@@ -343,8 +346,12 @@
- return *buf;
- }
-
-- /* No -- allocate a larger buffer, doubling buflen. */
-- *buflen += *buflen;
-+ /* No -- allocate a larger buffer. Note that doubling the buflen
-+ * each time may cause issues; fgetgrent(3) would increment the
-+ * allocated buffer by the original buffer length each time. So we
-+ * do the same (Issue #1321).
-+ */
-+ *buflen += original_buflen;
-
- {
- char *new_buf;
---- proftpd.orig/tests/t/lib/ProFTPD/TestSuite/Utils.pm
-+++ proftpd/tests/t/lib/ProFTPD/TestSuite/Utils.pm
-@@ -1210,6 +1210,8 @@
- my $gid = shift;
- $gid = 500 unless defined($gid);
- my $home_dir = shift;
-+ my $groups = shift;
-+ $groups = $user unless defined($groups);
-
- my $config_file = "$tmpdir/$name.conf";
- my $pid_file = File::Spec->rel2abs("$tmpdir/$name.pid");
-@@ -1238,7 +1240,7 @@
-
- auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
- '/bin/bash');
-- auth_group_write($auth_group_file, $group, $gid, $user);
-+ auth_group_write($auth_group_file, $group, $gid, $groups);
-
- my $setup = {
- auth_user_file => $auth_user_file,
---- proftpd.orig/tests/t/lib/ProFTPD/Tests/Modules/mod_auth_file.pm
-+++ proftpd/tests/t/lib/ProFTPD/Tests/Modules/mod_auth_file.pm
-@@ -122,6 +122,10 @@
- test_class => [qw(bug forking)],
- },
-
-+ auth_file_line_too_long_issue1321 => {
-+ order => ++$order,
-+ test_class => [qw(bug forking)],
-+ },
- };
-
- sub new {
-@@ -2271,4 +2275,80 @@
- unlink($log_file);
- }
-
-+sub auth_file_line_too_long_issue1321 {
-+ my $self = shift;
-+ my $tmpdir = $self->{tmpdir};
-+
-+ # For Issue #1321, we create a very long AuthGroupFile entry with many
-+ # group names.
-+
-+ my $groups = 'proftpd';
-+ for (my $i = 0; $i < 200; $i++) {
-+ $groups .= ",quite.long.example.group.$i";
-+ }
-+
-+ my $setup = test_setup($tmpdir, 'authfile', undef, undef, undef, undef, undef,
-+ undef, $groups);
-+
-+ my $config = {
-+ PidFile => $setup->{pid_file},
-+ ScoreboardFile => $setup->{scoreboard_file},
-+ SystemLog => $setup->{log_file},
-+
-+ AuthUserFile => $setup->{auth_user_file},
-+ AuthGroupFile => $setup->{auth_group_file},
-+
-+ IfModules => {
-+ 'mod_delay.c' => {
-+ DelayEngine => 'off',
-+ },
-+ },
-+ };
-+
-+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
-+ $config);
-+
-+ # Open pipes, for use between the parent and child processes. Specifically,
-+ # the child will indicate when it's done with its test by writing a message
-+ # to the parent.
-+ my ($rfh, $wfh);
-+ unless (pipe($rfh, $wfh)) {
-+ die("Can't open pipe: $!");
-+ }
-+
-+ my $ex;
-+
-+ # Fork child
-+ $self->handle_sigchld();
-+ defined(my $pid = fork()) or die("Can't fork: $!");
-+ if ($pid) {
-+ eval {
-+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-+ $client->login($setup->{user}, $setup->{passwd});
-+ $client->quit();
-+ };
-+ if ($@) {
-+ $ex = $@;
-+ }
-+
-+ $wfh->print("done\n");
-+ $wfh->flush();
-+
-+ } else {
-+ eval { server_wait($setup->{config_file}, $rfh) };
-+ if ($@) {
-+ warn($@);
-+ exit 1;
-+ }
-+
-+ exit 0;
-+ }
-+
-+ # Stop server
-+ server_stop($setup->{pid_file});
-+ $self->assert_child_ok($pid);
-+
-+ test_cleanup($setup->{log_file}, $ex);
-+}
-+
- 1;
=====================================
debian/patches/upstream_1325 deleted
=====================================
@@ -1,569 +0,0 @@
-From 6e3d8debc14f1b532fae27994120f591b39fb183 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Sat, 11 Sep 2021 14:22:31 -0700
-Subject: [PATCH] Backport fix for Issue #1325 to the 1.3.7 branch.
-
----
- NEWS | 1 +
- modules/mod_ls.c | 6 +-
- tests/t/lib/ProFTPD/Tests/Commands/NLST.pm | 453 +++++++++++++++++++--
- 3 files changed, 412 insertions(+), 48 deletions(-)
-
-diff --git a/modules/mod_ls.c b/modules/mod_ls.c
-index 45a3187bd9..c7a44c450a 100644
---- a/modules/mod_ls.c
-+++ b/modules/mod_ls.c
-@@ -2,7 +2,7 @@
- * ProFTPD - FTP server daemon
- * Copyright (c) 1997, 1998 Public Flood Software
- * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver at tos.net>
-- * Copyright (c) 2001-2020 The ProFTPD Project
-+ * Copyright (c) 2001-2021 The ProFTPD Project
- *
- * 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
-@@ -3163,10 +3163,6 @@ MODRET ls_nlst(cmd_rec *cmd) {
- p = *path;
- path++;
-
-- if (*p == '.' && (!opt_A || is_dotdir(p))) {
-- continue;
-- }
--
- pr_fs_clear_cache2(p);
- if (pr_fsio_stat(p, &st) == 0) {
- /* If it's a directory... */
-diff --git a/tests/t/lib/ProFTPD/Tests/Commands/NLST.pm b/tests/t/lib/ProFTPD/Tests/Commands/NLST.pm
-index 7fa5c84177..eac38ea24d 100644
---- a/tests/t/lib/ProFTPD/Tests/Commands/NLST.pm
-+++ b/tests/t/lib/ProFTPD/Tests/Commands/NLST.pm
-@@ -157,6 +157,16 @@ my $TESTS = {
- test_class => [qw(forking rootprivs)],
- },
-
-+ nlst_glob_with_rel_path_issue1325 => {
-+ order => ++$order,
-+ test_class => [qw(bug forking)],
-+ },
-+
-+ nlst_glob_with_rel_path_dotdir_issue1325 => {
-+ order => ++$order,
-+ test_class => [qw(bug forking)],
-+ },
-+
- };
-
- sub new {
-@@ -3616,22 +3626,7 @@ sub nlst_rel_path_chrooted_bug2496 {
- sub nlst_parent_dir_bug4011 {
- my $self = shift;
- my $tmpdir = $self->{tmpdir};
--
-- my $config_file = "$tmpdir/cmds.conf";
-- my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid");
-- my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard");
--
-- my $log_file = test_get_logfile();
--
-- my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd");
-- my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group");
--
-- my $user = 'proftpd';
-- my $passwd = 'test';
-- my $group = 'ftpd';
-- my $home_dir = File::Spec->rel2abs($tmpdir);
-- my $uid = 500;
-- my $gid = 500;
-+ my $setup = test_setup($tmpdir, 'cmds');
-
- my $sub_dir1 = File::Spec->rel2abs("$tmpdir/dir1");
- my $sub_dir2 = File::Spec->rel2abs("$tmpdir/dir1/dir2");
-@@ -3662,26 +3657,22 @@ sub nlst_parent_dir_bug4011 {
- # Make sure that, if we're running as root, that the home directory has
- # permissions/privs set for the account we create
- if ($< == 0) {
-- unless (chmod(0755, $home_dir, $sub_dir1)) {
-- die("Can't set perms on $home_dir to 0755: $!");
-+ unless (chmod(0755, $sub_dir1)) {
-+ die("Can't set perms on $sub_dir1 to 0755: $!");
- }
-
-- unless (chown($uid, $gid, $home_dir, $sub_dir1)) {
-- die("Can't set owner of $home_dir to $uid/$gid: $!");
-+ unless (chown($setup->{uid}, $setup->{gid}, $sub_dir1)) {
-+ die("Can't set owner of $sub_dir1 to $setup->{uid}/$setup->{gid}: $!");
- }
- }
-
-- auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
-- '/bin/bash');
-- auth_group_write($auth_group_file, $group, $gid, $user);
--
- my $config = {
-- PidFile => $pid_file,
-- ScoreboardFile => $scoreboard_file,
-- SystemLog => $log_file,
-+ PidFile => $setup->{pid_file},
-+ ScoreboardFile => $setup->{scoreboard_file},
-+ SystemLog => $setup->{log_file},
-
-- AuthUserFile => $auth_user_file,
-- AuthGroupFile => $auth_group_file,
-+ AuthUserFile => $setup->{auth_user_file},
-+ AuthGroupFile => $setup->{auth_group_file},
-
- IfModules => {
- 'mod_delay.c' => {
-@@ -3690,7 +3681,8 @@ sub nlst_parent_dir_bug4011 {
- },
- };
-
-- my ($port, $config_user, $config_group) = config_write($config_file, $config);
-+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
-+ $config);
-
- # Open pipes, for use between the parent and child processes. Specifically,
- # the child will indicate when it's done with its test by writing a message
-@@ -3708,7 +3700,7 @@ sub nlst_parent_dir_bug4011 {
- if ($pid) {
- eval {
- my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-- $client->login($user, $passwd);
-+ $client->login($setup->{user}, $setup->{passwd});
- $client->cwd("dir1");
- $client->cwd("dir2");
-
-@@ -3722,6 +3714,12 @@ sub nlst_parent_dir_bug4011 {
- $conn->read($buf, 8192, 25);
- eval { $conn->close() };
-
-+ $client->quit();
-+
-+ if ($ENV{TEST_VERBOSE}) {
-+ print STDERR "# response:\n$buf\n";
-+ }
-+
- # We have to be careful of the fact that readdir returns directory
- # entries in an unordered fashion.
- my $res = {};
-@@ -3749,7 +3747,6 @@ sub nlst_parent_dir_bug4011 {
- die("Unexpected name '$mismatch' appeared in NLST data")
- }
- };
--
- if ($@) {
- $ex = $@;
- }
-@@ -3758,7 +3755,7 @@ sub nlst_parent_dir_bug4011 {
- $wfh->flush();
-
- } else {
-- eval { server_wait($config_file, $rfh) };
-+ eval { server_wait($setup->{config_file}, $rfh) };
- if ($@) {
- warn($@);
- exit 1;
-@@ -3768,18 +3765,10 @@ sub nlst_parent_dir_bug4011 {
- }
-
- # Stop server
-- server_stop($pid_file);
--
-+ server_stop($setup->{pid_file});
- $self->assert_child_ok($pid);
-
-- if ($ex) {
-- test_append_logfile($log_file, $ex);
-- unlink($log_file);
--
-- die($ex);
-- }
--
-- unlink($log_file);
-+ test_cleanup($setup->{log_file}, $ex);
- }
-
- sub nlst_opt_a_root_dir_bug4069 {
-@@ -4080,4 +4069,382 @@ sub nlst_opt_1_with_chroot {
- unlink($log_file);
- }
-
-+sub nlst_glob_with_rel_path_issue1325 {
-+ my $self = shift;
-+ my $tmpdir = $self->{tmpdir};
-+ my $setup = test_setup($tmpdir, 'cmds');
-+
-+ my $test_path = File::Spec->rel2abs("$tmpdir/test.d");
-+ mkpath($test_path);
-+
-+ for (my $i = 0; $i < 10; $i++) {
-+ my $test_file = File::Spec->rel2abs("$test_path/TEST000$i.dat");
-+ if (open(my $fh, "> $test_file")) {
-+ print $fh "Hello, World!\n";
-+ unless (close($fh)) {
-+ die("Can't write $test_file: $!");
-+ }
-+
-+ } else {
-+ die("Can't open $test_file: $!");
-+ }
-+ }
-+
-+ my $config = {
-+ PidFile => $setup->{pid_file},
-+ ScoreboardFile => $setup->{scoreboard_file},
-+ SystemLog => $setup->{log_file},
-+
-+ AuthUserFile => $setup->{auth_user_file},
-+ AuthGroupFile => $setup->{auth_group_file},
-+
-+ IfModules => {
-+ 'mod_delay.c' => {
-+ DelayEngine => 'off',
-+ },
-+ },
-+ };
-+
-+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
-+ $config);
-+
-+ # Open pipes, for use between the parent and child processes. Specifically,
-+ # the child will indicate when it's done with its test by writing a message
-+ # to the parent.
-+ my ($rfh, $wfh);
-+ unless (pipe($rfh, $wfh)) {
-+ die("Can't open pipe: $!");
-+ }
-+
-+ my $ex;
-+
-+ # Fork child
-+ $self->handle_sigchld();
-+ defined(my $pid = fork()) or die("Can't fork: $!");
-+ if ($pid) {
-+ eval {
-+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-+ $client->login($setup->{user}, $setup->{passwd});
-+
-+ my $conn = $client->nlst_raw('test.d/TEST????.dat');
-+ unless ($conn) {
-+ die("Failed to NLST: " . $client->response_code() . " " .
-+ $client->response_msg());
-+ }
-+
-+ my $buf;
-+ $conn->read($buf, 8192, 25);
-+ eval { $conn->close() };
-+
-+ if ($ENV{TEST_VERBOSE}) {
-+ print STDERR "# response:\n$buf\n";
-+ }
-+
-+ # We have to be careful of the fact that readdir returns directory
-+ # entries in an unordered fashion.
-+ my $res = {};
-+ my $names = [split(/\n/, $buf)];
-+ foreach my $name (@$names) {
-+ $res->{$name} = 1;
-+ }
-+
-+ $self->assert(scalar(@$names) > 0,
-+ test_msg("Expected multiple names, got 0"));
-+
-+ my $expected = {
-+ 'test.d/TEST0000.dat' => 1,
-+ 'test.d/TEST0001.dat' => 1,
-+ 'test.d/TEST0002.dat' => 1,
-+ 'test.d/TEST0003.dat' => 1,
-+ 'test.d/TEST0004.dat' => 1,
-+ 'test.d/TEST0005.dat' => 1,
-+ 'test.d/TEST0006.dat' => 1,
-+ 'test.d/TEST0007.dat' => 1,
-+ 'test.d/TEST0008.dat' => 1,
-+ 'test.d/TEST0009.dat' => 1,
-+ };
-+
-+ my $ok = 1;
-+ my $mismatch;
-+ foreach my $name (keys(%$res)) {
-+ unless (defined($expected->{$name})) {
-+ $mismatch = $name;
-+ $ok = 0;
-+ last;
-+ }
-+ }
-+
-+ unless ($ok) {
-+ die("Unexpected name '$mismatch' appeared in NLST data")
-+ }
-+
-+ # Now do it again, this time using an explicit relative path.
-+
-+ $conn = $client->nlst_raw('./test.d/TEST????.dat');
-+ unless ($conn) {
-+ die("Failed to NLST: " . $client->response_code() . " " .
-+ $client->response_msg());
-+ }
-+
-+ $buf = '';
-+ $conn->read($buf, 8192, 25);
-+ eval { $conn->close() };
-+
-+ if ($ENV{TEST_VERBOSE}) {
-+ print STDERR "# response:\n$buf\n";
-+ }
-+
-+ # We have to be careful of the fact that readdir returns directory
-+ # entries in an unordered fashion.
-+ $res = {};
-+ $names = [split(/\n/, $buf)];
-+ foreach my $name (@$names) {
-+ $res->{$name} = 1;
-+ }
-+
-+ $self->assert(scalar(@$names) > 0,
-+ test_msg("Expected multiple names, got 0"));
-+
-+ $expected = {
-+ './test.d/TEST0000.dat' => 1,
-+ './test.d/TEST0001.dat' => 1,
-+ './test.d/TEST0002.dat' => 1,
-+ './test.d/TEST0003.dat' => 1,
-+ './test.d/TEST0004.dat' => 1,
-+ './test.d/TEST0005.dat' => 1,
-+ './test.d/TEST0006.dat' => 1,
-+ './test.d/TEST0007.dat' => 1,
-+ './test.d/TEST0008.dat' => 1,
-+ './test.d/TEST0009.dat' => 1,
-+ };
-+
-+ $ok = 1;
-+ $mismatch = '';
-+ foreach my $name (keys(%$res)) {
-+ unless (defined($expected->{$name})) {
-+ $mismatch = $name;
-+ $ok = 0;
-+ last;
-+ }
-+ }
-+
-+ unless ($ok) {
-+ die("Unexpected name '$mismatch' appeared in NLST data")
-+ }
-+
-+ $client->quit();
-+ };
-+ if ($@) {
-+ $ex = $@;
-+ }
-+
-+ $wfh->print("done\n");
-+ $wfh->flush();
-+
-+ } else {
-+ eval { server_wait($setup->{config_file}, $rfh) };
-+ if ($@) {
-+ warn($@);
-+ exit 1;
-+ }
-+
-+ exit 0;
-+ }
-+
-+ # Stop server
-+ server_stop($setup->{pid_file});
-+ $self->assert_child_ok($pid);
-+
-+ test_cleanup($setup->{log_file}, $ex);
-+}
-+
-+sub nlst_glob_with_rel_path_dotdir_issue1325 {
-+ my $self = shift;
-+ my $tmpdir = $self->{tmpdir};
-+ my $setup = test_setup($tmpdir, 'cmds');
-+
-+ my $test_path = File::Spec->rel2abs("$tmpdir/.test.d");
-+ mkpath($test_path);
-+
-+ for (my $i = 0; $i < 10; $i++) {
-+ my $test_file = File::Spec->rel2abs("$test_path/TEST000$i.dat");
-+ if (open(my $fh, "> $test_file")) {
-+ print $fh "Hello, World!\n";
-+ unless (close($fh)) {
-+ die("Can't write $test_file: $!");
-+ }
-+
-+ } else {
-+ die("Can't open $test_file: $!");
-+ }
-+ }
-+
-+ my $config = {
-+ PidFile => $setup->{pid_file},
-+ ScoreboardFile => $setup->{scoreboard_file},
-+ SystemLog => $setup->{log_file},
-+
-+ AuthUserFile => $setup->{auth_user_file},
-+ AuthGroupFile => $setup->{auth_group_file},
-+
-+ IfModules => {
-+ 'mod_delay.c' => {
-+ DelayEngine => 'off',
-+ },
-+ },
-+ };
-+
-+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
-+ $config);
-+
-+ # Open pipes, for use between the parent and child processes. Specifically,
-+ # the child will indicate when it's done with its test by writing a message
-+ # to the parent.
-+ my ($rfh, $wfh);
-+ unless (pipe($rfh, $wfh)) {
-+ die("Can't open pipe: $!");
-+ }
-+
-+ my $ex;
-+
-+ # Fork child
-+ $self->handle_sigchld();
-+ defined(my $pid = fork()) or die("Can't fork: $!");
-+ if ($pid) {
-+ eval {
-+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
-+ $client->login($setup->{user}, $setup->{passwd});
-+
-+ my $conn = $client->nlst_raw('.test.d/TEST????.dat');
-+ unless ($conn) {
-+ die("Failed to NLST: " . $client->response_code() . " " .
-+ $client->response_msg());
-+ }
-+
-+ my $buf;
-+ $conn->read($buf, 8192, 25);
-+ eval { $conn->close() };
-+
-+ if ($ENV{TEST_VERBOSE}) {
-+ print STDERR "# response:\n$buf\n";
-+ }
-+
-+ # We have to be careful of the fact that readdir returns directory
-+ # entries in an unordered fashion.
-+ my $res = {};
-+ my $names = [split(/\n/, $buf)];
-+ foreach my $name (@$names) {
-+ $res->{$name} = 1;
-+ }
-+
-+ $self->assert(scalar(@$names) > 0,
-+ test_msg("Expected multiple names, got 0"));
-+
-+ my $expected = {
-+ '.test.d/TEST0000.dat' => 1,
-+ '.test.d/TEST0001.dat' => 1,
-+ '.test.d/TEST0002.dat' => 1,
-+ '.test.d/TEST0003.dat' => 1,
-+ '.test.d/TEST0004.dat' => 1,
-+ '.test.d/TEST0005.dat' => 1,
-+ '.test.d/TEST0006.dat' => 1,
-+ '.test.d/TEST0007.dat' => 1,
-+ '.test.d/TEST0008.dat' => 1,
-+ '.test.d/TEST0009.dat' => 1,
-+ };
-+
-+ my $ok = 1;
-+ my $mismatch;
-+ foreach my $name (keys(%$res)) {
-+ unless (defined($expected->{$name})) {
-+ $mismatch = $name;
-+ $ok = 0;
-+ last;
-+ }
-+ }
-+
-+ unless ($ok) {
-+ die("Unexpected name '$mismatch' appeared in NLST data")
-+ }
-+
-+ # Now do it again, this time using an explicit relative path.
-+
-+ $conn = $client->nlst_raw('./.test.d/TEST????.dat');
-+ unless ($conn) {
-+ die("Failed to NLST: " . $client->response_code() . " " .
-+ $client->response_msg());
-+ }
-+
-+ $buf = '';
-+ $conn->read($buf, 8192, 25);
-+ eval { $conn->close() };
-+
-+ if ($ENV{TEST_VERBOSE}) {
-+ print STDERR "# response:\n$buf\n";
-+ }
-+
-+ # We have to be careful of the fact that readdir returns directory
-+ # entries in an unordered fashion.
-+ $res = {};
-+ $names = [split(/\n/, $buf)];
-+ foreach my $name (@$names) {
-+ $res->{$name} = 1;
-+ }
-+
-+ $self->assert(scalar(@$names) > 0,
-+ test_msg("Expected multiple names, got 0"));
-+
-+ $expected = {
-+ './.test.d/TEST0000.dat' => 1,
-+ './.test.d/TEST0001.dat' => 1,
-+ './.test.d/TEST0002.dat' => 1,
-+ './.test.d/TEST0003.dat' => 1,
-+ './.test.d/TEST0004.dat' => 1,
-+ './.test.d/TEST0005.dat' => 1,
-+ './.test.d/TEST0006.dat' => 1,
-+ './.test.d/TEST0007.dat' => 1,
-+ './.test.d/TEST0008.dat' => 1,
-+ './.test.d/TEST0009.dat' => 1,
-+ };
-+
-+ $ok = 1;
-+ $mismatch = '';
-+ foreach my $name (keys(%$res)) {
-+ unless (defined($expected->{$name})) {
-+ $mismatch = $name;
-+ $ok = 0;
-+ last;
-+ }
-+ }
-+
-+ unless ($ok) {
-+ die("Unexpected name '$mismatch' appeared in NLST data")
-+ }
-+
-+ $client->quit();
-+ };
-+ if ($@) {
-+ $ex = $@;
-+ }
-+
-+ $wfh->print("done\n");
-+ $wfh->flush();
-+
-+ } else {
-+ eval { server_wait($setup->{config_file}, $rfh) };
-+ if ($@) {
-+ warn($@);
-+ exit 1;
-+ }
-+
-+ exit 0;
-+ }
-+
-+ # Stop server
-+ server_stop($setup->{pid_file});
-+ $self->assert_child_ok($pid);
-+
-+ test_cleanup($setup->{log_file}, $ex);
-+}
-+
- 1;
=====================================
debian/patches/upstream_1346 deleted
=====================================
@@ -1,441 +0,0 @@
-From bb8116d21f7849bf36cc356de4d8cfec579eba64 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Tue, 26 Oct 2021 19:10:59 -0700
-Subject: [PATCH] Issue #1346: When accept connections for passive data
- transfers, and a class name has been configured for `AllowForeignAddress`,
- check the connecting client against that class.
-
----
- src/inet.c | 90 +++++--
- .../Tests/Config/AllowForeignAddress.pm | 255 +++++++++++++++++-
- 2 files changed, 314 insertions(+), 31 deletions(-)
-
-diff --git a/src/inet.c b/src/inet.c
-index 33ce349aa3..81c1c99b1d 100644
---- a/src/inet.c
-+++ b/src/inet.c
-@@ -1522,9 +1522,9 @@ int pr_inet_accept_nowait(pool *p, conn_t *c) {
- */
- conn_t *pr_inet_accept(pool *p, conn_t *d, conn_t *c, int rfd, int wfd,
- unsigned char resolve) {
-+ config_rec *allow_foreign_addr_config = NULL;
- conn_t *res = NULL;
-- unsigned char *foreign_addr = NULL;
-- int fd = -1, allow_foreign_address = FALSE;
-+ int fd = -1;
- pr_netaddr_t na;
- socklen_t nalen;
-
-@@ -1540,13 +1540,10 @@ conn_t *pr_inet_accept(pool *p, conn_t *d, conn_t *c, int rfd, int wfd,
- pr_netaddr_set_family(&na, pr_netaddr_get_family(c->remote_addr));
- nalen = pr_netaddr_get_sockaddr_len(&na);
-
-+ allow_foreign_addr_config = find_config(TOPLEVEL_CONF, CONF_PARAM,
-+ "AllowForeignAddress", FALSE);
- d->mode = CM_ACCEPT;
-
-- foreign_addr = get_param_ptr(TOPLEVEL_CONF, "AllowForeignAddress", FALSE);
-- if (foreign_addr != NULL) {
-- allow_foreign_address = *foreign_addr;
-- }
--
- /* A directive could enforce only IPv4 or IPv6 connections here, by
- * actually using a sockaddr argument to accept(2), and checking the
- * family of the connecting entity.
-@@ -1566,28 +1563,67 @@ conn_t *pr_inet_accept(pool *p, conn_t *d, conn_t *c, int rfd, int wfd,
- break;
- }
-
-- if (allow_foreign_address == FALSE) {
-- /* If foreign addresses (i.e. IP addresses that do not match the
-- * control connection's remote IP address) are not allowed, we
-- * need to see just what our remote address IS.
-- */
-- if (getpeername(fd, pr_netaddr_get_sockaddr(&na), &nalen) < 0) {
-- /* If getpeername(2) fails, should we still allow this connection?
-- * Caution (and the AllowForeignAddress setting say "no".
-+ if (allow_foreign_addr_config != NULL) {
-+ int allowed;
-+
-+ allowed = *((int *) allow_foreign_addr_config->argv[0]);
-+ if (allowed != TRUE) {
-+ /* If foreign addresses (i.e. IP addresses that do not match the
-+ * control connection's remote IP address) are not allowed, we
-+ * need to see just what our remote address IS.
- */
-- pr_log_pri(PR_LOG_DEBUG, "rejecting passive connection; "
-- "failed to get address of remote peer: %s", strerror(errno));
-- (void) close(fd);
-- continue;
-- }
-
-- if (pr_netaddr_cmp(&na, c->remote_addr) != 0) {
-- pr_log_pri(PR_LOG_NOTICE, "SECURITY VIOLATION: Passive connection "
-- "from foreign IP address %s rejected (does not match client "
-- "IP address %s).", pr_netaddr_get_ipstr(&na),
-- pr_netaddr_get_ipstr(c->remote_addr));
-- (void) close(fd);
-- continue;
-+ if (getpeername(fd, pr_netaddr_get_sockaddr(&na), &nalen) < 0) {
-+ /* If getpeername(2) fails, should we still allow this connection?
-+ * Caution (and the AllowForeignAddress setting) say "no".
-+ */
-+ pr_log_pri(PR_LOG_DEBUG, "rejecting passive connection; "
-+ "failed to get address of remote peer: %s", strerror(errno));
-+ (void) close(fd);
-+ continue;
-+ }
-+
-+ if (allowed == FALSE) {
-+ if (pr_netaddr_cmp(&na, c->remote_addr) != 0) {
-+ pr_log_pri(PR_LOG_NOTICE, "SECURITY VIOLATION: Passive connection "
-+ "from foreign IP address %s rejected (does not match client "
-+ "IP address %s).", pr_netaddr_get_ipstr(&na),
-+ pr_netaddr_get_ipstr(c->remote_addr));
-+
-+ (void) close(fd);
-+ d->mode = CM_ERROR;
-+ d->xerrno = EACCES;
-+
-+ return NULL;
-+ }
-+
-+ } else {
-+ char *class_name;
-+ const pr_class_t *cls;
-+
-+ class_name = allow_foreign_addr_config->argv[1];
-+ cls = pr_class_find(class_name);
-+ if (cls != NULL) {
-+ if (pr_class_satisfied(p, cls, &na) != TRUE) {
-+ pr_log_debug(DEBUG8, "<Class> '%s' not satisfied by foreign "
-+ "address '%s'", class_name, pr_netaddr_get_ipstr(&na));
-+
-+ pr_log_pri(PR_LOG_NOTICE,
-+ "SECURITY VIOLATION: Passive connection from foreign IP "
-+ "address %s rejected (does not match <Class %s>).",
-+ pr_netaddr_get_ipstr(&na), class_name);
-+
-+ (void) close(fd);
-+ d->mode = CM_ERROR;
-+ d->xerrno = EACCES;
-+ return NULL;
-+ }
-+
-+ } else {
-+ pr_log_debug(DEBUG8, "<Class> '%s' not found for filtering "
-+ "AllowForeignAddress", class_name);
-+ }
-+ }
- }
- }
-
-diff --git a/tests/t/lib/ProFTPD/Tests/Config/AllowForeignAddress.pm b/tests/t/lib/ProFTPD/Tests/Config/AllowForeignAddress.pm
-index cd64b5578d..0ee36cbb4e 100644
---- a/tests/t/lib/ProFTPD/Tests/Config/AllowForeignAddress.pm
-+++ b/tests/t/lib/ProFTPD/Tests/Config/AllowForeignAddress.pm
-@@ -26,11 +26,16 @@ my $TESTS = {
- test_class => [qw(forking)],
- },
-
-- fxp_denied_by_class => {
-+ fxp_port_denied_by_class => {
- order => ++$order,
- test_class => [qw(forking)],
- },
-
-+ fxp_pasv_denied_by_class_issue1346 => {
-+ order => ++$order,
-+ test_class => [qw(bug forking)],
-+ },
-+
- fxp_allowed => {
- order => ++$order,
- test_class => [qw(forking)],
-@@ -41,11 +46,16 @@ my $TESTS = {
- test_class => [qw(forking)],
- },
-
-- fxp_allowed_by_class => {
-+ fxp_port_allowed_by_class => {
- order => ++$order,
- test_class => [qw(forking)],
- },
-
-+ fxp_pasv_allowed_by_class_issue1346 => {
-+ order => ++$order,
-+ test_class => [qw(bug forking)],
-+ },
-+
- fxp_allowed_2gb => {
- order => ++$order,
- test_class => [qw(forking)],
-@@ -353,7 +363,7 @@ sub fxp_denied_eprt {
- test_cleanup($setup->{log_file}, $ex);
- }
-
--sub fxp_denied_by_class {
-+sub fxp_port_denied_by_class {
- my $self = shift;
- my $tmpdir = $self->{tmpdir};
- my $setup = test_setup($tmpdir, 'config');
-@@ -519,6 +529,139 @@ EOC
- test_cleanup($setup->{log_file}, $ex);
- }
-
-+sub fxp_pasv_denied_by_class_issue1346 {
-+ my $self = shift;
-+ my $tmpdir = $self->{tmpdir};
-+ my $setup = test_setup($tmpdir, 'config');
-+
-+ my $class_name = 'allowed_fxp';
-+
-+ my $config = {
-+ PidFile => $setup->{pid_file},
-+ ScoreboardFile => $setup->{scoreboard_file},
-+ SystemLog => $setup->{log_file},
-+
-+ AuthUserFile => $setup->{auth_user_file},
-+ AuthGroupFile => $setup->{auth_group_file},
-+
-+ AllowForeignAddress => $class_name,
-+
-+ IfModules => {
-+ 'mod_delay.c' => {
-+ DelayEngine => 'off',
-+ },
-+ },
-+ };
-+
-+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
-+ $config);
-+
-+ if (open(my $fh, ">> $setup->{config_file}")) {
-+ print $fh <<EOC;
-+<Class $class_name>
-+ From none
-+</Class>
-+EOC
-+ unless (close($fh)) {
-+ die("Can't write $setup->{config_file}: $!");
-+ }
-+
-+ } else {
-+ die("Can't open $setup->{config_file}: $!");
-+ }
-+
-+ # Open pipes, for use between the parent and child processes. Specifically,
-+ # the child will indicate when it's done with its test by writing a message
-+ # to the parent.
-+ my ($rfh, $wfh);
-+ unless (pipe($rfh, $wfh)) {
-+ die("Can't open pipe: $!");
-+ }
-+
-+ my $ex;
-+
-+ # Fork child
-+ $self->handle_sigchld();
-+ defined(my $pid = fork()) or die("Can't fork: $!");
-+ if ($pid) {
-+ eval {
-+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 3);
-+ $client->login($setup->{user}, $setup->{passwd});
-+
-+ # Attemping a data transfer should fail, due to the AllowForeignAddress
-+ # class restriction.
-+
-+ my $conn = $client->list_raw();
-+ if ($conn) {
-+ die("LIST succeeded unexpectedly");
-+ }
-+
-+ my $resp_code = $client->response_code();
-+ my $resp_msg = $client->response_msg();
-+
-+ my $expected = 425;
-+ $self->assert($expected == $resp_code,
-+ "Expected response code $expected, got $resp_code");
-+
-+ $expected = 'Unable to build data connection:';
-+ $self->assert(qr/$expected/, $resp_msg,
-+ "Expected response message '$expected', got '$resp_msg'");
-+
-+ $client->quit();
-+ };
-+ if ($@) {
-+ $ex = $@;
-+ }
-+
-+ $wfh->print("done\n");
-+ $wfh->flush();
-+
-+ } else {
-+ eval { server_wait($setup->{config_file}, $rfh) };
-+ if ($@) {
-+ warn($@);
-+ exit 1;
-+ }
-+
-+ exit 0;
-+ }
-+
-+ # Stop server
-+ server_stop($setup->{pid_file});
-+ $self->assert_child_ok($pid);
-+
-+ eval {
-+ if (open(my $fh, "< $setup->{log_file}")) {
-+ my $ok = 0;
-+
-+ while (my $line = <$fh>) {
-+ chomp($line);
-+
-+ if ($ENV{TEST_VERBOSE}) {
-+ print STDERR "$line\n";
-+ }
-+
-+ if ($line =~ /SECURITY VIOLATION: Passive connection from foreign IP address \S+ rejected \(does not match <Class \S+>\)/) {
-+ $ok = 1;
-+ last;
-+ }
-+ }
-+
-+ close($fh);
-+
-+ $self->assert($ok, "Did not see expected log messages");
-+
-+ } else {
-+ die("Can't read $setup->{log_file}: $!");
-+ }
-+ };
-+ if ($@) {
-+ $ex = $@;
-+ }
-+
-+ test_cleanup($setup->{log_file}, $ex);
-+}
-+
- sub fxp_allowed {
- my $self = shift;
- my $tmpdir = $self->{tmpdir};
-@@ -781,7 +924,7 @@ sub fxp_allowed_eprt {
- test_cleanup($setup->{log_file}, $ex);
- }
-
--sub fxp_allowed_by_class {
-+sub fxp_port_allowed_by_class {
- my $self = shift;
- my $tmpdir = $self->{tmpdir};
- my $setup = test_setup($tmpdir, 'config');
-@@ -926,6 +1069,110 @@ EOC
- test_cleanup($setup->{log_file}, $ex);
- }
-
-+sub fxp_pasv_allowed_by_class_issue1346 {
-+ my $self = shift;
-+ my $tmpdir = $self->{tmpdir};
-+ my $setup = test_setup($tmpdir, 'config');
-+
-+ my $class_name = 'allowed_fxp';
-+
-+ my $config = {
-+ PidFile => $setup->{pid_file},
-+ ScoreboardFile => $setup->{scoreboard_file},
-+ SystemLog => $setup->{log_file},
-+ TraceLog => $setup->{log_file},
-+ Trace => 'class:20 inet:20',
-+
-+ AuthUserFile => $setup->{auth_user_file},
-+ AuthGroupFile => $setup->{auth_group_file},
-+
-+ AllowForeignAddress => $class_name,
-+
-+ IfModules => {
-+ 'mod_delay.c' => {
-+ DelayEngine => 'off',
-+ },
-+ },
-+ };
-+
-+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
-+ $config);
-+
-+ if (open(my $fh, ">> $setup->{config_file}")) {
-+ print $fh <<EOC;
-+<Class $class_name>
-+ From 127.0.0.0/8
-+</Class>
-+EOC
-+ unless (close($fh)) {
-+ die("Can't write $setup->{config_file}: $!");
-+ }
-+
-+ } else {
-+ die("Can't open $setup->{config_file}: $!");
-+ }
-+
-+ # Open pipes, for use between the parent and child processes. Specifically,
-+ # the child will indicate when it's done with its test by writing a message
-+ # to the parent.
-+ my ($rfh, $wfh);
-+ unless (pipe($rfh, $wfh)) {
-+ die("Can't open pipe: $!");
-+ }
-+
-+ my $ex;
-+
-+ # Fork child
-+ $self->handle_sigchld();
-+ defined(my $pid = fork()) or die("Can't fork: $!");
-+ if ($pid) {
-+ eval {
-+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 3);
-+ $client->login($setup->{user}, $setup->{passwd});
-+
-+ # Attemping a data transfer should succeed, due to the AllowForeignAddress
-+ # class restriction.
-+ my $conn = $client->list_raw();
-+ unless ($conn) {
-+ die("Failed to LIST: " . $client->response_code() . " " .
-+ $client->response_msg());
-+ }
-+
-+ my $buf;
-+ $conn->read($buf, 8192, 30);
-+ eval { $conn->close() };
-+
-+ my ($resp_code, $resp_msg);
-+ $resp_code = $client->response_code();
-+ $resp_msg = $client->response_msg();
-+
-+ $self->assert_transfer_ok($resp_code, $resp_msg);
-+ $client->quit();
-+ };
-+ if ($@) {
-+ $ex = $@;
-+ }
-+
-+ $wfh->print("done\n");
-+ $wfh->flush();
-+
-+ } else {
-+ eval { server_wait($setup->{config_file}, $rfh) };
-+ if ($@) {
-+ warn($@);
-+ exit 1;
-+ }
-+
-+ exit 0;
-+ }
-+
-+ # Stop server
-+ server_stop($setup->{pid_file});
-+ $self->assert_child_ok($pid);
-+
-+ test_cleanup($setup->{log_file}, $ex);
-+}
-+
- sub fxp_allowed_2gb {
- my $self = shift;
- my $tmpdir = $self->{tmpdir};
=====================================
debian/patches/upstream_1450.diff deleted
=====================================
@@ -1,557 +0,0 @@
-From 8aa39b27d8fd6ada556b51c4547a504956474078 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Mon, 9 May 2022 17:49:08 -0700
-Subject: [PATCH] Issue #1448: Backporting the mod_sftp/OpenSSL 3.x fixes to
- the 1.3.7 branch.
-
----
- NEWS | 4 ++
- RELEASE_NOTES | 6 ++
- contrib/mod_sftp/cipher.c | 79 ++++++++++++++++++---
- contrib/mod_sftp/configure | 123 +++++++++++++++++++++++++++++++++
- contrib/mod_sftp/configure.in | 74 +++++++++++++++++++-
- contrib/mod_sftp/crypto.c | 14 +++-
- contrib/mod_sftp/keys.c | 4 +-
- contrib/mod_sftp/mod_sftp.c | 20 +++++-
- contrib/mod_sftp/mod_sftp.h.in | 14 +++-
- 9 files changed, 324 insertions(+), 14 deletions(-)
-
-diff --git a/NEWS b/NEWS
-index 52d4b58c94..6cf27d97ff 100644
---- a/NEWS
-+++ b/NEWS
-@@ -15,6 +15,10 @@
- where `N' is the issue number.
- -----------------------------------------------------------------------------
-
-+1.3.7e
-+--------------------------------
-+- Issue 1448 - Ensure that mod_sftp algorithms work properly with OpenSSL 3.x.
-+
- 1.3.7d - Released 23-Apr-2022
- --------------------------------
- - Issue 1321 - Crash with long lines in AuthGroupFile due to large realloc(3).
-diff --git a/RELEASE_NOTES b/RELEASE_NOTES
-index 7c274a01f6..ea583ca079 100644
---- a/RELEASE_NOTES
-+++ b/RELEASE_NOTES
-@@ -6,6 +6,12 @@ This file contains a description of the major changes to ProFTPD for the
- releases. More information on these changes can be found in the NEWS and
- ChangeLog files.
-
-+1.3.7e
-+---------
-+
-+ + Ensure that mod_sftp algorithms work properly when OpenSSL 3.x is used.
-+
-+
- 1.3.7d
- ---------
-
-diff --git a/contrib/mod_sftp/cipher.c b/contrib/mod_sftp/cipher.c
-index 77c79e0672..57d4c2f996 100644
---- a/contrib/mod_sftp/cipher.c
-+++ b/contrib/mod_sftp/cipher.c
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - mod_sftp ciphers
-- * Copyright (c) 2008-2020 TJ Saunders
-+ * Copyright (c) 2008-2022 TJ Saunders
- *
- * 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
-@@ -192,14 +192,40 @@ static int set_cipher_iv(struct sftp_cipher *cipher, const EVP_MD *hash,
- }
-
- ctx = EVP_MD_CTX_create();
-- EVP_DigestInit(ctx, hash);
-+ if (EVP_DigestInit(ctx, hash) != 1) {
-+ (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-+ "unable to initialize MD context for '%s': %s", EVP_MD_name(hash),
-+ sftp_crypto_get_errors());
-+ free(iv);
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
- if (sftp_interop_supports_feature(SFTP_SSH2_FEAT_CIPHER_USE_K)) {
- EVP_DigestUpdate(ctx, k, klen);
- }
-- EVP_DigestUpdate(ctx, h, hlen);
-+
-+ if (EVP_DigestUpdate(ctx, h, hlen) != 1) {
-+ (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-+ "unable to update MD context for '%s': %s", EVP_MD_name(hash),
-+ sftp_crypto_get_errors());
-+ free(iv);
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
- EVP_DigestUpdate(ctx, letter, sizeof(char));
- EVP_DigestUpdate(ctx, (char *) id, id_len);
-- EVP_DigestFinal(ctx, iv, &iv_len);
-+
-+ if (EVP_DigestFinal(ctx, iv, &iv_len) != 1) {
-+ (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-+ "unable to finish MD context for '%s': %s", EVP_MD_name(hash),
-+ sftp_crypto_get_errors());
-+ free(iv);
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
- EVP_MD_CTX_destroy(ctx);
-
- /* If we need more, keep hashing, as per RFC, until we have enough
-@@ -264,12 +290,37 @@ static int set_cipher_key(struct sftp_cipher *cipher, const EVP_MD *hash,
- }
-
- ctx = EVP_MD_CTX_create();
-- EVP_DigestInit(ctx, hash);
-- EVP_DigestUpdate(ctx, k, klen);
-+ if (EVP_DigestInit(ctx, hash) != 1) {
-+ (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-+ "unable to initialize MD context for '%s': %s", EVP_MD_name(hash),
-+ sftp_crypto_get_errors());
-+ free(key);
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
-+ if (EVP_DigestUpdate(ctx, k, klen) != 1) {
-+ (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-+ "unable to update MD context for '%s': %s", EVP_MD_name(hash),
-+ sftp_crypto_get_errors());
-+ free(key);
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
- EVP_DigestUpdate(ctx, h, hlen);
- EVP_DigestUpdate(ctx, letter, sizeof(char));
- EVP_DigestUpdate(ctx, (char *) id, id_len);
-- EVP_DigestFinal(ctx, key, &key_len);
-+
-+ if (EVP_DigestFinal(ctx, key, &key_len) != 1) {
-+ (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
-+ "unable to finish MD context for '%s': %s", EVP_MD_name(hash),
-+ sftp_crypto_get_errors());
-+ free(key);
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
- EVP_MD_CTX_destroy(ctx);
-
- pr_trace_msg(trace_channel, 19, "hashed data to produce key (%lu bytes)",
-@@ -507,7 +558,19 @@ int sftp_cipher_set_read_key(pool *p, const EVP_MD *hash, const BIGNUM *k,
- }
-
- pr_memscrub(ptr, bufsz);
-- sftp_cipher_set_block_size(EVP_CIPHER_block_size(cipher->cipher));
-+
-+ if (strcmp(cipher->algo, "aes128-ctr") == 0 ||
-+ strcmp(cipher->algo, "aes192-ctr") == 0 ||
-+ strcmp(cipher->algo, "aes256-ctr") == 0) {
-+ /* For some reason, OpenSSL returns 8 for the AES block size (even
-+ * though the AES block size is 16, per RFC 5647), but OpenSSH wants 16.
-+ */
-+ sftp_cipher_set_block_size(16);
-+
-+ } else {
-+ sftp_cipher_set_block_size(EVP_CIPHER_block_size(cipher->cipher));
-+ }
-+
- return 0;
- }
-
-diff --git a/contrib/mod_sftp/configure b/contrib/mod_sftp/configure
-index f0cd88d445..0907fdbd14 100755
---- a/contrib/mod_sftp/configure
-+++ b/contrib/mod_sftp/configure
-@@ -3865,6 +3865,88 @@ $as_echo "no" >&6; }
- LIBS="$saved_libs"
-
-
-+fi
-+rm -f core conftest.err conftest.$ac_objext \
-+ conftest$ac_exeext conftest.$ac_ext
-+
-+LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
-+LIBS="-lcrypto $LIBS"
-+
-+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL supports EVP_aes_128_ctr" >&5
-+$as_echo_n "checking whether OpenSSL supports EVP_aes_128_ctr... " >&6; }
-+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-+/* end confdefs.h. */
-+
-+ #include <openssl/evp.h>
-+
-+int
-+main ()
-+{
-+
-+ EVP_CIPHER *cipher;
-+ cipher = EVP_aes_128_ctr();
-+
-+ ;
-+ return 0;
-+}
-+_ACEOF
-+if ac_fn_c_try_link "$LINENO"; then :
-+
-+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-+$as_echo "yes" >&6; }
-+
-+$as_echo "#define HAVE_EVP_AES_128_CTR_OPENSSL 1" >>confdefs.h
-+
-+ LIBS="$saved_libs"
-+
-+else
-+
-+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-+$as_echo "no" >&6; }
-+ LIBS="$saved_libs"
-+
-+
-+fi
-+rm -f core conftest.err conftest.$ac_objext \
-+ conftest$ac_exeext conftest.$ac_ext
-+
-+LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
-+LIBS="-lcrypto $LIBS"
-+
-+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL supports EVP_aes_192_ctr" >&5
-+$as_echo_n "checking whether OpenSSL supports EVP_aes_192_ctr... " >&6; }
-+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-+/* end confdefs.h. */
-+
-+ #include <openssl/evp.h>
-+
-+int
-+main ()
-+{
-+
-+ EVP_CIPHER *cipher;
-+ cipher = EVP_aes_192_ctr();
-+
-+ ;
-+ return 0;
-+}
-+_ACEOF
-+if ac_fn_c_try_link "$LINENO"; then :
-+
-+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-+$as_echo "yes" >&6; }
-+
-+$as_echo "#define HAVE_EVP_AES_192_CTR_OPENSSL 1" >>confdefs.h
-+
-+ LIBS="$saved_libs"
-+
-+else
-+
-+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-+$as_echo "no" >&6; }
-+ LIBS="$saved_libs"
-+
-+
- fi
- rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-@@ -3906,6 +3988,47 @@ $as_echo "no" >&6; }
- LIBS="$saved_libs"
-
-
-+fi
-+rm -f core conftest.err conftest.$ac_objext \
-+ conftest$ac_exeext conftest.$ac_ext
-+
-+LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
-+LIBS="-lcrypto $LIBS"
-+
-+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL supports OSSL_PROVIDER_load" >&5
-+$as_echo_n "checking whether OpenSSL supports OSSL_PROVIDER_load... " >&6; }
-+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-+/* end confdefs.h. */
-+
-+ #include <openssl/provider.h>
-+
-+int
-+main ()
-+{
-+
-+ OSSL_PROVIDER *provider;
-+ provider = OSSL_PROVIDER_load(NULL, "default");
-+
-+ ;
-+ return 0;
-+}
-+_ACEOF
-+if ac_fn_c_try_link "$LINENO"; then :
-+
-+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-+$as_echo "yes" >&6; }
-+
-+$as_echo "#define HAVE_OSSL_PROVIDER_LOAD_OPENSSL 1" >>confdefs.h
-+
-+ LIBS="$saved_libs"
-+
-+else
-+
-+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-+$as_echo "no" >&6; }
-+ LIBS="$saved_libs"
-+
-+
- fi
- rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-diff --git a/contrib/mod_sftp/configure.in b/contrib/mod_sftp/configure.in
-index b45d434fec..690efef3da 100644
---- a/contrib/mod_sftp/configure.in
-+++ b/contrib/mod_sftp/configure.in
-@@ -1,5 +1,5 @@
- dnl ProFTPD - mod_sftp
--dnl Copyright (c) 2012-2019 TJ Saunders <tj at castaglia.org>
-+dnl Copyright (c) 2012-2022 TJ Saunders <tj at castaglia.org>
- dnl
- dnl This program is free software; you can redistribute it and/or modify
- dnl it under the terms of the GNU General Public License as published by
-@@ -206,6 +206,54 @@ dnl Splice out -lsupp, since that library hasn't been built yet
- LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
- LIBS="-lcrypto $LIBS"
-
-+AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_128_ctr])
-+AC_TRY_LINK(
-+ [
-+ #include <openssl/evp.h>
-+ ],
-+ [
-+ EVP_CIPHER *cipher;
-+ cipher = EVP_aes_128_ctr();
-+ ],
-+ [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_EVP_AES_128_CTR_OPENSSL, 1, [OpenSSL supports EVP_aes_128_ctr])
-+ LIBS="$saved_libs"
-+ ],
-+ [
-+ AC_MSG_RESULT(no)
-+ LIBS="$saved_libs"
-+ ]
-+)
-+
-+dnl Splice out -lsupp, since that library hasn't been built yet
-+LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
-+LIBS="-lcrypto $LIBS"
-+
-+AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_192_ctr])
-+AC_TRY_LINK(
-+ [
-+ #include <openssl/evp.h>
-+ ],
-+ [
-+ EVP_CIPHER *cipher;
-+ cipher = EVP_aes_192_ctr();
-+ ],
-+ [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_EVP_AES_192_CTR_OPENSSL, 1, [OpenSSL supports EVP_aes_192_ctr])
-+ LIBS="$saved_libs"
-+ ],
-+ [
-+ AC_MSG_RESULT(no)
-+ LIBS="$saved_libs"
-+ ]
-+)
-+
-+dnl Splice out -lsupp, since that library hasn't been built yet
-+LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
-+LIBS="-lcrypto $LIBS"
-+
- AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_256_ctr])
- AC_TRY_LINK(
- [
-@@ -226,6 +274,30 @@ AC_TRY_LINK(
- ]
- )
-
-+dnl Splice out -lsupp, since that library hasn't been built yet
-+LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
-+LIBS="-lcrypto $LIBS"
-+
-+AC_MSG_CHECKING([whether OpenSSL supports OSSL_PROVIDER_load])
-+AC_TRY_LINK(
-+ [
-+ #include <openssl/provider.h>
-+ ],
-+ [
-+ OSSL_PROVIDER *provider;
-+ provider = OSSL_PROVIDER_load(NULL, "default");
-+ ],
-+ [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_OSSL_PROVIDER_LOAD_OPENSSL, 1, [OpenSSL supports OSSL_PROVIDER_load])
-+ LIBS="$saved_libs"
-+ ],
-+ [
-+ AC_MSG_RESULT(no)
-+ LIBS="$saved_libs"
-+ ]
-+)
-+
- LIBS="$saved_libs"
-
- INCLUDES="$ac_build_addl_includes"
-diff --git a/contrib/mod_sftp/crypto.c b/contrib/mod_sftp/crypto.c
-index e9d776bcde..3ff94d4b3e 100644
---- a/contrib/mod_sftp/crypto.c
-+++ b/contrib/mod_sftp/crypto.c
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - mod_sftp OpenSSL interface
-- * Copyright (c) 2008-2017 TJ Saunders
-+ * Copyright (c) 2008-2022 TJ Saunders
- *
- * 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
-@@ -983,13 +983,25 @@ const EVP_CIPHER *sftp_crypto_get_cipher(const char *name, size_t *key_len,
- # endif /* !OPENSSL_NO_DES */
-
- } else if (strncmp(name, "aes256-ctr", 11) == 0) {
-+# if defined(HAVE_EVP_AES_256_CTR_OPENSSL)
-+ cipher = EVP_aes_256_ctr();
-+# else
- cipher = get_aes_ctr_cipher(32);
-+# endif /* HAVE_EVP_AES_256_CTR_OPENSSL */
-
- } else if (strncmp(name, "aes192-ctr", 11) == 0) {
-+# if defined(HAVE_EVP_AES_192_CTR_OPENSSL)
-+ cipher = EVP_aes_192_ctr();
-+# else
- cipher = get_aes_ctr_cipher(24);
-+# endif /* HAVE_EVP_AES_192_CTR_OPENSSL */
-
- } else if (strncmp(name, "aes128-ctr", 11) == 0) {
-+# if defined(HAVE_EVP_AES_128_CTR_OPENSSL)
-+ cipher = EVP_aes_128_ctr();
-+# else
- cipher = get_aes_ctr_cipher(16);
-+# endif /* HAVE_EVP_AES_128_CTR_OPENSSL */
- #endif /* OpenSSL older than 0.9.7 */
-
- } else {
-diff --git a/contrib/mod_sftp/keys.c b/contrib/mod_sftp/keys.c
-index c6b88cf4de..54f19321db 100644
---- a/contrib/mod_sftp/keys.c
-+++ b/contrib/mod_sftp/keys.c
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - mod_sftp key mgmt (keys)
-- * Copyright (c) 2008-2021 TJ Saunders
-+ * Copyright (c) 2008-2022 TJ Saunders
- *
- * 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
-@@ -2903,7 +2903,7 @@ static int decrypt_openssh_data(pool *p, const char *path,
- * trailing AEAD bytes. Need to fix that in the future.
- */
-
-- if (EVP_Cipher(cipher_ctx, buf, encrypted_data, encrypted_len) != 1) {
-+ if (EVP_Cipher(cipher_ctx, buf, encrypted_data, encrypted_len) < 0) {
- /* This might happen due to a wrong/bad passphrase. */
- pr_trace_msg(trace_channel, 3,
- "error decrypting %s data for key: %s", cipher->algo,
-diff --git a/contrib/mod_sftp/mod_sftp.c b/contrib/mod_sftp/mod_sftp.c
-index b84b1a77b6..f53407e88e 100644
---- a/contrib/mod_sftp/mod_sftp.c
-+++ b/contrib/mod_sftp/mod_sftp.c
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - mod_sftp
-- * Copyright (c) 2008-2020 TJ Saunders
-+ * Copyright (c) 2008-2022 TJ Saunders
- *
- * 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
-@@ -72,6 +72,10 @@ static const char *sftp_server_version = SFTP_ID_DEFAULT_STRING;
- #define SFTP_HOSTKEY_FL_CLEAR_ECDSA_KEY 0x004
- #define SFTP_HOSTKEY_FL_CLEAR_ED25519_KEY 0x008
-
-+#if defined(HAVE_OSSL_PROVIDER_LOAD_OPENSSL)
-+static OSSL_PROVIDER *legacy_provider = NULL;
-+#endif /* HAVE_OSSL_PROVIDER_LOAD_OPENSSL */
-+
- static const char *trace_channel = "ssh2";
-
- static int sftp_have_authenticated(cmd_rec *cmd) {
-@@ -1881,6 +1885,13 @@ static void sftp_shutdown_ev(const void *event_data, void *user_data) {
- /* Clean up the OpenSSL stuff. */
- sftp_crypto_free(0);
-
-+#if defined(HAVE_OSSL_PROVIDER_LOAD_OPENSSL)
-+ if (legacy_provider != NULL) {
-+ OSSL_PROVIDER_unload(legacy_provider);
-+ legacy_provider = NULL;
-+ }
-+#endif /* HAVE_OSSL_PROVIDER_LOAD_OPENSSL */
-+
- destroy_pool(sftp_pool);
- sftp_pool = NULL;
-
-@@ -2035,6 +2046,13 @@ static int sftp_init(void) {
- }
- #endif /* HAVE_SODIUM_H */
-
-+#if defined(HAVE_OSSL_PROVIDER_LOAD_OPENSSL)
-+ /* Load the "legacy" OpenSSL algorithm provider, for those SSH algorithms
-+ * that require support of algorithms that OpenSSL deemed "legacy".
-+ */
-+ legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
-+#endif /* HAVE_OSSL_PROVIDER_LOAD_OPENSSL */
-+
- sftp_keystore_init();
- sftp_cipher_init();
- sftp_mac_init();
-diff --git a/contrib/mod_sftp/mod_sftp.h.in b/contrib/mod_sftp/mod_sftp.h.in
-index 065981c313..9af590e8e3 100644
---- a/contrib/mod_sftp/mod_sftp.h.in
-+++ b/contrib/mod_sftp/mod_sftp.h.in
-@@ -1,6 +1,6 @@
- /*
- * ProFTPD - mod_sftp
-- * Copyright (c) 2008-2020 TJ Saunders
-+ * Copyright (c) 2008-2022 TJ Saunders
- *
- * 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
-@@ -49,9 +49,18 @@
- /* Define if you have OpenSSL with crippled AES support. */
- #undef HAVE_AES_CRIPPLED_OPENSSL
-
-+/* Define if you have OpenSSL with EVP_aes_128_ctr support. */
-+#undef HAVE_EVP_AES_128_CTR_OPENSSL
-+
-+/* Define if you have OpenSSL with EVP_aes_192_ctr support. */
-+#undef HAVE_EVP_AES_192_CTR_OPENSSL
-+
- /* Define if you have OpenSSL with EVP_aes_256_ctr support. */
- #undef HAVE_EVP_AES_256_CTR_OPENSSL
-
-+/* Define if you have OpenSSL with OSSL_PROVIDER_load support. */
-+#undef HAVE_OSSL_PROVIDER_LOAD_OPENSSL
-+
- /* Define if you have OpenSSL with SHA256 support. */
- #undef HAVE_SHA256_OPENSSL
-
-@@ -93,6 +102,9 @@
- # include <openssl/ec.h>
- # include <openssl/ecdh.h>
- #endif /* PR_USE_OPENSSL_ECC */
-+#if defined(HAVE_OSSL_PROVIDER_LOAD_OPENSSL)
-+# include <openssl/provider.h>
-+#endif /* HAVE_OSSL_PROVIDER_LOAD_OPENSSL */
-
- /* Define if you have the LibreSSL library. */
- #if defined(LIBRESSL_VERSION_NUMBER)
=====================================
debian/patches/upstream_long_AuthGroupFile_lines deleted
=====================================
@@ -1,187 +0,0 @@
-From 9aff151f6810b8f0e64cc9f7e15dd21ebecd4cc3 Mon Sep 17 00:00:00 2001
-From: TJ Saunders <tj at castaglia.org>
-Date: Fri, 28 Jan 2022 08:21:44 -0800
-Subject: [PATCH] Backporting buffering fixes when parsing long `AuthGroupFile`
- lines.
-
----
- modules/mod_auth_file.c | 87 ++++++++++++++++++++++++++++++++---------
- 1 file changed, 68 insertions(+), 19 deletions(-)
-
-diff --git a/modules/mod_auth_file.c b/modules/mod_auth_file.c
-index b1ccaa771..3530905f1 100644
---- a/modules/mod_auth_file.c
-+++ b/modules/mod_auth_file.c
-@@ -1,7 +1,7 @@
- /*
- * ProFTPD: mod_auth_file - file-based authentication module that supports
- * restrictions on the file contents
-- * Copyright (c) 2002-2021 The ProFTPD Project team
-+ * Copyright (c) 2002-2022 The ProFTPD Project team
- *
- * 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
-@@ -325,24 +325,35 @@ static struct passwd *af_getpasswd(const char *buf, unsigned int lineno) {
- #define NGRPFIELDS 4
-
- static char *grpbuf = NULL;
-+static size_t grpbufsz = 0;
- static struct group grent;
- static char *grpfields[NGRPFIELDS];
- static char *members[MAXMEMBERS+1];
-
--static char *af_getgrentline(char **buf, int *buflen, pr_fh_t *fh,
-+static char *af_getgrentline(char **buf, size_t *bufsz, pr_fh_t *fh,
- unsigned int *lineno) {
-- char *cp = *buf;
-- int original_buflen;
-+ char *ptr, *res;
-+ size_t original_bufsz, buflen;
-
-- original_buflen = *buflen;
-+ original_bufsz = *bufsz;
-+ buflen = *bufsz;
-
-- while (pr_fsio_gets(cp, (*buflen) - (cp - *buf), fh) != NULL) {
-- pr_signals_handle();
-+ /* Try to keep our unfilled buffer zeroed out, so that strlen(3) et al
-+ * work as expected.
-+ */
-+ memset(*buf, '\0', *bufsz);
-
-- (*lineno)++;
-+ ptr = *buf;
-+ res = pr_fsio_gets(ptr, buflen, fh);
-+ while (res != NULL) {
-+ pr_signals_handle();
-
- /* Is this a full line? */
-- if (strchr(cp, '\n')) {
-+ if (strchr(*buf, '\n') != NULL) {
-+ pr_trace_msg(trace_channel, 25,
-+ "found LF, returning line: '%s' (%lu bytes)", *buf,
-+ (unsigned long) strlen(*buf));
-+ (*lineno)++;
- return *buf;
- }
-
-@@ -351,26 +362,37 @@ static char *af_getgrentline(char **buf, int *buflen, pr_fh_t *fh,
- * allocated buffer by the original buffer length each time. So we
- * do the same (Issue #1321).
- */
-- *buflen += original_buflen;
--
- {
-+ size_t new_bufsz;
- char *new_buf;
-
-- new_buf = realloc(*buf, *buflen);
-+ pr_trace_msg(trace_channel, 25, "getgrentline() buffer (%lu bytes): "
-+ "'%.*s'", (unsigned long) *bufsz, (int) *bufsz, *buf);
-+
-+ pr_trace_msg(trace_channel, 19,
-+ "no LF found in group line, increasing buffer (%lu bytes) by %lu bytes",
-+ (unsigned long) *bufsz, (unsigned long) original_bufsz);
-+ new_bufsz = *bufsz + original_bufsz;
-+
-+ new_buf = realloc(*buf, new_bufsz);
- if (new_buf == NULL) {
- break;
- }
-
-+ ptr = new_buf + *bufsz;
- *buf = new_buf;
-+ *bufsz = new_bufsz;
-+ buflen = original_bufsz;
-+
-+ memset(ptr, '\0', buflen);
- }
-
-- cp = *buf + (cp - *buf);
-- cp = strchr(cp, '\0');
-+ res = pr_fsio_gets(ptr, buflen, fh);
- }
-
- free(*buf);
- *buf = NULL;
-- *buflen = 0;
-+ *bufsz = 0;
-
- return NULL;
- }
-@@ -401,22 +423,29 @@ static struct group *af_getgrp(const char *buf, unsigned int lineno) {
-
- i = strlen(buf) + 1;
-
-- if (!grpbuf) {
-+ if (grpbuf == NULL) {
-+ grpbufsz = i;
- grpbuf = malloc(i);
-
-- } else {
-+ } else if (grpbufsz < (size_t) i) {
- char *new_buf;
-
-+ pr_trace_msg(trace_channel, 19,
-+ "parsing group line '%s' (%lu bytes), allocating %lu bytes via "
-+ "realloc(3)", buf, (unsigned long) i, (unsigned long) i);
-+
- new_buf = realloc(grpbuf, i);
- if (new_buf == NULL) {
- return NULL;
- }
-
- grpbuf = new_buf;
-+ grpbufsz = i;
- }
-
-- if (!grpbuf)
-+ if (grpbuf == NULL) {
- return NULL;
-+ }
-
- sstrncpy(grpbuf, buf, i);
-
-@@ -524,7 +553,16 @@ static struct group *af_getgrent(pool *p) {
-
- while (TRUE) {
- char *cp = NULL, *buf = NULL;
-- int buflen = PR_TUNABLE_BUFFER_SIZE;
-+ size_t buflen;
-+
-+ buflen = PR_TUNABLE_BUFFER_SIZE;
-+
-+ if (af_group_file->af_file_fh->fh_iosz > 0) {
-+ /* This aligns our group(5) buffer with the preferred filesystem read
-+ * block size.
-+ */
-+ buflen = af_group_file->af_file_fh->fh_iosz;
-+ }
-
- pr_signals_handle();
-
-@@ -533,6 +571,11 @@ static struct group *af_getgrent(pool *p) {
- pr_log_pri(PR_LOG_ALERT, "Out of memory!");
- _exit(1);
- }
-+
-+ pr_trace_msg(trace_channel, 19,
-+ "getgrent(3): allocated buffer %p (%lu bytes)", buf,
-+ (unsigned long) buflen);
-+
- grp = NULL;
-
- while (af_getgrentline(&buf, &buflen, af_group_file->af_file_fh,
-@@ -636,6 +679,12 @@ static int af_setgrent(pool *p) {
- pbuf->remaining = pbuf->buflen;
- }
-
-+ if (grpbuf != NULL) {
-+ free(grpbuf);
-+ grpbuf = NULL;
-+ }
-+ grpbufsz = 0;
-+
- return 0;
- }
-
View it on GitLab: https://salsa.debian.org/debian-proftpd-team/proftpd/-/commit/7c4d3644c46ff3922269b050d2456c366af1d021
--
View it on GitLab: https://salsa.debian.org/debian-proftpd-team/proftpd/-/commit/7c4d3644c46ff3922269b050d2456c366af1d021
You're receiving this email because of your account on salsa.debian.org.
More information about the Pkg-proftpd-maintainers
mailing list