From edec970dadf041aa188dd8ebf1e3fe140b06ee3f Mon Sep 17 00:00:00 2001 From: zouzhimin Date: Tue, 11 Jun 2024 11:37:42 +0800 Subject: [PATCH] Add support for GnuTLS --- backport-Add-support-for-GnuTLS.patch | 370 +++++++++++++++++++ booth.spec | 18 +- pacemaker-Check-snprintf-return-values.patch | 124 +++++++ 3 files changed, 508 insertions(+), 4 deletions(-) create mode 100644 backport-Add-support-for-GnuTLS.patch create mode 100644 pacemaker-Check-snprintf-return-values.patch diff --git a/backport-Add-support-for-GnuTLS.patch b/backport-Add-support-for-GnuTLS.patch new file mode 100644 index 0000000..d135e07 --- /dev/null +++ b/backport-Add-support-for-GnuTLS.patch @@ -0,0 +1,370 @@ +From 2958d1835f5bc75caad863916a259cfc700cd988 Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Wed, 14 Feb 2024 17:20:32 +0100 +Subject: [PATCH 1/3] configure: Add option to select HMAC library + +Signed-off-by: Jan Friesse +--- + configure.ac | 40 +++++++++++++++++++++++++++------------- + 1 file changed, 27 insertions(+), 13 deletions(-) + +diff --git a/configure.ac b/configure.ac +index eff027e..c36e9c3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -73,19 +73,6 @@ AM_CONDITIONAL(IS_ASCIIDOC, test x"${ASCIIDOC}" != x"") + AM_CONDITIONAL(IS_A2X, test x"${A2X}" != x"") + AM_CONDITIONAL(BUILD_ASCIIDOC, test x"${A2X}" != x"" || test x"${ASCIIDOCTOR}" != x"") + +-# libgcrypt or mhash for hmac +-libgcrypt_installed="yes" +-AC_CHECK_HEADERS(gcrypt.h, , [libgcrypt_installed="no"],) +-AC_CHECK_LIB(gcrypt, gcry_md_open, , [libgcrypt_installed="no"]) +-AM_CONDITIONAL(BUILD_AUTH_C, test "x${libgcrypt_installed}" = "xyes") +- +-if test "x$libgcrypt_installed" = "xno"; then +- mhash_installed="yes" +- AC_CHECK_HEADERS(mhash.h, , [mhash_installed="no"],) +- AC_CHECK_LIB(mhash, mhash_init, , [mhash_installed="no"]) +- AM_CONDITIONAL(BUILD_AUTH_C, test "x${mhash_installed}" = "xyes") +-fi +- + AC_CHECK_LIB([xml2], xmlReadDoc) + PKG_CHECK_MODULES(XML, [libxml-2.0]) + PKG_CHECK_MODULES(GLIB, [glib-2.0]) +@@ -247,6 +234,33 @@ AC_ARG_WITH([ocfdir], + + AC_SUBST([ocfdir]) + ++AC_ARG_WITH([hmac_library], ++ [ --with-hmac-library=LIBRARY : Select HMAC library to use (default: autodetect one of gcrypt or mhash).]) ++ ++# libgcrypt or mhash for hmac ++hmac_library_installed="no" ++if test "x$with_hmac_library" == "x" && test "x$hmac_library_installed" == "xno" || \ ++ test "x$with_hmac_library" == "xgcrypt"; then ++ libgcrypt_installed="yes" ++ AC_CHECK_HEADERS(gcrypt.h, , [libgcrypt_installed="no"],) ++ AC_CHECK_LIB(gcrypt, gcry_md_open, , [libgcrypt_installed="no"]) ++ hmac_library_installed="${libgcrypt_installed}" ++fi ++ ++if test "x$with_hmac_library" == "x" && test "x$hmac_library_installed" == "xno" || \ ++ test "x$with_hmac_library" == "xmhash"; then ++ mhash_installed="yes" ++ AC_CHECK_HEADERS(mhash.h, , [mhash_installed="no"],) ++ AC_CHECK_LIB(mhash, mhash_init, , [mhash_installed="no"]) ++ hmac_library_installed="${mhash_installed}" ++fi ++ ++if test "x$with_hmac_library" != "x" && test "x$hmac_library_installed" == "xno";then ++ AC_MSG_ERROR([required HMAC library not detected]) ++fi ++ ++AM_CONDITIONAL(BUILD_AUTH_C, test "x${hmac_library_installed}" = "xyes") ++ + # figure out logging provider + logging_provider="" + if test "x$logging_provider" = "x" && test "x$with_glue" = "xyes"; then +-- +2.25.1 + +From a0aa2de8814fd32ae6b1193df54db6872dc324fa Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Thu, 15 Feb 2024 17:02:23 +0100 +Subject: [PATCH 2/3] Add support for GnuTLS + +Signed-off-by: Jan Friesse +--- + booth.spec.in | 2 +- + configure.ac | 18 +++++++++--- + src/auth.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ + src/auth.h | 19 ++++++++++++ + src/config.c | 2 +- + src/main.c | 13 +++++++++ + src/transport.c | 6 ++-- + 7 files changed, 129 insertions(+), 9 deletions(-) + +diff --git a/booth.spec.in b/booth.spec.in +index 9f67fff..4961763 100644 +--- a/booth.spec.in ++++ b/booth.spec.in +@@ -72,7 +72,7 @@ BuildRequires: firewall-macros + %else + BuildRequires: pkgconfig(glib-2.0) + %endif +-BuildRequires: libgcrypt-devel ++BuildRequires: gnutls-devel + %if 0%{?fedora} || 0%{?centos} || 0%{?rhel} + BuildRequires: pacemaker-libs-devel + %else +diff --git a/configure.ac b/configure.ac +index c36e9c3..4c4a0af 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -235,10 +235,20 @@ AC_ARG_WITH([ocfdir], + AC_SUBST([ocfdir]) + + AC_ARG_WITH([hmac_library], +- [ --with-hmac-library=LIBRARY : Select HMAC library to use (default: autodetect one of gcrypt or mhash).]) ++ [ --with-hmac-library=LIBRARY : Select HMAC library to use (default: autodetect one of gnutls, gcrypt or mhash).]) + +-# libgcrypt or mhash for hmac ++# GnuTLS, libgcrypt or mhash for hmac + hmac_library_installed="no" ++if test "x$with_hmac_library" == "x" && test "x$hmac_library_installed" == "xno" || \ ++ test "x$with_hmac_library" == "xgnutls"; then ++ libgnutls_installed="yes" ++ PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 2.10.0], [ ++ AC_DEFINE([HAVE_LIBGNUTLS], [1], [Have gnutls library]) ++ libgnutls_installed="yes" ++ ], [libgnutls_installed="no"]) ++ hmac_library_installed="${libgnutls_installed}" ++fi ++ + if test "x$with_hmac_library" == "x" && test "x$hmac_library_installed" == "xno" || \ + test "x$with_hmac_library" == "xgcrypt"; then + libgcrypt_installed="yes" +@@ -457,10 +467,10 @@ fi + + # final build of *FLAGS + CFLAGS="$ENV_CFLAGS $OPT_CFLAGS $GDB_FLAGS $OS_CFLAGS \ +- $COVERAGE_CFLAGS $EXTRA_WARNINGS $WERROR_CFLAGS $NSS_CFLAGS" ++ $COVERAGE_CFLAGS $EXTRA_WARNINGS $WERROR_CFLAGS $LIBGNUTLS_CFLAGS" + CPPFLAGS="$ENV_CPPFLAGS $ANSI_CPPFLAGS $OS_CPPFLAGS $GLIB_CFLAGS $RESMON_CFLAGS $XML_CFLAGS" + LDFLAGS="$ENV_LDFLAGS $COVERAGE_LDFLAGS $OS_LDFLAGS" +-LIBS="$LIBS $XML_LIBS" ++LIBS="$LIBS $XML_LIBS $LIBGNUTLS_LIBS" + + # substitute what we need: + AC_SUBST([INITDDIR]) +diff --git a/src/auth.c b/src/auth.c +index a3b3d20..26a220e 100644 +--- a/src/auth.c ++++ b/src/auth.c +@@ -18,6 +18,84 @@ + + #include "auth.h" + ++#if HAVE_LIBGNUTLS ++/* calculate the HMAC of the message in data and store it in result ++ * it is up to the caller to make sure that there's enough space ++ * at result for the MAC ++ */ ++int calc_hmac(const void *data, size_t datalen, ++ int hid, unsigned char *result, char *key, unsigned int keylen) ++{ ++ int rc; ++ ++ /* ++ * Only SHA1 is supported so we can hardcode GNUTLS_MAC_SHA1 ++ */ ++ if (hid != BOOTH_COMPAT_MHASH_SHA1) { ++ log_error("calc_hmac unsupported HMAC algorithm %u", hid); ++ return -1; ++ } ++ ++ /* ++ * This shouldn't happen but gnutls_hmac_fast segfault if key or ++ * data are NULL so it is better to check beforehand. ++ */ ++ if (data == NULL || key == NULL) { ++ log_error("calc_hmac data or key is NULL"); ++ return -1; ++ } ++ ++ rc = gnutls_hmac_fast(GNUTLS_MAC_SHA1, key, keylen, data, datalen, result); ++ if (rc) { ++ log_error("gnutls_hmac_fast: %s", gnutls_strerror(rc)); ++ return -1; ++ } ++ ++ return rc; ++} ++ ++/* test HMAC ++ */ ++int verify_hmac(const void *data, size_t datalen, ++ int hid, unsigned char *hmac, char *key, int keylen) ++{ ++ unsigned char *our_hmac; ++ int rc; ++ unsigned int hlen; ++ ++ /* ++ * Only SHA1 is supported so we can hardcode GNUTLS_MAC_SHA1 ++ */ ++ if (hid != BOOTH_COMPAT_MHASH_SHA1) { ++ log_error("verify_hmac unsupported HMAC algorithm %u", hid); ++ return -1; ++ } ++ ++ if (data == NULL || key == NULL) { ++ log_error("verify_hmac data or key is NULL"); ++ return -1; ++ } ++ ++ hlen = gnutls_hmac_get_len(GNUTLS_MAC_SHA1); ++ if (!hlen) ++ return -1; ++ ++ our_hmac = calloc(hlen, 1); ++ if (!our_hmac) ++ return -1; ++ ++ rc = calc_hmac(data, datalen, hid, our_hmac, key, keylen); ++ if (rc) ++ goto out_free; ++ rc = memcmp(our_hmac, hmac, hlen); ++ ++out_free: ++ if (our_hmac) ++ free(our_hmac); ++ return rc; ++} ++#endif ++ + #if HAVE_LIBGCRYPT + /* calculate the HMAC of the message in data and store it in result + * it is up to the caller to make sure that there's enough space +diff --git a/src/auth.h b/src/auth.h +index 98f0286..be1fc9e 100644 +--- a/src/auth.h ++++ b/src/auth.h +@@ -20,6 +20,25 @@ + #include "log.h" + #include + ++#if HAVE_LIBGNUTLS ++ ++#include ++#include ++ ++/* ++ * We need to stay backwards compatible. Both gcrypt and mhash defines ++ * SHA1 algorithm as 2. but GNUTLS_MAC_SHA1 is defined as 3, so hardcode ++ * 2 here and use correct value in auth.c ++ */ ++#define BOOTH_COMPAT_MHASH_SHA1 2 ++#define BOOTH_HASH BOOTH_COMPAT_MHASH_SHA1 ++ ++int calc_hmac(const void *data, size_t datalen, ++ int hid, unsigned char *result, char *key, unsigned int keylen); ++int verify_hmac(const void *data, size_t datalen, ++ int hid, unsigned char *hmac, char *key, int keylen); ++#endif ++ + #if HAVE_LIBGCRYPT + + #include +diff --git a/src/config.c b/src/config.c +index f0ca4aa..a533da3 100644 +--- a/src/config.c ++++ b/src/config.c +@@ -720,7 +720,7 @@ no_value: + continue; + } + +-#if HAVE_LIBGCRYPT || HAVE_LIBMHASH ++#if HAVE_LIBGNUTLS || HAVE_LIBGCRYPT || HAVE_LIBMHASH + if (strcmp(key, "authfile") == 0) { + safe_copy(booth_conf->authfile, + val, BOOTH_PATH_LEN, +diff --git a/src/main.c b/src/main.c +index 12085f4..71932fa 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -46,6 +46,9 @@ + + #include + ++#if HAVE_LIBGNUTLS ++#include ++#endif + #if HAVE_LIBGCRYPT + #include + #endif +@@ -376,6 +379,13 @@ static int setup_config(int type) + } + gcry_control(GCRYCTL_DISABLE_SECMEM, 0); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); ++#endif ++#if HAVE_LIBGNUTLS ++ if (gnutls_global_init() != 0) { ++ log_error("Cannot initialize GnuTLS"); ++ rv = -EINVAL; ++ goto out; ++ }; + #endif + } + +@@ -1671,6 +1681,9 @@ int main(int argc, char *argv[], char *envp[]) + } + + out: ++#if HAVE_LIBGNUTLS ++ gnutls_global_deinit(); ++#endif + #ifdef LOGGING_LIBQB + qb_log_fini(); + #endif +diff --git a/src/transport.c b/src/transport.c +index 817a4dc..8267c96 100644 +--- a/src/transport.c ++++ b/src/transport.c +@@ -977,7 +977,7 @@ const struct booth_transport booth_transport[TRANSPORT_ENTRIES] = { + int add_hmac(void *data, int len) + { + int rv = 0; +-#if HAVE_LIBGCRYPT || HAVE_LIBMHASH ++#if HAVE_LIBGNUTLS || HAVE_LIBGCRYPT || HAVE_LIBMHASH + int payload_len; + struct hmac *hp; + +@@ -997,7 +997,7 @@ int add_hmac(void *data, int len) + return rv; + } + +-#if HAVE_LIBGCRYPT || HAVE_LIBMHASH ++#if HAVE_LIBGNUTLS || HAVE_LIBGCRYPT || HAVE_LIBMHASH + + /* TODO: we need some client identification for logging */ + #define peer_string(p) (p ? site_string(p) : "client") +@@ -1051,7 +1051,7 @@ accept: + int check_auth(struct booth_site *from, void *buf, int len) + { + int rv = 0; +-#if HAVE_LIBGCRYPT || HAVE_LIBMHASH ++#if HAVE_LIBGNUTLS || HAVE_LIBGCRYPT || HAVE_LIBMHASH + int payload_len; + struct hmac *hp; + +-- +2.25.1 + +From 322fea0ef083e85ac161415b1c66f46d079932c9 Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Fri, 7 Jun 2024 08:02:38 +0200 +Subject: [PATCH 3/3] build: Prepare version 1.2 release + +Signed-off-by: Jan Friesse +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 4c4a0af..6b86bbe 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -5,7 +5,7 @@ + AC_PREREQ([2.69]) + + AC_INIT([booth], +- [m4_esyscmd([build-aux/git-version-gen --fallback 1.1 .tarball-version .gitarchivever])], ++ [m4_esyscmd([build-aux/git-version-gen --fallback 1.2 .tarball-version .gitarchivever])], + [users@clusterlabs.org]) + + AC_USE_SYSTEM_EXTENSIONS +-- +2.25.1 + diff --git a/booth.spec b/booth.spec index fc1818f..fe222ce 100644 --- a/booth.spec +++ b/booth.spec @@ -24,7 +24,7 @@ %bcond_with run_build_tests %bcond_with include_unit_test -%global release 5 +%global release 7 ## User and group to use for nonprivileged services (should be in sync with pacemaker) %global uname hacluster @@ -51,7 +51,11 @@ Source0: https://github.com/%{github_owner}/%{name}/releases/download/v%{ Patch0: Remove-const-warning.patch Patch1: pacemaker-Don-t-add-explicit-error-prefix-in-log.patch Patch2: pacemaker-Use-long-format-for-crm_ticket-v.patch -Patch3000: backport-CVE-2024-3049.patch +Patch3: pacemaker-Check-snprintf-return-values.patch +Patch0004: backport-CVE-2024-3049.patch +Patch0005: backport-Add-support-for-GnuTLS.patch + + # direct build process dependencies BuildRequires: autoconf @@ -65,7 +69,7 @@ BuildRequires: asciidoctor BuildRequires: gcc BuildRequires: pkgconfig # linking dependencies -BuildRequires: libgcrypt-devel +BuildRequires: gnutls-devel BuildRequires: libxml2-devel ## just for include BuildRequires: pacemaker-libs-devel @@ -300,12 +304,18 @@ VERBOSE=1 make check %{_usr}/lib/ocf/resource.d/booth/sharedrsc %changelog -* Sun Jun 09 2024 xuchenchen -1.1-5 +* Tue Jun 11 2024 zouzhimin -1.1-7 +- Add support for GnuTLS as and alternative for mcrypt and gcrypt + +* Sun Jun 09 2024 xuchenchen -1.1-6 - Type:CVES - ID:CVE-2024-3049 - SUG:NA - DESC:fix CVE-2024-3049 +* Sun Apr 28 2024 bizhiyuan - 1.1-5 +- pacemaker Check snprintf return values + * Thu Feb 29 2024 bizhiyuan - 1.1-4 - pacemaker: Use long format for crm_ticket -v diff --git a/pacemaker-Check-snprintf-return-values.patch b/pacemaker-Check-snprintf-return-values.patch new file mode 100644 index 0000000..312a010 --- /dev/null +++ b/pacemaker-Check-snprintf-return-values.patch @@ -0,0 +1,124 @@ +From 7e33a45d6898e06119dbe9dfd487f6c4923b48cb Mon Sep 17 00:00:00 2001 +From: Jan Friesse +Date: Tue, 14 Nov 2023 17:21:49 +0100 +Subject: [PATCH 2/7] pacemaker: Check snprintf return values + +crm_ticket command string is stored into static buffer and not checked +so it can be truncated without notice. + +Solution would be to use dynamic buffer, but for now at least check +snprintf return value and return error when string was truncated. + +Signed-off-by: Jan Friesse +--- + src/pacemaker.c | 39 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 34 insertions(+), 5 deletions(-) + +diff --git a/src/pacemaker.c b/src/pacemaker.c +index 8ad3c69..80aa1a3 100644 +--- a/src/pacemaker.c ++++ b/src/pacemaker.c +@@ -128,7 +128,7 @@ static int pcmk_write_ticket_atomic(struct ticket_config *tk, int grant) + + /* The long format (--attr-value=) for attribute value is used instead of "-v", + * so that NO_ONE (which is -1) isn't seen as another option. */ +- snprintf(cmd, COMMAND_MAX, ++ rv = snprintf(cmd, COMMAND_MAX, + "crm_ticket -t '%s' " + "%s --force " + "-S owner --attr-value=%" PRIi32 " " +@@ -142,6 +142,10 @@ static int pcmk_write_ticket_atomic(struct ticket_config *tk, int grant) + (int64_t)wall_ts(&tk->term_expires), + (int64_t)tk->current_term); + ++ if (rv < 0 || rv >= COMMAND_MAX) { ++ log_error("pcmk_write_ticket_atomic: cannot format crm_ticket cmdline (probably too long)"); ++ return -1; ++ } + rv = system(cmd); + log_debug("command: '%s' was executed", cmd); + if (rv != 0) +@@ -230,20 +234,34 @@ static int crm_ticket_set_int(const struct ticket_config *tk, const char *attr, + static int pcmk_set_attr(struct ticket_config *tk, const char *attr, const char *val) + { + char cmd[COMMAND_MAX]; ++ int rv; + +- snprintf(cmd, COMMAND_MAX, ++ rv = snprintf(cmd, COMMAND_MAX, + "crm_ticket -t '%s' -S '%s' --attr-value='%s'", + tk->name, attr, val); ++ ++ if (rv < 0 || rv >= COMMAND_MAX) { ++ log_error("pcmk_set_attr: cannot format crm_ticket cmdline (probably too long)"); ++ return -1; ++ } ++ + return _run_crm_ticket(cmd); + } + + static int pcmk_del_attr(struct ticket_config *tk, const char *attr) + { + char cmd[COMMAND_MAX]; ++ int rv; + +- snprintf(cmd, COMMAND_MAX, ++ rv = snprintf(cmd, COMMAND_MAX, + "crm_ticket -t '%s' -D '%s'", + tk->name, attr); ++ ++ if (rv < 0 || rv >= COMMAND_MAX) { ++ log_error("pcmk_del_attr: cannot format crm_ticket cmdline (probably too long)"); ++ return -1; ++ } ++ + return _run_crm_ticket(cmd); + } + +@@ -352,13 +370,18 @@ static int pcmk_get_attr(struct ticket_config *tk, const char *attr, const char + char cmd[COMMAND_MAX]; + char line[BOOTH_ATTRVAL_LEN+1]; + int rv = 0, pipe_rv; ++ int res; + FILE *p; + + + *vp = NULL; +- snprintf(cmd, COMMAND_MAX, ++ res = snprintf(cmd, COMMAND_MAX, + "crm_ticket -t '%s' -G '%s' --quiet", + tk->name, attr); ++ if (res < 0 || res >= COMMAND_MAX) { ++ log_error("pcmk_get_attr: cannot format crm_ticket cmdline (probably too long)"); ++ return -1; ++ } + + p = popen(cmd, "r"); + if (p == NULL) { +@@ -483,16 +506,22 @@ static int pcmk_load_ticket(struct ticket_config *tk) + { + char cmd[COMMAND_MAX]; + int rv = 0, pipe_rv; ++ int res; + FILE *p; + + /* This here gets run during startup; testing that here means that + * normal operation won't be interrupted with that test. */ + test_atomicity(); + +- snprintf(cmd, COMMAND_MAX, ++ res = snprintf(cmd, COMMAND_MAX, + "crm_ticket -t '%s' -q", + tk->name); + ++ if (res < 0 || res >= COMMAND_MAX) { ++ log_error("pcmk_load_ticket: cannot format crm_ticket cmdline (probably too long)"); ++ return -1; ++ } ++ + p = popen(cmd, "r"); + if (p == NULL) { + pipe_rv = errno; +-- +2.33.0 + -- Gitee