[Git][debian-proftpd-team/proftpd][upstream] New upstream version 1.3.8.b+dfsg
Hilmar Preuße (@hilmar-guest)
gitlab at salsa.debian.org
Wed Dec 20 13:38:37 GMT 2023
Hilmar Preuße pushed to branch upstream at Debian ProFTPD Team / proftpd
Commits:
209e4d5c by Hilmar Preusse at 2023-12-20T10:10:20+00:00
New upstream version 1.3.8.b+dfsg
- - - - -
24 changed files:
- .github/workflows/ci.yml
- .github/workflows/rpm.yml
- NEWS
- README.md
- RELEASE_NOTES
- configure
- configure.in
- contrib/dist/rpm/proftpd.spec
- contrib/mod_digest.c
- contrib/mod_sftp/crypto.c
- contrib/mod_sftp/fxp.c
- contrib/mod_sftp/kex.c
- contrib/mod_sftp/keys.c
- contrib/mod_sftp/mac.c
- contrib/mod_sftp/mod_sftp.c
- contrib/mod_sftp/mod_sftp.h.in
- contrib/mod_sftp/packet.c
- contrib/mod_sftp/packet.h
- contrib/mod_sftp/tap.c
- contrib/mod_sftp/tap.h
- contrib/mod_tls.c
- doc/contrib/mod_sftp.html
- include/version.h
- tests/t/lib/ProFTPD/Tests/Modules/mod_sftp.pm
Changes:
=====================================
.github/workflows/ci.yml
=====================================
@@ -4,9 +4,19 @@ on:
push:
branches:
- 1.3.8
+ paths-ignore:
+ - NEWS
+ - RELEASE_NOTES
+ - '**/*.html'
+ - '**/*.md'
pull_request:
branches:
- 1.3.8
+ paths-ignore:
+ - NEWS
+ - RELEASE_NOTES
+ - '**/*.html'
+ - '**/*.md'
jobs:
build:
=====================================
.github/workflows/rpm.yml
=====================================
@@ -4,9 +4,19 @@ on:
push:
branches:
- 1.3.8
+ paths-ignore:
+ - NEWS
+ - RELEASE_NOTES
+ - '**/*.html'
+ - '**/*.md'
pull_request:
branches:
- 1.3.8
+ paths-ignore:
+ - NEWS
+ - RELEASE_NOTES
+ - '**/*.html'
+ - '**/*.md'
jobs:
build:
=====================================
NEWS
=====================================
@@ -15,6 +15,14 @@
where `N' is the issue number.
-----------------------------------------------------------------------------
+1.3.8b - Released 19-Dec-2023
+--------------------------------
+- Issue 1735 - Compiling ProFTPD 1.3.8a mod_sftp, mod_tls using libressl 3.7.3
+ fails.
+- Issue 1756 - Build system fails for specific module names.
+- Issue 1760 - mod_sftp is affected by "Terrapin" Prefix Truncation Attacks in
+ SSH Specification (CVE-2023-48795).
+
1.3.8a - Released 08-Oct-2023
--------------------------------
- Issue 1581 - mod_sftp fails to handle SFTP requests to truncate files to
=====================================
README.md
=====================================
@@ -8,7 +8,7 @@
[![Coverage Status](https://coveralls.io/repos/github/proftpd/proftpd/badge.svg?branch=master)](https://coveralls.io/github/proftpd/proftpd?branch=master)
[![Coverity Scan Status](https://scan.coverity.com/projects/198/badge.svg)](https://scan.coverity.com/projects/198)
[![C/C++ Language Grade](https://img.shields.io/lgtm/grade/cpp/g/proftpd/proftpd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/proftpd/proftpd/context:cpp)
-[![Release](https://img.shields.io/badge/release-1.3.8a-brightgreen)](https://github.com/proftpd/proftpd/releases/latest)
+[![Release](https://img.shields.io/badge/release-1.3.8b-brightgreen)](https://github.com/proftpd/proftpd/releases/latest)
[![License](https://img.shields.io/badge/license-GPL-brightgreen.svg)](https://img.shields.io/badge/license-GPL-brightgreen.svg)
## Introduction
=====================================
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.8b
+------
+
+ + Implemented mitigations for "Terrapin" SSH attack (CVE-2023-48795).
+
+
1.3.8a
------
=====================================
configure
=====================================
@@ -24090,12 +24090,13 @@ ac_static_module_dirs=
for amodule in $ac_shared_modules; do
module=`echo "$amodule" | sed -e 's/\.la//g'`.o;
+ modulename=`echo "$amodule" | sed -e 's/\.la$//'`;
- ac_core_modules=`echo "$ac_core_modules" | sed -e "s/$module//g"`;
- ac_build_core_modules=`echo "$ac_build_core_modules" | sed -e "s/modules\/$module//g"`;
+ ac_core_modules=`echo "$ac_core_modules" | sed -e "s/$modulename\.o//g"`;
+ ac_build_core_modules=`echo "$ac_build_core_modules" | sed -e "s/modules\/$modulename\.o//g"`;
- ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$module//g"`;
- ac_build_static_modules=`echo "$ac_build_static_modules" | sed -e "s/modules\/$module//g"`;
+ ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$modulename\.o//g"`;
+ ac_build_static_modules=`echo "$ac_build_static_modules" | sed -e "s/modules\/$modulename\.o//g"`;
done
GLUE_MODULE_OBJS="$ac_core_modules $ac_static_modules"
@@ -25418,33 +25419,39 @@ fi
for module in $ac_shared_modules ; do
moduledir=`echo "$module" | sed -e 's/\.la$//'`;
+ modulename=`echo "$module" | sed -e 's/\.la$//'`;
+ src=`echo "$module" | sed -e 's/\.o$//'`.c;
+ srcinc=`echo "$module" | sed -e 's/\.o$//'`.h;
if test -f $srcdir/modules/$src -o -f $srcdir/contrib/$src; then
continue
elif test -d $srcdir/modules/$moduledir; then
ac_shared_module_dirs="$ac_shared_module_dirs modules/$moduledir";
- ac_shared_modules=`echo "$ac_shared_modules" | sed -e "s/$module//"`
+ ac_shared_modules=`echo "$ac_shared_modules" | sed -e "s/$modulename\.la//"`
elif test -d $srcdir/contrib/$moduledir; then
ac_shared_module_dirs="$ac_shared_module_dirs contrib/$moduledir";
- ac_shared_modules=`echo "$ac_shared_modules" | sed -e "s/$module//"`
+ ac_shared_modules=`echo "$ac_shared_modules" | sed -e "s/$modulename\.la//"`
fi
done
for module in $ac_static_modules ; do
moduledir=`echo "$module" | sed -e 's/\.o$//'`;
+ modulename=`echo "$module" | sed -e 's/\.o$//'`;
+ src=`echo "$module" | sed -e 's/\.o$//'`.c;
+ srcinc=`echo "$module" | sed -e 's/\.o$//'`.h;
if test -f $srcdir/modules/$src -o -f $srcdir/contrib/$src; then
continue
elif test -d $srcdir/modules/$moduledir; then
ac_static_module_dirs="$ac_static_module_dirs modules/$moduledir";
- ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$module//"`
+ ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$modulename\.o//"`
elif test -d $srcdir/contrib/$moduledir; then
ac_static_module_dirs="$ac_static_module_dirs contrib/$moduledir";
- ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$module//"`
+ ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$modulename\.o//"`
addonlibs=""
src=`echo "$module" | sed -e 's/\.o$//'`.c;
@@ -25478,8 +25485,8 @@ for module in $ac_static_modules ; do
as_fn_error $? "specified archive '$thearch' does not match expected module archive name '$moduledir.a' -- aborting" "$LINENO" 5
fi
- ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$module//g"`
- ac_build_static_modules=`echo "$ac_build_static_modules" | sed -e "s/modules\/$module//g"`
+ ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$modulename\.o//g"`
+ ac_build_static_modules=`echo "$ac_build_static_modules" | sed -e "s/modules\/$modulename\.o//g"`
ac_build_static_module_archives="$ac_build_static_module_archives contrib/$moduledir/$thearch"
done
=====================================
configure.in
=====================================
@@ -3136,12 +3136,13 @@ dnl Remove any modules in the shared module list from the core and static
dnl module lists
for amodule in $ac_shared_modules; do
module=`echo "$amodule" | sed -e 's/\.la//g'`.o;
+ modulename=`echo "$amodule" | sed -e 's/\.la$//'`;
- ac_core_modules=`echo "$ac_core_modules" | sed -e "s/$module//g"`;
- ac_build_core_modules=`echo "$ac_build_core_modules" | sed -e "s/modules\/$module//g"`;
+ ac_core_modules=`echo "$ac_core_modules" | sed -e "s/$modulename\.o//g"`;
+ ac_build_core_modules=`echo "$ac_build_core_modules" | sed -e "s/modules\/$modulename\.o//g"`;
- ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$module//g"`;
- ac_build_static_modules=`echo "$ac_build_static_modules" | sed -e "s/modules\/$module//g"`;
+ ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$modulename\.o//g"`;
+ ac_build_static_modules=`echo "$ac_build_static_modules" | sed -e "s/modules\/$modulename\.o//g"`;
done
GLUE_MODULE_OBJS="$ac_core_modules $ac_static_modules"
@@ -3991,33 +3992,39 @@ fi
for module in $ac_shared_modules ; do
moduledir=`echo "$module" | sed -e 's/\.la$//'`;
+ modulename=`echo "$module" | sed -e 's/\.la$//'`;
+ src=`echo "$module" | sed -e 's/\.o$//'`.c;
+ srcinc=`echo "$module" | sed -e 's/\.o$//'`.h;
if test -f $srcdir/modules/$src -o -f $srcdir/contrib/$src; then
continue
elif test -d $srcdir/modules/$moduledir; then
ac_shared_module_dirs="$ac_shared_module_dirs modules/$moduledir";
- ac_shared_modules=`echo "$ac_shared_modules" | sed -e "s/$module//"`
+ ac_shared_modules=`echo "$ac_shared_modules" | sed -e "s/$modulename\.la//"`
elif test -d $srcdir/contrib/$moduledir; then
ac_shared_module_dirs="$ac_shared_module_dirs contrib/$moduledir";
- ac_shared_modules=`echo "$ac_shared_modules" | sed -e "s/$module//"`
+ ac_shared_modules=`echo "$ac_shared_modules" | sed -e "s/$modulename\.la//"`
fi
done
for module in $ac_static_modules ; do
moduledir=`echo "$module" | sed -e 's/\.o$//'`;
+ modulename=`echo "$module" | sed -e 's/\.o$//'`;
+ src=`echo "$module" | sed -e 's/\.o$//'`.c;
+ srcinc=`echo "$module" | sed -e 's/\.o$//'`.h;
if test -f $srcdir/modules/$src -o -f $srcdir/contrib/$src; then
continue
elif test -d $srcdir/modules/$moduledir; then
ac_static_module_dirs="$ac_static_module_dirs modules/$moduledir";
- ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$module//"`
+ ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$modulename\.o//"`
elif test -d $srcdir/contrib/$moduledir; then
ac_static_module_dirs="$ac_static_module_dirs contrib/$moduledir";
- ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$module//"`
+ ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$modulename\.o//"`
addonlibs=""
src=`echo "$module" | sed -e 's/\.o$//'`.c;
@@ -4053,8 +4060,8 @@ for module in $ac_static_modules ; do
AC_MSG_ERROR([specified archive '$thearch' does not match expected module archive name '$moduledir.a' -- aborting])
fi
- ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$module//g"`
- ac_build_static_modules=`echo "$ac_build_static_modules" | sed -e "s/modules\/$module//g"`
+ ac_static_modules=`echo "$ac_static_modules" | sed -e "s/$modulename\.o//g"`
+ ac_build_static_modules=`echo "$ac_build_static_modules" | sed -e "s/modules\/$modulename\.o//g"`
ac_build_static_module_archives="$ac_build_static_module_archives contrib/$moduledir/$thearch"
done
=====================================
contrib/dist/rpm/proftpd.spec
=====================================
@@ -53,7 +53,7 @@
# RHEL5 and clones don't have suitably recent versions of pcre/libmemcached
# so use --with rhel5 to inhibit those features when using --with everything
-%global proftpd_version 1.3.8a
+%global proftpd_version 1.3.8b
# rc_version should be incremented for each RC release, and reset back to 1
# AFTER each stable release.
@@ -61,7 +61,7 @@
# release_version should be incremented for each maint release, and reset back
# to 1 BEFORE starting new release cycle.
-%global release_version 2
+%global release_version 3
%if %(echo %{proftpd_version} | grep rc >/dev/null 2>&1 && echo 1 || echo 0)
%global rpm_version %(echo %{proftpd_version} | sed -e 's/rc.*//')
=====================================
contrib/mod_digest.c
=====================================
@@ -1,7 +1,7 @@
/*
* ProFTPD: mod_digest - File hashing/checksumming module
* Copyright (c) Mathias Berchtold <mb at smartftp.com>
- * Copyright (c) 2016-2022 TJ Saunders <tj at castaglia.org>
+ * Copyright (c) 2016-2023 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
@@ -321,12 +321,12 @@ static int CRC32_Free(CRC32_CTX *ctx) {
static int crc32_init(EVP_MD_CTX *ctx) {
void *md_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return CRC32_Init(md_data);
}
@@ -334,12 +334,12 @@ static int crc32_init(EVP_MD_CTX *ctx) {
static int crc32_update(EVP_MD_CTX *ctx, const void *data, size_t datasz) {
void *md_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return CRC32_Update(md_data, data, datasz);
}
@@ -347,12 +347,12 @@ static int crc32_update(EVP_MD_CTX *ctx, const void *data, size_t datasz) {
static int crc32_final(EVP_MD_CTX *ctx, unsigned char *md) {
void *md_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return CRC32_Final(md, md_data);
}
@@ -360,18 +360,18 @@ static int crc32_final(EVP_MD_CTX *ctx, unsigned char *md) {
static int crc32_free(EVP_MD_CTX *ctx) {
void *md_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return CRC32_Free(md_data);
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
static const EVP_MD crc32_md = {
NID_undef,
NID_undef,
@@ -386,13 +386,13 @@ static const EVP_MD crc32_md = {
CRC32_BLOCK,
sizeof(EVP_MD *) + sizeof(CRC32_CTX)
};
-#endif /* Older OpenSSLs */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
static const EVP_MD *EVP_crc32(void) {
EVP_MD *md;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
/* XXX TODO: At some point, we also need to call EVP_MD_meth_free() on
* this, to avoid a resource leak.
*/
@@ -407,7 +407,7 @@ static const EVP_MD *EVP_crc32(void) {
EVP_MD_meth_set_flags(md, 0);
#else
md = &crc32_md;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return md;
}
@@ -1039,9 +1039,9 @@ static int compute_digest(pool *p, const char *path, off_t start, off_t len,
unsigned char *buf;
size_t bufsz, readsz, iter_count;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
fh = pr_fsio_open(path, O_RDONLY);
@@ -1097,21 +1097,21 @@ static int compute_digest(pool *p, const char *path, off_t start, off_t len,
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
pctx = &ctx;
#else
pctx = EVP_MD_CTX_new();
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
EVP_MD_CTX_init(pctx);
if (EVP_DigestInit_ex(pctx, md, NULL) != 1) {
pr_log_debug(DEBUG1, MOD_DIGEST_VERSION
": error preparing digest context: %s", get_errors());
(void) pr_fsio_close(fh);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
errno = EPERM;
return -1;
}
@@ -1169,10 +1169,10 @@ static int compute_digest(pool *p, const char *path, off_t start, off_t len,
(void) pr_fsio_close(fh);
if (len != 0) {
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
pr_log_debug(DEBUG3, MOD_DIGEST_VERSION
": failed to read all %" PR_LU " bytes of '%s' (premature EOF?)",
(pr_off_t) len, path);
@@ -1183,18 +1183,18 @@ static int compute_digest(pool *p, const char *path, off_t start, off_t len,
if (EVP_DigestFinal_ex(pctx, digest, digest_len) != 1) {
pr_log_debug(DEBUG1, MOD_DIGEST_VERSION
": error finishing digest: %s", get_errors());
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
errno = EPERM;
return -1;
}
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return 0;
}
@@ -1207,25 +1207,25 @@ static const EVP_MD *get_algo_md(unsigned long algo) {
md = EVP_crc32();
break;
-#ifndef OPENSSL_NO_MD5
+#if !defined(OPENSSL_NO_MD5)
case DIGEST_ALGO_MD5:
md = EVP_md5();
break;
#endif /* OPENSSL_NO_MD5 */
-#ifndef OPENSSL_NO_SHA1
+#if !defined(OPENSSL_NO_SHA1)
case DIGEST_ALGO_SHA1:
md = EVP_sha1();
break;
#endif /* OPENSSL_NO_SHA1 */
-#ifndef OPENSSL_NO_SHA256
+#if !defined(OPENSSL_NO_SHA256)
case DIGEST_ALGO_SHA256:
md = EVP_sha256();
break;
#endif /* OPENSSL_NO_SHA256 */
-#ifndef OPENSSL_NO_SHA512
+#if !defined(OPENSSL_NO_SHA512)
case DIGEST_ALGO_SHA512:
md = EVP_sha512();
break;
=====================================
contrib/mod_sftp/crypto.c
=====================================
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_sftp OpenSSL interface
- * Copyright (c) 2008-2022 TJ Saunders
+ * Copyright (c) 2008-2023 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
@@ -104,10 +104,12 @@ static struct sftp_cipher ciphers[] = {
{ "aes128-cbc", "aes-128-cbc", 0, 0, EVP_aes_128_cbc, TRUE, TRUE },
#endif
-#if !defined(OPENSSL_NO_BF)
+#if !defined(OPENSSL_NO_BF) && \
+ (!defined(HAVE_LIBRESSL) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L))
# if OPENSSL_VERSION_NUMBER < 0x30000000L
{ "blowfish-ctr", NULL, 0, 0, NULL, FALSE, FALSE },
-# endif /* Prior to OpenSSL 3.x */
+# endif /* Prior to OpenSSL 3.x/LibreSSL-3.5.0 */
{ "blowfish-cbc", "bf-cbc", 0, 0, EVP_bf_cbc, FALSE, FALSE },
#endif /* !OPENSSL_NO_BF */
@@ -134,10 +136,12 @@ static struct sftp_cipher ciphers[] = {
{ "arcfour", "rc4", 0, 0, EVP_rc4, FALSE, FALSE },
#endif
-#if !defined(OPENSSL_NO_DES)
+#if !defined(OPENSSL_NO_DES) && \
+ (!defined(HAVE_LIBRESSL) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L))
# if OPENSSL_VERSION_NUMBER < 0x30000000L
{ "3des-ctr", NULL, 0, 0, NULL, TRUE, TRUE },
-# endif /* Prior to OpenSSL 3.x */
+# endif /* Prior to OpenSSL 3.x/LibreSSL-3.5.0 */
{ "3des-cbc", "des-ede3-cbc", 0, 0, EVP_des_ede3_cbc, TRUE, TRUE },
#endif /* !OPENSSL_NO_DES */
@@ -253,7 +257,9 @@ static const char *key_exchanges[] = {
static const char *trace_channel = "ssh2";
-#if OPENSSL_VERSION_NUMBER < 0x30000000L
+#if OPENSSL_VERSION_NUMBER < 0x30000000L && \
+ (!defined(HAVE_LIBRESSL) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L))
static void ctr_incr(unsigned char *ctr, size_t len) {
register int i;
@@ -271,6 +277,8 @@ static void ctr_incr(unsigned char *ctr, size_t len) {
#endif /* Prior to OpenSSL 3.x */
#if !defined(OPENSSL_NO_BF) && \
+ (!defined(HAVE_LIBRESSL) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)) && \
OPENSSL_VERSION_NUMBER < 0x30000000L
/* Blowfish CTR mode implementation */
@@ -396,8 +404,8 @@ static int do_bf_ctr(EVP_CIPHER_CTX *ctx, unsigned char *dst,
static const EVP_CIPHER *get_bf_ctr_cipher(void) {
EVP_CIPHER *cipher;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
/* XXX TODO: At some point, we also need to call EVP_CIPHER_meth_free() on
* this, to avoid a resource leak.
*/
@@ -407,7 +415,6 @@ static const EVP_CIPHER *get_bf_ctr_cipher(void) {
EVP_CIPHER_meth_set_cleanup(cipher, cleanup_bf_ctr);
EVP_CIPHER_meth_set_do_cipher(cipher, do_bf_ctr);
EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CBC_MODE|EVP_CIPH_VARIABLE_LENGTH|EVP_CIPH_ALWAYS_CALL_INIT|EVP_CIPH_CUSTOM_IV);
-
#else
static EVP_CIPHER bf_ctr_cipher;
@@ -424,7 +431,7 @@ static const EVP_CIPHER *get_bf_ctr_cipher(void) {
bf_ctr_cipher.flags = EVP_CIPH_CBC_MODE|EVP_CIPH_VARIABLE_LENGTH|EVP_CIPH_ALWAYS_CALL_INIT|EVP_CIPH_CUSTOM_IV;
cipher = &bf_ctr_cipher;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return cipher;
}
@@ -433,6 +440,8 @@ static const EVP_CIPHER *get_bf_ctr_cipher(void) {
#if OPENSSL_VERSION_NUMBER > 0x000907000L
# if !defined(OPENSSL_NO_DES) && \
+ (!defined(HAVE_LIBRESSL) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)) && \
OPENSSL_VERSION_NUMBER < 0x30000000L
/* 3DES CTR mode implementation */
@@ -568,8 +577,8 @@ static int do_des3_ctr(EVP_CIPHER_CTX *ctx, unsigned char *dst,
static const EVP_CIPHER *get_des3_ctr_cipher(void) {
EVP_CIPHER *cipher;
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
unsigned long flags;
/* XXX TODO: At some point, we also need to call EVP_CIPHER_meth_free() on
@@ -607,7 +616,7 @@ static const EVP_CIPHER *get_des3_ctr_cipher(void) {
# endif /* OPENSSL_FIPS */
cipher = &des3_ctr_cipher;
-# endif /* prior to OpenSSL-1.1.0 */
+# endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return cipher;
}
@@ -615,7 +624,9 @@ static const EVP_CIPHER *get_des3_ctr_cipher(void) {
#if !defined(HAVE_EVP_AES_256_CTR_OPENSSL) && \
!defined(HAVE_EVP_AES_192_CTR_OPENSSL) && \
- !defined(HAVE_EVP_AES_128_CTR_OPENSSL)
+ !defined(HAVE_EVP_AES_128_CTR_OPENSSL) && \
+ (!defined(HAVE_LIBRESSL) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L))
/* AES CTR mode implementation */
struct aes_ctr_ex {
@@ -869,12 +880,12 @@ static int update_umac64(EVP_MD_CTX *ctx, const void *data, size_t len) {
int res;
void *md_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
if (md_data == NULL) {
struct umac_ctx *umac;
void **ptr;
@@ -897,12 +908,12 @@ static int update_umac128(EVP_MD_CTX *ctx, const void *data, size_t len) {
int res;
void *md_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
if (md_data == NULL) {
struct umac_ctx *umac;
@@ -927,12 +938,12 @@ static int final_umac64(EVP_MD_CTX *ctx, unsigned char *md) {
int res;
void *md_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
res = umac_final(md_data, md, nonce);
return res;
@@ -943,12 +954,12 @@ static int final_umac128(EVP_MD_CTX *ctx, unsigned char *md) {
int res;
void *md_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
res = umac128_final(md_data, md, nonce);
return res;
@@ -958,12 +969,12 @@ static int delete_umac64(EVP_MD_CTX *ctx) {
struct umac_ctx *umac;
void *md_data, **ptr;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
umac = md_data;
umac_delete(umac);
@@ -978,12 +989,12 @@ static int delete_umac128(EVP_MD_CTX *ctx) {
struct umac_ctx *umac;
void *md_data, **ptr;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
md_data = EVP_MD_CTX_md_data(ctx);
#else
md_data = ctx->md_data;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
umac = md_data;
umac128_delete(umac);
@@ -997,8 +1008,8 @@ static int delete_umac128(EVP_MD_CTX *ctx) {
static const EVP_MD *get_umac64_digest(void) {
EVP_MD *md;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
/* XXX TODO: At some point, we also need to call EVP_MD_meth_free() on
* this, to avoid a resource leak.
*/
@@ -1024,7 +1035,7 @@ static const EVP_MD *get_umac64_digest(void) {
umac64_digest.block_size = 32;
md = &umac64_digest;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return md;
}
@@ -1032,8 +1043,8 @@ static const EVP_MD *get_umac64_digest(void) {
static const EVP_MD *get_umac128_digest(void) {
EVP_MD *md;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
/* XXX TODO: At some point, we also need to call EVP_MD_meth_free() on
* this, to avoid a resource leak.
*/
@@ -1044,7 +1055,6 @@ static const EVP_MD *get_umac128_digest(void) {
EVP_MD_meth_set_update(md, update_umac128);
EVP_MD_meth_set_final(md, final_umac128);
EVP_MD_meth_set_cleanup(md, delete_umac128);
-
#else
static EVP_MD umac128_digest;
@@ -1060,7 +1070,7 @@ static const EVP_MD *get_umac128_digest(void) {
umac128_digest.block_size = 64;
md = &umac128_digest;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
return md;
}
@@ -1081,6 +1091,8 @@ const EVP_CIPHER *sftp_crypto_get_cipher(const char *name, size_t *key_len,
if (strcmp(name, "blowfish-ctr") == 0) {
#if !defined(OPENSSL_NO_BF) && \
+ (!defined(HAVE_LIBRESSL) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)) && \
OPENSSL_VERSION_NUMBER < 0x30000000L
cipher = get_bf_ctr_cipher();
#else
@@ -1093,6 +1105,8 @@ const EVP_CIPHER *sftp_crypto_get_cipher(const char *name, size_t *key_len,
#if OPENSSL_VERSION_NUMBER > 0x000907000L
} else if (strcmp(name, "3des-ctr") == 0) {
# if !defined(OPENSSL_NO_DES) && \
+ (!defined(HAVE_LIBRESSL) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)) && \
OPENSSL_VERSION_NUMBER < 0x30000000L
cipher = get_des3_ctr_cipher();
# else
=====================================
contrib/mod_sftp/fxp.c
=====================================
@@ -4106,9 +4106,9 @@ static int fxp_handle_ext_check_file(struct fxp_packet *fxp, char *digest_list,
void *data;
size_t datasz;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX md_ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
const EVP_MD *md;
@@ -4437,12 +4437,12 @@ static int fxp_handle_ext_check_file(struct fxp_packet *fxp, char *digest_list,
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
pctx = &md_ctx;
EVP_MD_CTX_init(pctx);
#else
pctx = EVP_MD_CTX_new();
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_EXTENDED_REPLY);
sftp_msg_write_int(&buf, &buflen, fxp->request_id);
@@ -4461,12 +4461,12 @@ static int fxp_handle_ext_check_file(struct fxp_packet *fxp, char *digest_list,
pr_signals_handle();
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX_cleanup(pctx);
EVP_MD_CTX_init(pctx);
#else
EVP_MD_CTX_reset(pctx);
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
EVP_DigestInit(pctx, md);
pr_trace_msg(trace_channel, 19,
=====================================
contrib/mod_sftp/kex.c
=====================================
@@ -166,6 +166,13 @@ static struct sftp_kex *kex_first_kex = NULL;
static struct sftp_kex *kex_rekey_kex = NULL;
static int kex_sent_kexinit = FALSE;
+/* Using strict kex? Note that we maintain this value here, rather than
+ * in the sftp_kex struct, so that any "use strict KEX" flag set via the
+ * first KEXINIT is used through any subsequent KEXINITs.
+ */
+static int use_strict_kex = FALSE;
+static int kex_done_first_kex = FALSE;
+
/* Diffie-Hellman group moduli */
static const char *dh_group1_str =
@@ -310,9 +317,9 @@ static const unsigned char *calculate_h(struct sftp_kex *kex,
const unsigned char *hostkey_data, uint32_t hostkey_datalen,
const BIGNUM *k, uint32_t *hlen) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
const BIGNUM *dh_pub_key = NULL;
unsigned char *buf, *ptr;
@@ -348,23 +355,23 @@ static const unsigned char *calculate_h(struct sftp_kex *kex,
sftp_msg_write_mpint(&buf, &buflen, kex->e);
/* Server's key */
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_key(kex->dh, &dh_pub_key, NULL);
#else
dh_pub_key = kex->dh->pub_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(&buf, &buflen, dh_pub_key);
/* Shared secret */
sftp_msg_write_mpint(&buf, &buflen, k);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
/* In OpenSSL 0.9.6, many of the EVP_Digest* functions returned void, not
* int. Without these ugly OpenSSL version preprocessor checks, the
@@ -378,10 +385,10 @@ static const unsigned char *calculate_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
@@ -395,10 +402,10 @@ static const unsigned char *calculate_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
@@ -412,20 +419,20 @@ static const unsigned char *calculate_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
EVP_DigestFinal(pctx, kex_digest_buf, hlen);
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
@@ -439,9 +446,9 @@ static const unsigned char *calculate_gex_h(struct sftp_kex *kex,
const BIGNUM *k, uint32_t min, uint32_t pref, uint32_t max,
uint32_t *hlen) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
const BIGNUM *dh_p = NULL, *dh_g = NULL, *dh_pub_key = NULL;
unsigned char *buf, *ptr;
@@ -485,13 +492,13 @@ static const unsigned char *calculate_gex_h(struct sftp_kex *kex,
sftp_msg_write_int(&buf, &buflen, max);
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
#else
dh_p = kex->dh->p;
dh_g = kex->dh->g;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(&buf, &buflen, dh_p);
sftp_msg_write_mpint(&buf, &buflen, dh_g);
@@ -499,23 +506,23 @@ static const unsigned char *calculate_gex_h(struct sftp_kex *kex,
sftp_msg_write_mpint(&buf, &buflen, kex->e);
/* Server's key */
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_key(kex->dh, &dh_pub_key, NULL);
#else
dh_pub_key = kex->dh->pub_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(&buf, &buflen, dh_pub_key);
/* Shared secret */
sftp_msg_write_mpint(&buf, &buflen, k);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
/* In OpenSSL 0.9.6, many of the EVP_Digest* functions returned void, not
* int. Without these ugly OpenSSL version preprocessor checks, the
@@ -529,10 +536,10 @@ static const unsigned char *calculate_gex_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
@@ -546,10 +553,10 @@ static const unsigned char *calculate_gex_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
@@ -563,20 +570,20 @@ static const unsigned char *calculate_gex_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
EVP_DigestFinal(pctx, kex_digest_buf, hlen);
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
@@ -589,9 +596,9 @@ static const unsigned char *calculate_kexrsa_h(struct sftp_kex *kex,
const BIGNUM *k, unsigned char *rsa_key, uint32_t rsa_keylen,
uint32_t *hlen) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
unsigned char *buf, *ptr;
uint32_t buflen, bufsz;
@@ -632,12 +639,12 @@ static const unsigned char *calculate_kexrsa_h(struct sftp_kex *kex,
/* Shared secret. */
sftp_msg_write_mpint(&buf, &buflen, k);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
/* In OpenSSL 0.9.6, many of the EVP_Digest* functions returned void, not
* int. Without these ugly OpenSSL version preprocessor checks, the
@@ -649,10 +656,10 @@ static const unsigned char *calculate_kexrsa_h(struct sftp_kex *kex,
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error initializing message digest: %s", sftp_crypto_get_errors());
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
@@ -664,10 +671,10 @@ static const unsigned char *calculate_kexrsa_h(struct sftp_kex *kex,
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error updating message digest: %s", sftp_crypto_get_errors());
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
@@ -679,20 +686,20 @@ static const unsigned char *calculate_kexrsa_h(struct sftp_kex *kex,
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error finalizing message digest: %s", sftp_crypto_get_errors());
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
EVP_DigestFinal(pctx, kex_digest_buf, hlen);
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
pr_memscrub(ptr, bufsz);
return kex_digest_buf;
@@ -703,9 +710,9 @@ static const unsigned char *calculate_ecdh_h(struct sftp_kex *kex,
const unsigned char *hostkey_data, uint32_t hostkey_datalen,
const BIGNUM *k, uint32_t *hlen) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
unsigned char *buf, *ptr;
uint32_t buflen, bufsz;
@@ -749,12 +756,12 @@ static const unsigned char *calculate_ecdh_h(struct sftp_kex *kex,
/* Shared secret */
sftp_msg_write_mpint(&buf, &buflen, k);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
/* In OpenSSL 0.9.6, many of the EVP_Digest* functions returned void, not
* int. Without these ugly OpenSSL version preprocessor checks, the
@@ -768,10 +775,10 @@ static const unsigned char *calculate_ecdh_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
@@ -785,10 +792,10 @@ static const unsigned char *calculate_ecdh_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
@@ -802,20 +809,20 @@ static const unsigned char *calculate_ecdh_h(struct sftp_kex *kex,
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return NULL;
}
#else
EVP_DigestFinal(pctx, kex_digest_buf, hlen);
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000LL && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
BN_clear_free((BIGNUM *) kex->e);
kex->e = NULL;
pr_memscrub(ptr, bufsz);
@@ -846,12 +853,12 @@ static int have_good_dh(DH *dh, const BIGNUM *pub_key) {
return -1;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_pqg(dh, &dh_p, NULL, NULL);
#else
dh_p = dh->p;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
tmp = BN_new();
if (!BN_sub(tmp, dh_p, BN_value_one()) ||
@@ -1095,13 +1102,13 @@ static int create_dh(struct sftp_kex *kex, int type) {
return -1;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_set0_pqg(dh, (BIGNUM *) dh_p, NULL, (BIGNUM *) dh_g);
#else
dh->p = dh_p;
dh->g = dh_g;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
dh_priv_key = BN_new();
@@ -1116,13 +1123,13 @@ static int create_dh(struct sftp_kex *kex, int type) {
}
dh_pub_key = BN_new();
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_set0_key(dh, (BIGNUM *) dh_pub_key, (BIGNUM *) dh_priv_key);
#else
dh->pub_key = dh_pub_key;
dh->priv_key = dh_priv_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
pr_trace_msg(trace_channel, 12, "generating DH key");
if (DH_generate_key(dh) != 1) {
@@ -1132,12 +1139,12 @@ static int create_dh(struct sftp_kex *kex, int type) {
return -1;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_key(dh, &dh_pub_key, NULL);
#else
dh_pub_key = dh->pub_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
if (have_good_dh(dh, dh_pub_key) < 0) {
DH_free(dh);
@@ -1258,13 +1265,13 @@ static int finish_dh(struct sftp_kex *kex) {
dh_pub_key = BN_new();
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_set0_key(kex->dh, dh_pub_key, dh_priv_key);
#else
kex->dh->pub_key = dh_pub_key;
kex->dh->priv_key = dh_priv_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
pr_trace_msg(trace_channel, 12, "generating DH key");
if (DH_generate_key(kex->dh) != 1) {
@@ -1275,7 +1282,7 @@ static int finish_dh(struct sftp_kex *kex) {
if (have_good_dh(kex->dh, kex->e) < 0) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
if (kex->dh->priv_key != NULL) {
BN_clear_free(kex->dh->priv_key);
kex->dh->priv_key = NULL;
@@ -1285,7 +1292,7 @@ static int finish_dh(struct sftp_kex *kex) {
BN_clear_free(kex->dh->pub_key);
kex->dh->pub_key = NULL;
}
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
continue;
}
@@ -1612,6 +1619,16 @@ static const char *get_kexinit_exchange_list(pool *p) {
res = pstrcat(p, res, *res ? "," : "", pstrdup(p, "ext-info-s"), NULL);
}
+ if (!(sftp_opts & SFTP_OPT_NO_STRICT_KEX)) {
+ /* Indicate support for OpenSSH's custom "strict KEX" mode extension,
+ * but only if we have not done/completed our first KEX.
+ */
+ if (kex_done_first_kex == FALSE) {
+ res = pstrcat(p, res, *res ? "," : "",
+ pstrdup(p, "kex-strict-s-v00 at openssh.com"), NULL);
+ }
+ }
+
return res;
}
@@ -2323,6 +2340,21 @@ static int get_session_names(struct sftp_kex *kex, int *correct_guess) {
pr_trace_msg(trace_channel, 20, "client %s EXT_INFO support",
kex->use_ext_info ? "signaled" : "did not signal" );
+ if (!(sftp_opts & SFTP_OPT_NO_STRICT_KEX)) {
+ /* Did the client indicate "strict kex" support (Issue 1760)?
+ *
+ * Note that we only check for this if it is our first KEXINIT.
+ * The "strict kex" extension is ignored in any subsequent KEXINITs, as
+ * for rekeys.
+ */
+ if (kex_done_first_kex == FALSE) {
+ use_strict_kex = sftp_misc_namelist_contains(kex->pool,
+ client_list, "kex-strict-c-v00 at openssh.com");
+ pr_trace_msg(trace_channel, 20, "client %s strict KEX support",
+ use_strict_kex ? "signaled" : "did not signal" );
+ }
+ }
+
} else {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"no shared key exchange algorithm found (client sent '%s', server sent "
@@ -3009,12 +3041,12 @@ static int write_dh_reply(struct ssh2_packet *pkt, struct sftp_kex *kex) {
sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_KEX_DH_REPLY);
sftp_msg_write_data(&buf, &buflen, hostkey_data, hostkey_datalen, TRUE);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_key(kex->dh, &dh_pub_key, NULL);
#else
dh_pub_key = kex->dh->pub_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(&buf, &buflen, dh_pub_key);
sftp_msg_write_data(&buf, &buflen, hsig, hsiglen, TRUE);
@@ -3420,13 +3452,13 @@ static int get_dh_gex_group(struct sftp_kex *kex, uint32_t min,
* of them for our KEX DH.
*/
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_pqg(chosen_dh, &dh_p, NULL, &dh_g);
#else
dh_p = chosen_dh->p;
dh_g = chosen_dh->g;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
dup_p = BN_dup(dh_p);
if (dup_p == NULL) {
@@ -3448,13 +3480,13 @@ static int get_dh_gex_group(struct sftp_kex *kex, uint32_t min,
} else {
/* Now set those P, G copies into our KEX DH. */
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_set0_pqg(kex->dh, (BIGNUM *) dup_p, NULL, (BIGNUM *) dup_g);
#else
kex->dh->p = dup_p;
kex->dh->g = dup_g;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
}
}
}
@@ -3514,13 +3546,13 @@ static int get_dh_gex_group(struct sftp_kex *kex, uint32_t min,
return -1;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_set0_pqg(kex->dh, dh_p, NULL, dh_g);
#else
kex->dh->p = dh_p;
kex->dh->g = dh_g;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
}
return 0;
@@ -3542,13 +3574,13 @@ static int write_dh_gex_group(struct ssh2_packet *pkt, struct sftp_kex *kex,
sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_KEX_DH_GEX_GROUP);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
#else
dh_p = kex->dh->p;
dh_g = kex->dh->g;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(&buf, &buflen, dh_p);
sftp_msg_write_mpint(&buf, &buflen, dh_g);
@@ -3661,12 +3693,12 @@ static int write_dh_gex_reply(struct ssh2_packet *pkt, struct sftp_kex *kex,
sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_KEX_DH_GEX_REPLY);
sftp_msg_write_data(&buf, &buflen, hostkey_data, hostkey_datalen, TRUE);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DH_get0_key(kex->dh, &dh_pub_key, NULL);
#else
dh_pub_key = kex->dh->pub_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(&buf, &buflen, dh_pub_key);
sftp_msg_write_data(&buf, &buflen, hsig, hsiglen, TRUE);
@@ -3863,13 +3895,13 @@ static int write_kexrsa_pubkey(struct ssh2_packet *pkt, struct sftp_kex *kex) {
*/
sftp_msg_write_string(&buf, &buflen, "ssh-rsa");
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
RSA_get0_key(kex->rsa, &rsa_n, &rsa_e, NULL);
#else
rsa_e = kex->rsa->e;
rsa_n = kex->rsa->n;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(&buf, &buflen, rsa_e);
sftp_msg_write_mpint(&buf, &buflen, rsa_n);
@@ -3922,13 +3954,13 @@ static int write_kexrsa_done(struct ssh2_packet *pkt, struct sftp_kex *kex) {
*/
sftp_msg_write_string(&buf2, &buflen2, "ssh-rsa");
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
RSA_get0_key(kex->rsa, &rsa_n, &rsa_e, NULL);
#else
rsa_e = kex->rsa->e;
rsa_n = kex->rsa->n;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(&buf2, &buflen2, rsa_e);
sftp_msg_write_mpint(&buf2, &buflen2, rsa_n);
@@ -4146,9 +4178,10 @@ static const unsigned char *calculate_curve25519_h(struct sftp_kex *kex,
const unsigned char *hostkey_data, uint32_t hostkey_datalen,
const BIGNUM *k, unsigned char *client_curve25519,
unsigned char *server_curve25519, uint32_t *hlen) {
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
unsigned char *buf, *ptr;
uint32_t buflen, bufsz;
@@ -4589,9 +4622,10 @@ static const unsigned char *calculate_curve448_h(struct sftp_kex *kex,
const unsigned char *hostkey_data, uint32_t hostkey_datalen,
const BIGNUM *k, unsigned char *client_curve448,
unsigned char *server_curve448, uint32_t *hlen) {
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
unsigned char *buf, *ptr;
uint32_t buflen, bufsz;
@@ -5056,7 +5090,6 @@ static int handle_kex_ecdh(struct ssh2_packet *pkt, struct sftp_kex *kex) {
destroy_pool(pkt->pool);
return 0;
}
-
#endif /* PR_USE_OPENSSL_ECC */
static struct ssh2_packet *read_kex_packet(pool *p, struct sftp_kex *kex,
@@ -5107,6 +5140,10 @@ static struct ssh2_packet *read_kex_packet(pool *p, struct sftp_kex *kex,
/* Per RFC 4253, Section 11, DEBUG, DISCONNECT, IGNORE, and UNIMPLEMENTED
* messages can occur at any time, even during KEX. We have to be prepared
* for this, and Do The Right Thing(tm).
+ *
+ * However, due to the Terrapin attack, if we are using a "strict KEX"
+ * mode, then only DISCONNECT messages can occur during KEX; DEBUG,
+ * IGNORE, and UNIMPLEMENTED messages will lead to disconnecting.
*/
msg_type = sftp_ssh2_packet_get_msg_type(pkt);
@@ -5135,35 +5172,43 @@ static struct ssh2_packet *read_kex_packet(pool *p, struct sftp_kex *kex,
}
switch (msg_type) {
- case SFTP_SSH2_MSG_DEBUG:
- sftp_ssh2_packet_handle_debug(pkt);
- pr_response_set_pool(NULL);
- pkt = NULL;
- break;
-
+ /* DISCONNECT messages are always allowed. */
case SFTP_SSH2_MSG_DISCONNECT:
sftp_ssh2_packet_handle_disconnect(pkt);
pr_response_set_pool(NULL);
pkt = NULL;
break;
+ case SFTP_SSH2_MSG_DEBUG:
+ if (use_strict_kex == FALSE) {
+ sftp_ssh2_packet_handle_debug(pkt);
+ pr_response_set_pool(NULL);
+ pkt = NULL;
+ break;
+ }
+
case SFTP_SSH2_MSG_IGNORE:
- sftp_ssh2_packet_handle_ignore(pkt);
- pr_response_set_pool(NULL);
- pkt = NULL;
- break;
+ if (use_strict_kex == FALSE) {
+ sftp_ssh2_packet_handle_ignore(pkt);
+ pr_response_set_pool(NULL);
+ pkt = NULL;
+ break;
+ }
case SFTP_SSH2_MSG_UNIMPLEMENTED:
- sftp_ssh2_packet_handle_unimplemented(pkt);
- pr_response_set_pool(NULL);
- pkt = NULL;
- break;
+ if (use_strict_kex == FALSE) {
+ sftp_ssh2_packet_handle_unimplemented(pkt);
+ pr_response_set_pool(NULL);
+ pkt = NULL;
+ break;
+ }
default:
/* For any other message type, it's considered a protocol error. */
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
- "received %s (%d) unexpectedly, disconnecting",
- sftp_ssh2_packet_get_msg_type_desc(msg_type), msg_type);
+ "received %s (%d) unexpectedly%s, disconnecting",
+ sftp_ssh2_packet_get_msg_type_desc(msg_type), msg_type,
+ use_strict_kex ? " during strict KEX" : "");
pr_response_set_pool(NULL);
destroy_kex(kex);
destroy_pool(pkt->pool);
@@ -5185,7 +5230,7 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
* initial connect (kex_first_kex not null), or because we
* are in a server-initiated rekeying (kex_rekey_kex not null).
*/
- if (kex_first_kex) {
+ if (kex_first_kex != NULL) {
kex = kex_first_kex;
/* We need to assign the client/server versions, which this struct
@@ -5194,7 +5239,7 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
kex->client_version = kex_client_version;
kex->server_version = kex_server_version;
- } else if (kex_rekey_kex) {
+ } else if (kex_rekey_kex != NULL) {
kex = kex_rekey_kex;
} else {
@@ -5231,6 +5276,24 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
return -1;
}
+ if (use_strict_kex == TRUE &&
+ kex_done_first_kex == FALSE) {
+ uint32_t client_seqno;
+
+ client_seqno = sftp_ssh2_packet_get_client_seqno();
+ if (client_seqno != 1) {
+ /* Receiving any messages other than a KEXINIT as the first client
+ * message indicates the possibility of the Terrapin attack being
+ * conducted (Issue 1760). Thus we disconnect the client in such
+ * cases.
+ */
+ (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
+ "'strict KEX' violation, as KEXINIT was not the first message; disconnecting");
+ destroy_kex(kex);
+ SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
+ }
+ }
+
/* Once we have received the client KEXINIT message, we can compare what we
* want to send against what we already received from the client.
*
@@ -5289,7 +5352,7 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
destroy_pool(pkt->pool);
- if (!kex_sent_kexinit) {
+ if (kex_sent_kexinit == FALSE) {
pkt = sftp_ssh2_packet_create(kex_pool);
res = write_kexinit(pkt, kex);
if (res < 0) {
@@ -5312,7 +5375,7 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
}
}
- if (!kex_sent_kexinit) {
+ if (kex_sent_kexinit == FALSE) {
pkt = sftp_ssh2_packet_create(kex_pool);
res = write_kexinit(pkt, kex);
if (res < 0) {
@@ -5443,7 +5506,7 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
NULL, 1, SFTP_SSH2_MSG_NEWKEYS);
/* If we didn't send our NEWKEYS message earlier, do it now. */
- if (!sent_newkeys) {
+ if (sent_newkeys == FALSE) {
struct ssh2_packet *pkt2;
pr_trace_msg(trace_channel, 9, "sending NEWKEYS message to client");
@@ -5467,6 +5530,11 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
destroy_pool(pkt2->pool);
}
+ if (use_strict_kex == TRUE) {
+ sftp_ssh2_packet_reset_client_seqno();
+ sftp_ssh2_packet_reset_server_seqno();
+ }
+
/* Last but certainly not least, set up the keys for encryption and
* authentication, based on H and K.
*/
@@ -5487,6 +5555,9 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
destroy_pool(pkt->pool);
cmd = NULL;
+ /* We've now completed our KEX, possibly our first. */
+ kex_done_first_kex = TRUE;
+
/* If extension negotiation has not been disabled, AND if we have not
* received a service request, AND if the client sent "ext-info-c", THEN
* send our EXT_INFO. We do not want send this during rekeys.
@@ -5540,6 +5611,12 @@ int sftp_kex_handle(struct ssh2_packet *pkt) {
}
}
+ /* Only start the TAP timer after we have completed our first KEX.
+ * Otherwise, we risk sending "illegal" packets prior to, or during,
+ * a "strict KEX" session (Issue 1760).
+ */
+ sftp_tap_start_policy();
+
/* Reset this flag for the next time through. */
kex_sent_kexinit = FALSE;
@@ -5569,7 +5646,7 @@ int sftp_kex_free(void) {
destroy_kex(rekey_kex);
}
- if (kex_pool) {
+ if (kex_pool != NULL) {
destroy_pool(kex_pool);
kex_pool = NULL;
}
@@ -5745,7 +5822,7 @@ int sftp_kex_send_first_kexinit(void) {
struct ssh2_packet *pkt;
int res;
- if (!kex_pool) {
+ if (kex_pool == NULL) {
kex_pool = make_sub_pool(sftp_pool);
pr_pool_tag(kex_pool, "Kex Pool");
}
@@ -5780,4 +5857,3 @@ int sftp_kex_send_first_kexinit(void) {
destroy_pool(pkt->pool);
return 0;
}
-
=====================================
contrib/mod_sftp/keys.c
=====================================
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_sftp key mgmt (keys)
- * Copyright (c) 2008-2022 TJ Saunders
+ * Copyright (c) 2008-2023 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
@@ -178,8 +178,10 @@ static struct openssh_cipher ciphers[] = {
{ NULL, 0, 0, 0, 0, NULL, NULL }
};
+#if defined(HAVE_X448_OPENSSL)
static int handle_ed448_hostkey(pool *p, const unsigned char *key_data,
uint32_t key_datalen, const char *file_path);
+#endif /* HAVE_X448_OPENSSL */
static int read_openssh_private_key(pool *p, const char *path, int fd,
const char *passphrase, enum sftp_key_type_e *key_type, EVP_PKEY **pkey,
unsigned char **key, uint32_t *keylen);
@@ -1216,36 +1218,36 @@ static uint32_t read_pkey_from_data(pool *p, unsigned char *pkey_data,
}
len += res;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
RSA_set0_crt_params(rsa, NULL, NULL, (BIGNUM *) rsa_iqmp);
RSA_set0_factors(rsa, (BIGNUM *) rsa_p, (BIGNUM *) rsa_q);
#else
rsa->iqmp = rsa_iqmp;
rsa->p = rsa_p;
rsa->q = rsa_q;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
/* Turns out that for OpenSSH formatted RSA keys, the 'e' and 'n' values
* are in the opposite order than the normal PEM format. Typical.
*/
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
RSA_set0_key(rsa, (BIGNUM *) rsa_e, (BIGNUM *) rsa_n, (BIGNUM *) rsa_d);
#else
rsa->e = rsa_n;
rsa->n = rsa_e;
rsa->d = rsa_d;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
} else {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
RSA_set0_key(rsa, (BIGNUM *) rsa_n, (BIGNUM *) rsa_e, (BIGNUM *) rsa_d);
#else
rsa->e = rsa_e;
rsa->n = rsa_n;
rsa->d = rsa_d;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
}
if (EVP_PKEY_assign_RSA(*pkey, rsa) != 1) {
@@ -1339,8 +1341,8 @@ static uint32_t read_pkey_from_data(pool *p, unsigned char *pkey_data,
len += res;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DSA_set0_pqg(dsa, (BIGNUM *) dsa_p, (BIGNUM *) dsa_q, (BIGNUM *) dsa_g);
DSA_set0_key(dsa, (BIGNUM *) dsa_pub_key, (BIGNUM *) dsa_priv_key);
#else
@@ -1349,7 +1351,7 @@ static uint32_t read_pkey_from_data(pool *p, unsigned char *pkey_data,
dsa->g = dsa_g;
dsa->pub_key = dsa_pub_key;
dsa->priv_key = dsa_priv_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
if (EVP_PKEY_assign_DSA(*pkey, dsa) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
@@ -1983,8 +1985,8 @@ static int rsa_compare_keys(pool *p, EVP_PKEY *remote_pkey,
debug_rsa_key(p, "local RSA key:", local_rsa);
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
RSA_get0_key(remote_rsa, &remote_rsa_n, &remote_rsa_e, NULL);
RSA_get0_key(local_rsa, &local_rsa_n, &local_rsa_e, NULL);
#else
@@ -1992,7 +1994,7 @@ static int rsa_compare_keys(pool *p, EVP_PKEY *remote_pkey,
local_rsa_e = local_rsa->e;
remote_rsa_n = remote_rsa->n;
local_rsa_n = local_rsa->n;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
if (BN_cmp(remote_rsa_e, local_rsa_e) != 0) {
pr_trace_msg(trace_channel, 17, "%s",
@@ -2044,8 +2046,8 @@ static int dsa_compare_keys(pool *p, EVP_PKEY *remote_pkey,
remote_dsa = EVP_PKEY_get1_DSA(remote_pkey);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DSA_get0_pqg(remote_dsa, &remote_dsa_p, &remote_dsa_q, &remote_dsa_g);
DSA_get0_pqg(local_dsa, &local_dsa_p, &local_dsa_q, &local_dsa_g);
DSA_get0_key(remote_dsa, &remote_dsa_pub_key, NULL);
@@ -2059,7 +2061,7 @@ static int dsa_compare_keys(pool *p, EVP_PKEY *remote_pkey,
local_dsa_q = local_dsa->q;
local_dsa_g = local_dsa->g;
local_dsa_pub_key = local_dsa->pub_key;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
if (BN_cmp(remote_dsa_p, local_dsa_p) != 0) {
pr_trace_msg(trace_channel, 17, "%s",
@@ -2327,9 +2329,9 @@ int sftp_keys_compare_keys(pool *p,
const char *sftp_keys_get_fingerprint(pool *p, unsigned char *key_data,
uint32_t key_datalen, int digest_algo) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
const EVP_MD *digest;
char *digest_name = "none", *fp;
@@ -2362,12 +2364,12 @@ const char *sftp_keys_get_fingerprint(pool *p, unsigned char *key_data,
return NULL;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
/* In OpenSSL 0.9.6, many of the EVP_Digest* functions returned void, not
* int. Without these ugly OpenSSL version preprocessor checks, the
@@ -2379,10 +2381,10 @@ const char *sftp_keys_get_fingerprint(pool *p, unsigned char *key_data,
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error initializing %s digest: %s", digest_name,
sftp_crypto_get_errors());
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
errno = EPERM;
return NULL;
}
@@ -2394,10 +2396,10 @@ const char *sftp_keys_get_fingerprint(pool *p, unsigned char *key_data,
if (EVP_DigestUpdate(pctx, key_data, key_datalen) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error updating %s digest: %s", digest_name, sftp_crypto_get_errors());
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
errno = EPERM;
return NULL;
}
@@ -2411,10 +2413,10 @@ const char *sftp_keys_get_fingerprint(pool *p, unsigned char *key_data,
if (EVP_DigestFinal(pctx, fp_data, &fp_datalen) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error finishing %s digest: %s", digest_name, sftp_crypto_get_errors());
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
errno = EPERM;
return NULL;
}
@@ -2422,10 +2424,10 @@ const char *sftp_keys_get_fingerprint(pool *p, unsigned char *key_data,
EVP_DigestFinal(pctx, fp_data, &fp_datalen);
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
/* Now encode that digest in fp_data as hex characters. */
fp = "";
@@ -3786,13 +3788,13 @@ static int get_rsa_hostkey_data(pool *p, unsigned char **buf,
*ptr = *buf = palloc(p, *buflen);
sftp_msg_write_string(buf, buflen, "ssh-rsa");
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
#else
rsa_e = rsa->e;
rsa_n = rsa->n;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(buf, buflen, rsa_e);
sftp_msg_write_mpint(buf, buflen, rsa_n);
@@ -3817,8 +3819,8 @@ static int get_dsa_hostkey_data(pool *p, unsigned char **buf,
*ptr = *buf = palloc(p, *buflen);
sftp_msg_write_string(buf, buflen, "ssh-dss");
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DSA_get0_pqg(dsa, &dsa_p, &dsa_q, &dsa_g);
DSA_get0_key(dsa, &dsa_pub_key, NULL);
#else
@@ -3826,7 +3828,7 @@ static int get_dsa_hostkey_data(pool *p, unsigned char **buf,
dsa_q = dsa->q;
dsa_g = dsa->g;
dsa_pub_key = dsa->pub_key;;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sftp_msg_write_mpint(buf, buflen, dsa_p);
sftp_msg_write_mpint(buf, buflen, dsa_q);
sftp_msg_write_mpint(buf, buflen, dsa_g);
@@ -4236,9 +4238,9 @@ static const unsigned char *get_rsa_signed_data(pool *p,
const char *sig_name, const EVP_MD *md) {
RSA *rsa;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
unsigned char dgst[EVP_MAX_MD_SIZE], *sig_data;
unsigned char *buf, *ptr;
@@ -4268,12 +4270,12 @@ static const unsigned char *get_rsa_signed_data(pool *p,
}
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_DigestInit(pctx, md);
EVP_DigestUpdate(pctx, data, datalen);
@@ -4373,9 +4375,9 @@ static const unsigned char *dsa_sign_data(pool *p, const unsigned char *data,
DSA_SIG *sig;
const BIGNUM *sig_r = NULL, *sig_s = NULL;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
const EVP_MD *sha1 = EVP_sha1();
unsigned char dgst[EVP_MAX_MD_SIZE], *sig_data;
@@ -4412,12 +4414,12 @@ static const unsigned char *dsa_sign_data(pool *p, const unsigned char *data,
}
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_DigestInit(pctx, sha1);
EVP_DigestUpdate(pctx, data, datalen);
@@ -4440,13 +4442,13 @@ static const unsigned char *dsa_sign_data(pool *p, const unsigned char *data,
/* Got the signature, no need for the digest memory. */
pr_memscrub(dgst, dgstlen);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DSA_SIG_get0(sig, &sig_r, &sig_s);
#else
sig_r = sig->r;
sig_s = sig->s;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
rlen = BN_num_bytes(sig_r);
slen = BN_num_bytes(sig_s);
@@ -4500,9 +4502,9 @@ static const unsigned char *ecdsa_sign_data(pool *p, const unsigned char *data,
ECDSA_SIG *sig;
const BIGNUM *sig_r = NULL, *sig_s = NULL;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
const EVP_MD *md;
unsigned char dgst[EVP_MAX_MD_SIZE];
@@ -4588,21 +4590,21 @@ static const unsigned char *ecdsa_sign_data(pool *p, const unsigned char *data,
buflen = bufsz = SFTP_MAX_SIG_SZ;
ptr = buf = palloc(p, bufsz);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_DigestInit(pctx, md);
EVP_DigestUpdate(pctx, data, datalen);
EVP_DigestFinal(pctx, dgst, &dgstlen);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
sig = ECDSA_do_sign(dgst, dgstlen, ec);
if (sig == NULL) {
@@ -4620,13 +4622,13 @@ static const unsigned char *ecdsa_sign_data(pool *p, const unsigned char *data,
* selected, so we do no sanity checking of their lengths.
*/
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
ECDSA_SIG_get0(sig, &sig_r, &sig_s);
#else
sig_r = sig->r;
sig_s = sig->s;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
/* XXX Is this buffer large enough? Too large? */
sig_buflen = sig_bufsz = 256;
@@ -5001,9 +5003,9 @@ static int verify_rsa_signed_data(pool *p, EVP_PKEY *pkey,
unsigned char *signature, uint32_t signature_len,
unsigned char *sig_data, size_t sig_datalen, const EVP_MD *md) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
RSA *rsa;
uint32_t len, sig_len;
@@ -5082,21 +5084,21 @@ static int verify_rsa_signed_data(pool *p, EVP_PKEY *pkey,
sig_len = (uint32_t) modulus_len;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_DigestInit(pctx, md);
EVP_DigestUpdate(pctx, sig_data, sig_datalen);
EVP_DigestFinal(pctx, digest, &digest_len);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
ok = RSA_verify(EVP_MD_type(md), digest, digest_len, sig, sig_len, rsa);
if (ok == 1) {
@@ -5143,9 +5145,9 @@ static int dsa_verify_signed_data(pool *p, EVP_PKEY *pkey,
unsigned char *signature, uint32_t signature_len,
unsigned char *sig_data, size_t sig_datalen) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
DSA *dsa;
DSA_SIG *dsa_sig;
@@ -5198,13 +5200,13 @@ static int dsa_verify_signed_data(pool *p, EVP_PKEY *pkey,
}
dsa_sig = DSA_SIG_new();
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
DSA_SIG_get0(dsa_sig, &sig_r, &sig_s);
#else
sig_r = dsa_sig->r;
sig_s = dsa_sig->s;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
sig_r = BN_bin2bn(sig, 20, (BIGNUM *) sig_r);
if (sig_r == NULL) {
@@ -5227,24 +5229,24 @@ static int dsa_verify_signed_data(pool *p, EVP_PKEY *pkey,
return -1;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_DigestInit(pctx, EVP_sha1());
EVP_DigestUpdate(pctx, sig_data, sig_datalen);
EVP_DigestFinal(pctx, digest, &digest_len);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
# if OPENSSL_VERSION_NUMBER >= 0x10100006L
DSA_SIG_set0(dsa_sig, (BIGNUM *) sig_r, (BIGNUM *) sig_s);
# else
@@ -5253,7 +5255,7 @@ static int dsa_verify_signed_data(pool *p, EVP_PKEY *pkey,
#else
dsa_sig->r = sig_r;
dsa_sig->s = sig_s;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
ok = DSA_do_verify(digest, digest_len, dsa_sig, dsa);
if (ok == 1) {
@@ -5277,9 +5279,9 @@ static int ecdsa_verify_signed_data(pool *p, EVP_PKEY *pkey,
unsigned char *signature, uint32_t signature_len,
unsigned char *sig_data, size_t sig_datalen, char *sig_type) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
const EVP_MD *md = NULL;
EC_KEY *ec;
@@ -5329,13 +5331,13 @@ static int ecdsa_verify_signed_data(pool *p, EVP_PKEY *pkey,
return -1;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
ECDSA_SIG_get0(ecdsa_sig, &sig_r, &sig_s);
#else
sig_r = ecdsa_sig->r;
sig_s = ecdsa_sig->s;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
len = sftp_msg_read_mpint2(p, &sig, &sig_len, &sig_r);
if (len == 0) {
@@ -5381,26 +5383,26 @@ static int ecdsa_verify_signed_data(pool *p, EVP_PKEY *pkey,
md = EVP_sha512();
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
pctx = EVP_MD_CTX_new();
#else
pctx = &ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_DigestInit(pctx, md);
EVP_DigestUpdate(pctx, sig_data, sig_datalen);
EVP_DigestFinal(pctx, digest, &digest_len);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
ec = EVP_PKEY_get1_EC_KEY(pkey);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
# if OPENSSL_VERSION_NUMBER >= 0x10100006L
ECDSA_SIG_set0(ecdsa_sig, (BIGNUM *) sig_r, (BIGNUM *) sig_s);
# else
@@ -5409,7 +5411,7 @@ static int ecdsa_verify_signed_data(pool *p, EVP_PKEY *pkey,
#else
ecdsa_sig->r = sig_r;
ecdsa_sig->s = sig_s;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
ok = ECDSA_do_verify(digest, digest_len, ecdsa_sig, ec);
if (ok == 1) {
=====================================
contrib/mod_sftp/mac.c
=====================================
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_sftp MACs
- * Copyright (c) 2008-2022 TJ Saunders
+ * Copyright (c) 2008-2023 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
@@ -107,8 +107,8 @@ static void switch_read_mac(void) {
/* First we can clear the read MAC, kept from rekeying. */
if (read_macs[read_mac_idx].key) {
clear_mac(&(read_macs[read_mac_idx]));
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
HMAC_CTX_reset(hmac_read_ctxs[read_mac_idx]);
#elif OPENSSL_VERSION_NUMBER > 0x000907000L
HMAC_CTX_cleanup(hmac_read_ctxs[read_mac_idx]);
@@ -138,8 +138,8 @@ static void switch_write_mac(void) {
/* First we can clear the write MAC, kept from rekeying. */
if (write_macs[write_mac_idx].key) {
clear_mac(&(write_macs[write_mac_idx]));
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
HMAC_CTX_reset(hmac_write_ctxs[write_mac_idx]);
#elif OPENSSL_VERSION_NUMBER > 0x000907000L
HMAC_CTX_cleanup(hmac_write_ctxs[write_mac_idx]);
@@ -182,8 +182,8 @@ static int init_mac(pool *p, struct sftp_mac *mac, HMAC_CTX *hmac_ctx,
return 0;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
HMAC_CTX_reset(hmac_ctx);
#elif OPENSSL_VERSION_NUMBER > 0x000907000L
HMAC_CTX_init(hmac_ctx);
@@ -431,9 +431,9 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
const unsigned char *k, uint32_t klen, const char *h, uint32_t hlen,
char letter, const unsigned char *id, uint32_t id_len) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
EVP_MD_CTX ctx;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
EVP_MD_CTX *pctx;
unsigned char *key = NULL;
size_t key_sz;
@@ -459,11 +459,11 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
pctx = &ctx;
#else
pctx = EVP_MD_CTX_new();
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
/* In OpenSSL 0.9.6, many of the EVP_Digest* functions returned void, not
* int. Without these ugly OpenSSL version preprocessor checks, the
@@ -475,10 +475,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error initializing message digest: %s", sftp_crypto_get_errors());
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -490,10 +490,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error updating message digest with K: %s", sftp_crypto_get_errors());
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -505,10 +505,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error updating message digest with H: %s", sftp_crypto_get_errors());
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -521,10 +521,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
"error updating message digest with '%c': %s", letter,
sftp_crypto_get_errors());
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -536,10 +536,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"error updating message digest with ID: %s", sftp_crypto_get_errors());
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -552,10 +552,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
"error finalizing message digest: %s", sftp_crypto_get_errors());
pr_memscrub(key, key_sz);
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -577,10 +577,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
"error initializing message digest: %s", sftp_crypto_get_errors());
pr_memscrub(key, key_sz);
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -593,10 +593,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
"error updating message digest with K: %s", sftp_crypto_get_errors());
pr_memscrub(key, key_sz);
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -609,10 +609,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
"error updating message digest with H: %s", sftp_crypto_get_errors());
pr_memscrub(key, key_sz);
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -626,10 +626,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
sftp_crypto_get_errors());
pr_memscrub(key, key_sz);
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -642,10 +642,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
"error finalizing message digest: %s", sftp_crypto_get_errors());
pr_memscrub(key, key_sz);
free(key);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+# if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-# endif /* OpenSSL-1.1.0 and later */
+# endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return -1;
}
#else
@@ -658,10 +658,10 @@ static int set_mac_key(struct sftp_mac *mac, const EVP_MD *hash,
mac->key = key;
mac->keysz = key_sz;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
EVP_MD_CTX_free(pctx);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
if (mac->algo_type == SFTP_MAC_ALGO_TYPE_HMAC) {
mac->key_len = EVP_MD_size(mac->digest);
@@ -1040,18 +1040,18 @@ int sftp_mac_write_data(struct ssh2_packet *pkt) {
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
-/* In older versions of OpenSSL, there was not a way to dynamically allocate
- * an HMAC_CTX object. Thus we have these static objects for those
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
+/* In older versions of OpenSSL/LibreSSL, there was not a way to dynamically
+ * allocate an HMAC_CTX object. Thus we have these static objects for those
* older versions.
*/
static HMAC_CTX read_ctx1, read_ctx2;
static HMAC_CTX write_ctx1, write_ctx2;
-#endif /* prior to OpenSSL-1.1.0 */
+#endif /* prior to OpenSSL-1.1.0/LibreSSL-3.5.0 */
int sftp_mac_init(void) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
hmac_read_ctxs[0] = &read_ctx1;
hmac_read_ctxs[1] = &read_ctx2;
hmac_write_ctxs[0] = &write_ctx1;
@@ -1061,7 +1061,7 @@ int sftp_mac_init(void) {
hmac_read_ctxs[1] = HMAC_CTX_new();
hmac_write_ctxs[0] = HMAC_CTX_new();
hmac_write_ctxs[1] = HMAC_CTX_new();
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
umac_read_ctxs[0] = NULL;
umac_read_ctxs[1] = NULL;
@@ -1072,12 +1072,12 @@ int sftp_mac_init(void) {
}
int sftp_mac_free(void) {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
HMAC_CTX_free(hmac_read_ctxs[0]);
HMAC_CTX_free(hmac_read_ctxs[1]);
HMAC_CTX_free(hmac_write_ctxs[0]);
HMAC_CTX_free(hmac_write_ctxs[1]);
-#endif /* OpenSSL-1.1.0 and later */
+#endif /* OpenSSL-1.1.0/LibreSSL-3.5.0 and later */
return 0;
}
=====================================
contrib/mod_sftp/mod_sftp.c
=====================================
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_sftp
- * Copyright (c) 2008-2022 TJ Saunders
+ * Copyright (c) 2008-2023 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
@@ -1718,8 +1718,9 @@ MODRET set_sftpoptions(cmd_rec *cmd) {
config_rec *c;
unsigned long opts = 0UL;
- if (cmd->argc-1 == 0)
+ if (cmd->argc-1 == 0) {
CONF_ERROR(cmd, "wrong number of parameters");
+ }
CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
@@ -1786,6 +1787,9 @@ MODRET set_sftpoptions(cmd_rec *cmd) {
} else if (strcmp(cmd->argv[i], "NoHostkeyRotation") == 0) {
opts |= SFTP_OPT_NO_HOSTKEY_ROTATION;
+ } else if (strcmp(cmd->argv[i], "NoStrictKex") == 0) {
+ opts |= SFTP_OPT_NO_STRICT_KEX;
+
} else {
CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown SFTPOption '",
cmd->argv[i], "'", NULL));
=====================================
contrib/mod_sftp/mod_sftp.h.in
=====================================
@@ -112,7 +112,12 @@
# include <openssl/provider.h>
#endif /* HAVE_OSSL_PROVIDER_LOAD_OPENSSL */
-/* Define if you have the LibreSSL library. */
+/* Define if you have the LibreSSL library.
+ *
+ * Note that in LibreSSL-3.5.0, the structs became opaque, as they are in
+ * OpenSSL-1.1.0, and thus these version-dependent macros became more
+ * complex.
+ */
#if defined(LIBRESSL_VERSION_NUMBER)
# define HAVE_LIBRESSL 1
#endif
@@ -132,24 +137,25 @@
#define SFTP_SESS_STATE_HAVE_EXT_INFO 0x00010
/* mod_sftp option flags */
-#define SFTP_OPT_IGNORE_SFTP_UPLOAD_PERMS 0x00001
-#define SFTP_OPT_IGNORE_SCP_UPLOAD_PERMS 0x00002
-#define SFTP_OPT_PESSIMISTIC_KEXINIT 0x00004
-#define SFTP_OPT_OLD_PROTO_COMPAT 0x00008
-#define SFTP_OPT_MATCH_KEY_SUBJECT 0x00010
-#define SFTP_OPT_IGNORE_SFTP_SET_PERMS 0x00020
-#define SFTP_OPT_IGNORE_SFTP_SET_TIMES 0x00040
-#define SFTP_OPT_IGNORE_SFTP_SET_OWNERS 0x00080
-#define SFTP_OPT_IGNORE_SCP_UPLOAD_TIMES 0x00100
-#define SFTP_OPT_ALLOW_INSECURE_LOGIN 0x00200
-#define SFTP_OPT_INSECURE_HOSTKEY_PERMS 0x00400
-#define SFTP_OPT_ALLOW_WEAK_DH 0x00800
-#define SFTP_OPT_IGNORE_FIFOS 0x01000
-#define SFTP_OPT_IGNORE_SFTP_UPLOAD_XATTRS 0x02000
-#define SFTP_OPT_IGNORE_SFTP_SET_XATTRS 0x04000
-#define SFTP_OPT_INCLUDE_SFTP_TIMES 0x08000
-#define SFTP_OPT_NO_EXT_INFO 0x10000
-#define SFTP_OPT_NO_HOSTKEY_ROTATION 0x20000
+#define SFTP_OPT_IGNORE_SFTP_UPLOAD_PERMS 0x000001
+#define SFTP_OPT_IGNORE_SCP_UPLOAD_PERMS 0x000002
+#define SFTP_OPT_PESSIMISTIC_KEXINIT 0x000004
+#define SFTP_OPT_OLD_PROTO_COMPAT 0x000008
+#define SFTP_OPT_MATCH_KEY_SUBJECT 0x000010
+#define SFTP_OPT_IGNORE_SFTP_SET_PERMS 0x000020
+#define SFTP_OPT_IGNORE_SFTP_SET_TIMES 0x000040
+#define SFTP_OPT_IGNORE_SFTP_SET_OWNERS 0x000080
+#define SFTP_OPT_IGNORE_SCP_UPLOAD_TIMES 0x000100
+#define SFTP_OPT_ALLOW_INSECURE_LOGIN 0x000200
+#define SFTP_OPT_INSECURE_HOSTKEY_PERMS 0x000400
+#define SFTP_OPT_ALLOW_WEAK_DH 0x000800
+#define SFTP_OPT_IGNORE_FIFOS 0x001000
+#define SFTP_OPT_IGNORE_SFTP_UPLOAD_XATTRS 0x002000
+#define SFTP_OPT_IGNORE_SFTP_SET_XATTRS 0x004000
+#define SFTP_OPT_INCLUDE_SFTP_TIMES 0x008000
+#define SFTP_OPT_NO_EXT_INFO 0x010000
+#define SFTP_OPT_NO_HOSTKEY_ROTATION 0x020000
+#define SFTP_OPT_NO_STRICT_KEX 0x040000
/* mod_sftp service flags */
#define SFTP_SERVICE_FL_SFTP 0x0001
=====================================
contrib/mod_sftp/packet.c
=====================================
@@ -2066,6 +2066,18 @@ int sftp_ssh2_packet_rekey_set_size(off_t size) {
return 0;
}
+uint32_t sftp_ssh2_packet_get_client_seqno(void) {
+ return packet_client_seqno;
+}
+
+void sftp_ssh2_packet_reset_client_seqno(void) {
+ packet_client_seqno = 0;
+}
+
+void sftp_ssh2_packet_reset_server_seqno(void) {
+ packet_server_seqno = 0;
+}
+
int sftp_ssh2_packet_send_version(void) {
if (!sent_version_id) {
int res;
=====================================
contrib/mod_sftp/packet.h
=====================================
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_sftp packet IO
- * Copyright (c) 2008-2021 TJ Saunders
+ * Copyright (c) 2008-2023 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
@@ -117,6 +117,13 @@ int sftp_ssh2_packet_rekey_reset(void);
int sftp_ssh2_packet_rekey_set_seqno(uint32_t);
int sftp_ssh2_packet_rekey_set_size(off_t);
+/* These are used for implementing the "strict KEX" mitigations of the Terrapin
+ * attack (Issue 1760).
+ */
+uint32_t sftp_ssh2_packet_get_client_seqno(void);
+void sftp_ssh2_packet_reset_client_seqno(void);
+void sftp_ssh2_packet_reset_server_seqno(void);
+
int sftp_ssh2_packet_send_version(void);
int sftp_ssh2_packet_set_poll_timeout(int);
int sftp_ssh2_packet_set_version(const char *);
=====================================
contrib/mod_sftp/tap.c
=====================================
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_sftp traffic analysis protection
- * Copyright (c) 2008-2016 TJ Saunders
+ * Copyright (c) 2008-2023 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
@@ -149,7 +149,6 @@ static void set_policy_chance(struct sftp_tap_policy *policy) {
}
static void set_policy_timer(struct sftp_tap_policy *policy) {
-
/* Start a timer which checks the last times we received and sent packets.
* From there, we may want to inject a TAP message, depending on the
* policy.
@@ -177,6 +176,16 @@ int sftp_tap_send_packet(void) {
int rnd;
unsigned int chance;
+ /* Due to chances of violating client-side "strict KEX" Terrapin
+ * mitigations, we will not send packets if we are in the middle of a KEX.
+ */
+ if (!(sftp_sess_state & SFTP_SESS_STATE_HAVE_KEX) ||
+ (sftp_sess_state & SFTP_SESS_STATE_REKEYING)) {
+ pr_trace_msg(trace_channel, 11,
+ "unwilling to send TAP packet during KEX");
+ return 0;
+ }
+
if (!sftp_interop_supports_feature(SFTP_SSH2_FEAT_IGNORE_MSG)) {
pr_trace_msg(trace_channel, 3,
"unable to send TAP packet: IGNORE not supported by client");
@@ -205,7 +214,7 @@ int sftp_tap_send_packet(void) {
struct ssh2_packet *pkt;
unsigned int max_datalen = 8192;
- if (curr_policy.max_datalen) {
+ if (curr_policy.max_datalen > 0) {
max_datalen = curr_policy.max_datalen;
}
@@ -246,15 +255,15 @@ int sftp_tap_send_packet(void) {
int sftp_tap_set_policy(const char *policy) {
register unsigned int i;
- if (tap_pool) {
+ if (tap_pool != NULL) {
/* Special case: IFF the existing policy is 'none' AND the given
* policy is 'rogaway', just return. The 'none' policy must have been
* explicitly configured, and it should override the automatic use of
* the 'rogaway' policy.
*/
- if (strncmp(curr_policy.policy, "none", 5) == 0 &&
- strncasecmp(policy, "rogaway", 8) == 0) {
+ if (strcasecmp(curr_policy.policy, "none") == 0 &&
+ strcasecmp(policy, "rogaway") == 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"'none' traffic policy explicitly configured, ignoring '%s' policy",
policy);
@@ -278,7 +287,6 @@ int sftp_tap_set_policy(const char *policy) {
if (strcasecmp(tap_policies[i].policy, policy) == 0) {
copy_policy(&curr_policy, &(tap_policies[i]));
set_policy_chance(&curr_policy);
- set_policy_timer(&curr_policy);
return 0;
}
}
@@ -286,3 +294,7 @@ int sftp_tap_set_policy(const char *policy) {
errno = ENOENT;
return -1;
}
+
+void sftp_tap_start_policy(void) {
+ set_policy_timer(&curr_policy);
+}
=====================================
contrib/mod_sftp/tap.h
=====================================
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_sftp traffic analysis protection
- * Copyright (c) 2008-2016 TJ Saunders
+ * Copyright (c) 2008-2013 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
@@ -63,4 +63,7 @@ int sftp_tap_send_packet(void);
*/
int sftp_tap_set_policy(const char *);
+/* Sets the configured TAP policy in motion. */
+void sftp_tap_start_policy(void);
+
#endif /* MOD_SFTP_TAP_H */
=====================================
contrib/mod_tls.c
=====================================
@@ -42,7 +42,12 @@
# include "mod_ctrls.h"
#endif
-/* Define if you have the LibreSSL library. */
+/* Define if you have the LibreSSL library.
+ *
+ * Note that in LibreSSL-3.5.0, the structs became opaque, as they are in
+ * OpenSSL-1.1.0, and thus these version-dependent macros became more
+ * complex.
+ */
#if defined(LIBRESSL_VERSION_NUMBER)
# define HAVE_LIBRESSL 1
#endif
@@ -100,8 +105,8 @@ static DH *get_dh(BIGNUM *p, BIGNUM *g) {
return NULL;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
if (DH_set0_pqg(dh, p, NULL, g) != 1) {
pr_trace_msg(trace_channel, 3, "error setting DH p/q parameters: %s",
ERR_error_string(ERR_get_error(), NULL));
@@ -111,7 +116,7 @@ static DH *get_dh(BIGNUM *p, BIGNUM *g) {
#else
dh->p = p;
dh->g = g;
-#endif /* OpenSSL 1.1.x and later */
+#endif /* OpenSSL 1.1.x/LibreSSL-3.5.x and later */
return dh;
}
@@ -120,14 +125,14 @@ static X509 *read_cert(FILE *fh, SSL_CTX *ctx) {
pem_password_cb *cb;
void *cb_data;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
cb = SSL_CTX_get_default_passwd_cb(ctx);
cb_data = SSL_CTX_get_default_passwd_cb_userdata(ctx);
#else
cb = ctx->default_passwd_callback;
cb_data = ctx->default_passwd_callback_userdata;
-#endif /* OpenSSL-1.1.x and later */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x and later */
return PEM_read_X509(fh, NULL, cb, cb_data);
}
@@ -681,7 +686,7 @@ static char *tls_dsa_cert_file = NULL, *tls_dsa_key_file = NULL;
static char *tls_pkcs12_file = NULL;
static char *tls_rsa_cert_file = NULL, *tls_rsa_key_file = NULL;
static char *tls_rand_file = NULL;
-#if !defined(OPENSSL_NO_TLSEXT) && \
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(HAVE_LIBRESSL) && \
OPENSSL_VERSION_NUMBER >= 0x10002000L
static char *tls_serverinfo_file = NULL;
#endif /* OPENSSL_NO_TLSEXT */
@@ -2743,9 +2748,8 @@ static int tls_cert_match_ip_san(pool *p, X509 *cert, const char *ipstr) {
return matched;
}
-static int tls_cert_match_cn(pool *p, X509 *cert, const char *name,
- int allow_wildcards) {
- int matched = 0, idx = -1;
+static char *tls_get_cert_cn(pool *p, X509 *cert) {
+ int idx = -1;
X509_NAME *subj_name = NULL;
X509_NAME_ENTRY *cn_entry = NULL;
ASN1_STRING *cn_asn1 = NULL;
@@ -2757,36 +2761,29 @@ static int tls_cert_match_cn(pool *p, X509 *cert, const char *name,
*/
subj_name = X509_get_subject_name(cert);
if (subj_name == NULL) {
- pr_trace_msg(trace_channel, 12,
- "unable to check certificate CommonName against '%s': "
- "unable to get Subject", name);
- return 0;
+ errno = ENOENT;
+ return NULL;
}
idx = X509_NAME_get_index_by_NID(subj_name, NID_commonName, -1);
if (idx < 0) {
- pr_trace_msg(trace_channel, 12,
- "unable to check certificate CommonName against '%s': "
- "no CommoName attribute found", name);
- return 0;
+ errno = ENOENT;
+ return NULL;
}
cn_entry = X509_NAME_get_entry(subj_name, idx);
if (cn_entry == NULL) {
- pr_trace_msg(trace_channel, 12,
- "unable to check certificate CommonName against '%s': "
- "error obtaining CommoName attribute found: %s", name, tls_get_errors());
- return 0;
+ errno = ENOENT;
+ return NULL;
}
/* Convert the CN field to a string, by way of an ASN1 object. */
cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry);
if (cn_asn1 == NULL) {
pr_trace_msg(trace_channel, 12,
- "unable to check certificate CommonName against '%s': "
- "error converting CommoName attribute to ASN.1: %s", name,
- tls_get_errors());
- return 0;
+ "error converting CommoName attribute to ASN.1: %s", tls_get_errors());
+ errno = EPERM;
+ return NULL;
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
@@ -2810,6 +2807,20 @@ static int tls_cert_match_cn(pool *p, X509 *cert, const char *name,
tls_log("suspicious CommonName value: '%s'",
get_printable_subjaltname(p, (const char *) cn_str,
ASN1_STRING_length(cn_asn1)));
+ errno = EPERM;
+ return NULL;
+ }
+
+ return pstrdup(p, cn_str);
+}
+
+static int tls_cert_match_cn(pool *p, X509 *cert, const char *name,
+ int allow_wildcards) {
+ int matched = 0;
+ char *cert_cn = NULL;
+
+ cert_cn = tls_get_cert_cn(p, cert);
+ if (cert_cn == NULL) {
return 0;
}
@@ -2818,16 +2829,16 @@ static int tls_cert_match_cn(pool *p, X509 *cert, const char *name,
* the case-insensitivity won't hurt anything. In fact, it's needed for
* e.g. IPv6 addresses.
*/
- if (strncasecmp(name, cn_str, cn_len + 1) == 0) {
+ if (strcasecmp(name, cert_cn) == 0) {
matched = 1;
}
if (matched == 0 &&
- allow_wildcards) {
+ allow_wildcards == TRUE) {
/* XXX Implement wildcard checking. */
}
-
+
return matched;
}
@@ -4033,13 +4044,13 @@ static int tls_renegotiate_timeout_cb(CALLBACK_FRAME) {
int ctrl_renegotiated = FALSE;
switch (SSL_version(ctrl_ssl)) {
-# if defined(TLS1_3_VERSION)
+# if defined(TLS1_3_VERSION) && !defined(HAVE_LIBRESSL)
case TLS1_3_VERSION:
if (SSL_get_key_update_type(ctrl_ssl) == SSL_KEY_UPDATE_NONE) {
ctrl_renegotiated = TRUE;
}
break;
-# endif /* TLS1_3_VERSION */
+# endif /* TLS1_3_VERSION and no LibreSSL */
default:
if (SSL_renegotiate_pending(ctrl_ssl) == 0) {
@@ -4069,13 +4080,13 @@ static int tls_renegotiate_timeout_cb(CALLBACK_FRAME) {
ssl = (SSL *) pr_table_get(tls_data_wr_nstrm->notes, TLS_NETIO_NOTE, NULL);
switch (SSL_version(ssl)) {
-# if defined(TLS1_3_VERSION)
+# if defined(TLS1_3_VERSION) && !defined(HAVE_LIBRESSL)
case TLS1_3_VERSION:
if (SSL_get_key_update_type(ssl) == SSL_KEY_UPDATE_NONE) {
data_renegotiated = TRUE;
}
break;
-# endif /* TLS1_3_VERSION */
+# endif /* TLS1_3_VERSION and no LibreSSL */
default:
if (SSL_renegotiate_pending(ssl) == 0) {
@@ -4109,7 +4120,7 @@ static int tls_ctrl_renegotiate_cb(CALLBACK_FRAME) {
if (tls_flags & TLS_SESS_ON_CTRL) {
switch (SSL_version(ctrl_ssl)) {
-#if defined(TLS1_3_VERSION)
+#if defined(TLS1_3_VERSION) && !defined(HAVE_LIBRESSL)
/* If we're a TLSv1.3 session, use SSL_key_update() to request new
* session keys; TLSv1.3 does not support renegotiations.
*/
@@ -4131,7 +4142,7 @@ static int tls_ctrl_renegotiate_cb(CALLBACK_FRAME) {
}
}
break;
-#endif /* TLS1_3_VERSION */
+#endif /* TLS1_3_VERSION and no LibreSSL */
default: {
#if OPENSSL_VERSION_NUMBER >= 0x009080cfL
@@ -4536,12 +4547,12 @@ static int tls_sni_cb(SSL *ssl, int *alert_desc, void *user_data) {
ctx = SSL_get_SSL_CTX(ssl);
ctx_options = SSL_CTX_get_options(ctx);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
sess_version = SSL_SESSION_get_protocol_version(sess);
#else
sess_version = sess->ssl_version;
-#endif /* OpenSSL 1.1.x and later */
+#endif /* OpenSSL 1.1.x/LibreSSL-3.5.x and later */
switch (sess_version) {
case SSL3_VERSION:
@@ -5720,7 +5731,7 @@ static OCSP_RESPONSE *ocsp_request_response(pool *p, X509 *cert, SSL *ssl,
}
#if OPENSSL_VERSION_NUMBER < 0x10002000L || \
- defined(HAVE_LIBRESSL)
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x3050000L)
/* We need to provide our own backport of the ASN1_TIME_diff() function. */
static time_t ASN1_TIME_seconds(const ASN1_TIME *a) {
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
@@ -6191,8 +6202,8 @@ static int tls_cert_must_staple(X509 *cert, int *v2) {
register int i;
int ext_count = 0, must_staple = FALSE;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
ext_count = X509_get_ext_count(cert);
#else
X509_CINF *ci;
@@ -6205,19 +6216,19 @@ static int tls_cert_must_staple(X509 *cert, int *v2) {
exts = ci->extensions;
ext_count = sk_X509_EXTENSION_num(exts);
-#endif /* Before OpenSSL-1.1.0, or libressl */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x or later */
for (i = 0; i < ext_count; i++) {
char buf[1024];
X509_EXTENSION *ext;
ASN1_OBJECT *obj;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
ext = X509_get_ext(cert, i);
#else
ext = sk_X509_EXTENSION_value(exts, i);
-#endif /* Before OpenSSL-1.1.0, or libressl */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x or later */
obj = X509_EXTENSION_get_object(ext);
memset(buf, '\0', sizeof(buf));
@@ -6228,12 +6239,12 @@ static int tls_cert_must_staple(X509 *cert, int *v2) {
char status_request[] = TLS_X509V3_TLS_FEAT_STATUS_REQUEST;
ASN1_OCTET_STRING *value;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
value = X509_EXTENSION_get_data(ext);
#else
value = ext->value;
-#endif /* Before OpenSSL-1.1.0, or libressl */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x or later */
/* Is the value of this extension the "status_request" value? */
must_staple = tls_feature_cmp(value, status_request, 5);
@@ -7892,7 +7903,7 @@ static int tls_accept(conn_t *conn, unsigned char on_data) {
break;
}
-#if defined(SSL_R_VERSION_TOO_LOW)
+#if defined(SSL_R_VERSION_TOO_LOW) && !defined(HAVE_LIBRESSL)
case SSL_R_VERSION_TOO_LOW: {
int client_version;
@@ -9310,14 +9321,14 @@ static int tls_dotlogin_allow(const char *user) {
pr_signals_handle();
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
X509_get0_signature(&client_sig, NULL, client_cert);
X509_get0_signature(&file_sig, NULL, file_cert);
#else
client_sig = client_cert->signature;
file_sig = file_cert->signature;
-#endif /* OpenSSL-1.1.x and later */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x and later */
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (!ASN1_STRING_cmp(client_sig, file_sig)) {
@@ -9947,8 +9958,8 @@ static void tls_setup_cert_environ(pool *p, const char *env_prefix,
if (tls_opts & TLS_OPT_STD_ENV_VARS) {
char buf[80] = {'\0'};
ASN1_INTEGER *serial = X509_get_serialNumber(cert);
- const X509_ALGOR *algo;
- X509_PUBKEY *pubkey;
+ const X509_ALGOR *algo = NULL;
+ X509_PUBKEY *pubkey = NULL;
memset(buf, '\0', sizeof(buf));
pr_snprintf(buf, sizeof(buf) - 1, "%lu", X509_get_version(cert) + 1);
@@ -10024,12 +10035,12 @@ static void tls_setup_cert_environ(pool *p, const char *env_prefix,
BIO_free(bio);
bio = BIO_new(BIO_s_mem());
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
X509_get0_signature(NULL, &algo, cert);
#else
algo = cert->cert_info->signature;
-#endif /* OpenSSL-1.1.x and later */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x and later */
i2a_ASN1_OBJECT(bio, algo->algorithm);
datalen = BIO_get_mem_data(bio, &data);
data[datalen] = '\0';
@@ -10041,13 +10052,13 @@ static void tls_setup_cert_environ(pool *p, const char *env_prefix,
BIO_free(bio);
bio = BIO_new(BIO_s_mem());
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
- pubkey = X509_get_X509_PUBKEY(cert);
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
X509_PUBKEY_get0_param(NULL, NULL, NULL, (X509_ALGOR **) &algo, pubkey);
#else
pubkey = cert->cert_info->key;
algo = pubkey->algor;
-#endif /* OpenSSL-1.1.x and later */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x and later */
i2a_ASN1_OBJECT(bio, algo->algorithm);
datalen = BIO_get_mem_data(bio, &data);
data[datalen] = '\0';
@@ -10214,6 +10225,7 @@ static void tls_setup_environ(pool *p, SSL *ssl) {
}
static void tls_setup_notes(pool *p, SSL *ssl) {
+ X509 *client_cert = NULL;
SSL_CIPHER *cipher = NULL;
const char *sni = NULL;
@@ -10226,15 +10238,61 @@ static void tls_setup_notes(pool *p, SSL *ssl) {
if (cipher != NULL) {
(void) pr_table_add_dup(session.notes, "TLS_CIPHER",
SSL_CIPHER_get_name(cipher), 0);
+ }
- sni = pr_table_get(session.notes, "mod_tls.sni", NULL);
- if (sni != NULL) {
- (void) pr_table_add_dup(session.notes, "TLS_SERVER_NAME", sni, 0);
+ sni = pr_table_get(session.notes, "mod_tls.sni", NULL);
+ if (sni != NULL) {
+ (void) pr_table_add_dup(session.notes, "TLS_SERVER_NAME", sni, 0);
+ }
+
+ client_cert = SSL_get_peer_certificate(ssl);
+ if (client_cert != NULL) {
+ const X509_ALGOR *algo = NULL;
+ X509_PUBKEY *pubkey = NULL;
+ BIO *bio = NULL;
+ char *data = NULL;
+ long datalen = 0;
+
+ /* Client cert CN */
+ data = tls_get_cert_cn(p, client_cert);
+ if (data != NULL) {
+ (void) pr_table_add_dup(session.notes, "TLS_CLIENT_S_DN_CN", data, 0);
}
- (void) pr_table_add_dup(session.notes, "TLS_LIBRARY_VERSIONS",
- OPENSSL_VERSION_TEXT, 0);
+ /* Client cert key algo */
+ bio = BIO_new(BIO_s_mem());
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ pubkey = X509_get_X509_PUBKEY(client_cert);
+ X509_PUBKEY_get0_param(NULL, NULL, NULL, (X509_ALGOR **) &algo, pubkey);
+#else
+ pubkey = client_cert->cert_info->key;
+ algo = pubkey->algor;
+#endif /* OpenSSL-1.1.x and later */
+ i2a_ASN1_OBJECT(bio, algo->algorithm);
+ datalen = BIO_get_mem_data(bio, &data);
+ data[datalen] = '\0';
+
+ (void) pr_table_add_dup(session.notes, "TLS_CLIENT_A_KEY", data, 0);
+ BIO_free(bio);
+
+ /* Client cert signature algorithm. */
+ bio = BIO_new(BIO_s_mem());
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
+ X509_get0_signature(NULL, &algo, client_cert);
+#else
+ algo = client_cert->cert_info->signature;
+#endif /* OpenSSL-1.1.x/Libre-3.5.x and later */
+ i2a_ASN1_OBJECT(bio, algo->algorithm);
+ datalen = BIO_get_mem_data(bio, &data);
+ data[datalen] = '\0';
+
+ (void) pr_table_add_dup(session.notes, "TLS_CLIENT_A_SIG", data, 0);
+ BIO_free(bio);
}
+
+ (void) pr_table_add_dup(session.notes, "TLS_LIBRARY_VERSION",
+ OPENSSL_VERSION_TEXT, 0);
}
static int tls_verify_cb(int ok, X509_STORE_CTX *ctx) {
@@ -10611,12 +10669,12 @@ static int tls_verify_crl(int ok, X509_STORE_CTX *ctx) {
if (revoked == NULL) {
continue;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
sn = X509_REVOKED_get0_serialNumber(revoked);
#else
sn = revoked->serialNumber;
-#endif /* OpenSSL-1.1.x and later */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x and later */
if (ASN1_INTEGER_cmp(sn, X509_get_serialNumber(xs)) == 0) {
long serial = ASN1_INTEGER_get(sn);
@@ -10877,12 +10935,12 @@ static int tls_verify_ocsp_url(X509_STORE_CTX *ctx, X509 *cert,
return FALSE;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !defined(HAVE_LIBRESSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(HAVE_LIBRESSL)) || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER >= 0x3050000L)
store = X509_STORE_CTX_get0_store(ctx);
#else
store = ctx->ctx;
-#endif /* OpenSSL-1.1.x and later */
+#endif /* OpenSSL-1.1.x/LibreSSL-3.5.x and later */
res = OCSP_basic_verify(basic_resp, NULL, store, 0);
if (res != 1) {
tls_log("error verifying basic response from OCSP responder at '%s': %s",
@@ -12350,7 +12408,7 @@ static void tls_data_renegotiate(SSL *ssl) {
tls_data_renegotiate_current >= tls_data_renegotiate_limit) {
switch (SSL_version(ssl)) {
-# if defined(TLS1_3_VERSION)
+# if defined(TLS1_3_VERSION) && !defined(HAVE_LIBRESSL)
/* If we're a TLSv1.3 session, use SSL_key_update() to request new
* session keys; TLSv1.3 does not support renegotiations.
*/
@@ -12373,7 +12431,7 @@ static void tls_data_renegotiate(SSL *ssl) {
}
}
break;
-# endif /* TLS1_3_VERSION */
+# endif /* TLS1_3_VERSION and no LibreSSL */
default: {
tls_flags |= TLS_SESS_DATA_RENEGOTIATING;
=====================================
doc/contrib/mod_sftp.html
=====================================
@@ -1311,6 +1311,19 @@ The currently implemented options are:
<code>proftpd-1.3.8rc3</code>.
</li>
+ <p>
+ <li><code>NoStrictKex</code><br>
+ <p>
+ By default, <code>mod_sftp</code> will honor/support the OpenSSH
+ "strict KEX" mode extension, "kex-strict-c-v00 at openssh.com" and
+ "kex-strict-s-v00 at openssh.com". Use this option to disable support for
+ these custom OpenSSH extensions.
+
+ <p>
+ <b>Note</b> that this option first appeared in
+ <code>proftpd-1.3.9rc1</code>.
+ </li>
+
<p>
<li><code>OldProtocolCompat</code><br>
<p>
@@ -2843,7 +2856,7 @@ deal with this issue, then, you can hopefully upgrade to ProFTPD 1.3.6 or later,
<p>
<hr>
<font size=2><b><i>
-© Copyright 2008-2022 TJ Saunders<br>
+© Copyright 2008-2023 TJ Saunders<br>
All Rights Reserved<br>
</i></b></font>
<hr>
=====================================
include/version.h
=====================================
@@ -28,8 +28,8 @@
#include "buildstamp.h"
/* Application version (in various forms) */
-#define PROFTPD_VERSION_NUMBER 0x0001030806
-#define PROFTPD_VERSION_TEXT "1.3.8a"
+#define PROFTPD_VERSION_NUMBER 0x0001030807
+#define PROFTPD_VERSION_TEXT "1.3.8b"
/* Module API version */
#define PR_MODULE_API_VERSION 0x20
=====================================
tests/t/lib/ProFTPD/Tests/Modules/mod_sftp.pm
=====================================
@@ -87,6 +87,11 @@ my $TESTS = {
test_class => [qw(forking ssh2)],
},
+ ssh2_ext_kex_strict_terrapin_issue1760 => {
+ order => ++$order,
+ test_class => [qw(bug forking ssh2)],
+ },
+
ssh2_hostkey_rsa => {
order => ++$order,
test_class => [qw(forking ssh2)],
@@ -4012,6 +4017,218 @@ EOC
unlink($log_file);
}
+sub ssh2_ext_kex_strict_terrapin_issue1760 {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+ my $setup = test_setup($tmpdir, 'sftp');
+
+ my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key');
+ my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key');
+
+ my $rsa_priv_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key');
+ my $rsa_pub_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/test_rsa_key.pub');
+ my $rsa_rfc4716_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/authorized_rsa_keys');
+
+ my $authorized_keys = File::Spec->rel2abs("$tmpdir/.authorized_keys");
+ unless (copy($rsa_rfc4716_key, $authorized_keys)) {
+ die("Can't copy $rsa_rfc4716_key to $authorized_keys: $!");
+ }
+
+ my $ssh_config = File::Spec->rel2abs("$tmpdir/ssh.conf");
+ if (open(my $fh, "> $ssh_config")) {
+ print $fh <<EOC;
+HostKeyAlgorithms rsa-sha2-256
+IdentityAgent none
+PubkeyAcceptedKeyTypes rsa-sha2-256
+EOC
+ unless (close($fh)) {
+ die("Can't write $ssh_config: $!");
+ }
+
+ } else {
+ die("Can't open $ssh_config: $!");
+ }
+
+ my $batch_file = File::Spec->rel2abs("$tmpdir/sftp-batch.conf");
+ if (open(my $fh, "> $batch_file")) {
+ print $fh "ls -l\n";
+
+ unless (close($fh)) {
+ die("Can't write $batch_file: $!");
+ }
+
+ } else {
+ die("Can't open $batch_file: $!");
+ }
+
+ my $config = {
+ PidFile => $setup->{pid_file},
+ ScoreboardFile => $setup->{scoreboard_file},
+ SystemLog => $setup->{log_file},
+ TraceLog => $setup->{log_file},
+ Trace => 'ssh2:30 sftp:20 scp:20',
+
+ AuthUserFile => $setup->{auth_user_file},
+ AuthGroupFile => $setup->{auth_group_file},
+ AuthOrder => 'mod_auth_file.c',
+
+ IfModules => {
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+
+ 'mod_sftp.c' => [
+ "SFTPEngine on",
+ "SFTPLog $setup->{log_file}",
+
+ "SFTPHostKey $rsa_host_key",
+ "SFTPHostKey $dsa_host_key",
+
+ "SFTPAuthorizedUserKeys file:~/.authorized_keys",
+ ],
+ },
+ };
+
+ 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: $!");
+ }
+
+ require Net::SSH2;
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ # We use OpenSSH-9.6p1 to test our "strict KEX" Terrapin mitigations.
+ my $sftp = '/Users/tj/local/openssh-9.6p1/bin/sftp';
+
+ my @cmd = (
+ $sftp,
+ '-F',
+ $ssh_config,
+ '-oBatchMode=yes',
+ '-oCheckHostIP=no',
+ '-oCompression=yes',
+ "-oPort=$port",
+ "-oIdentityFile=$rsa_priv_key",
+ '-oPubkeyAuthentication=yes',
+ '-oStrictHostKeyChecking=no',
+ '-oUserKnownHostsFile=/dev/null',
+ '-vvv',
+ '-b',
+ $batch_file,
+ "$setup->{user}\@127.0.0.1",
+ );
+
+ my $sftp_rh = IO::Handle->new();
+ my $sftp_wh = IO::Handle->new();
+ my $sftp_eh = IO::Handle->new();
+
+ $sftp_wh->autoflush(1);
+
+ sleep(1);
+
+ local $SIG{CHLD} = 'DEFAULT';
+
+ # Make sure that the perms on the priv key are what OpenSSH wants
+ unless (chmod(0400, $rsa_priv_key)) {
+ die("Can't set perms on $rsa_priv_key to 0400: $!");
+ }
+
+ if ($ENV{TEST_VERBOSE}) {
+ print STDERR "Executing: ", join(' ', @cmd), "\n";
+ }
+
+ my $sftp_pid = open3($sftp_wh, $sftp_rh, $sftp_eh, @cmd);
+ waitpid($sftp_pid, 0);
+ my $exit_status = $?;
+
+ # Restore the perms on the priv key
+ unless (chmod(0644, $rsa_priv_key)) {
+ die("Can't set perms on $rsa_priv_key to 0644: $!");
+ }
+
+ my ($res, $errstr);
+ if ($exit_status >> 8 == 0) {
+ $errstr = join('', <$sftp_eh>);
+ $res = 0;
+
+ } else {
+ $errstr = join('', <$sftp_eh>);
+ if ($ENV{TEST_VERBOSE}) {
+ print STDERR "Stderr: $errstr\n";
+ }
+
+ $res = 1;
+ }
+
+ unless ($res == 0) {
+ die("Can't list files on server: $errstr");
+ }
+ };
+ 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 =~ /client signaled strict KEX support/) {
+ $ok = 1;
+ last;
+ }
+ }
+
+ close($fh);
+
+ $self->assert($ok, test_msg("Did not see expected 'strict KEX' TraceLog message"));
+
+ } else {
+ die("Can't read $setup->{log_file}: $!");
+ }
+ };
+ if ($@) {
+ $ex = $@;
+ }
+
+ test_cleanup($setup->{log_file}, $ex);
+}
+
sub ssh2_hostkey_rsa {
my $self = shift;
my $tmpdir = $self->{tmpdir};
View it on GitLab: https://salsa.debian.org/debian-proftpd-team/proftpd/-/commit/209e4d5c3a76eb00c9adf2f8f1eace39bef1fcc7
--
View it on GitLab: https://salsa.debian.org/debian-proftpd-team/proftpd/-/commit/209e4d5c3a76eb00c9adf2f8f1eace39bef1fcc7
You're receiving this email because of your account on salsa.debian.org.
More information about the Pkg-proftpd-maintainers
mailing list