diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index cd6c173944..9716fd0435 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -185,33 +185,19 @@ blocks: commands: - '[[ -z $SEMAPHORE_GIT_TAG_NAME ]] || artifact push workflow artifacts/ --destination artifacts/${ARTIFACT_KEY}/' jobs: - - name: 'Build: centos8 glibc +gssapi' - env_vars: - - name: ARTIFACT_KEY - value: p-librdkafka__plat-linux__dist-centos8__arch-x64__lnk-std__extra-gssapi - commands: - - packaging/tools/build-release-artifacts.sh quay.io/pypa/manylinux_2_28_x86_64:2024.07.01-1 artifacts/librdkafka.tgz - - name: 'Build: centos8 glibc' env_vars: - name: ARTIFACT_KEY value: p-librdkafka__plat-linux__dist-centos8__arch-x64__lnk-all commands: - - packaging/tools/build-release-artifacts.sh --disable-gssapi quay.io/pypa/manylinux_2_28_x86_64:2024.07.01-1 artifacts/librdkafka.tgz - - - name: 'Build: alpine musl +gssapi' - env_vars: - - name: ARTIFACT_KEY - value: p-librdkafka__plat-linux__dist-alpine__arch-x64__lnk-std__extra-gssapi - commands: - - packaging/tools/build-release-artifacts.sh alpine:3.16.9 artifacts/librdkafka.tgz + - packaging/tools/build-release-artifacts.sh quay.io/pypa/manylinux_2_28_x86_64:2024.07.01-1 artifacts/librdkafka.tgz - name: 'Build: alpine musl' env_vars: - name: ARTIFACT_KEY value: p-librdkafka__plat-linux__dist-alpine__arch-x64__lnk-all commands: - - packaging/tools/build-release-artifacts.sh --disable-gssapi alpine:3.16.9 artifacts/librdkafka.tgz + - packaging/tools/build-release-artifacts.sh alpine:3.16.9 artifacts/librdkafka.tgz - name: 'Linux arm64: release artifact docker builds' @@ -227,33 +213,19 @@ blocks: commands: - '[[ -z $SEMAPHORE_GIT_TAG_NAME ]] || artifact push workflow artifacts/ --destination artifacts/${ARTIFACT_KEY}/' jobs: - - name: 'Build: centos8 glibc +gssapi' - env_vars: - - name: ARTIFACT_KEY - value: p-librdkafka__plat-linux__dist-centos8__arch-arm64__lnk-std__extra-gssapi - commands: - - packaging/tools/build-release-artifacts.sh quay.io/pypa/manylinux_2_28_aarch64:2024.07.01-1 artifacts/librdkafka.tgz - - name: 'Build: centos8 glibc' env_vars: - name: ARTIFACT_KEY value: p-librdkafka__plat-linux__dist-centos8__arch-arm64__lnk-all commands: - - packaging/tools/build-release-artifacts.sh --disable-gssapi quay.io/pypa/manylinux_2_28_aarch64:2024.07.01-1 artifacts/librdkafka.tgz - - - name: 'Build: alpine musl +gssapi' - env_vars: - - name: ARTIFACT_KEY - value: p-librdkafka__plat-linux__dist-alpine__arch-arm64__lnk-all__extra-gssapi - commands: - - packaging/tools/build-release-artifacts.sh alpine:3.16.9 artifacts/librdkafka.tgz + - packaging/tools/build-release-artifacts.sh quay.io/pypa/manylinux_2_28_aarch64:2024.07.01-1 artifacts/librdkafka.tgz - name: 'Build: alpine musl' env_vars: - name: ARTIFACT_KEY value: p-librdkafka__plat-linux__dist-alpine__arch-arm64__lnk-all commands: - - packaging/tools/build-release-artifacts.sh --disable-gssapi alpine:3.16.9 artifacts/librdkafka.tgz + - packaging/tools/build-release-artifacts.sh alpine:3.16.9 artifacts/librdkafka.tgz - name: 'Windows x64: MinGW-w64' diff --git a/CMakeLists.txt b/CMakeLists.txt index f3d05bad7a..00541c5096 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,38 +123,19 @@ endif() # SASL { if(WIN32) set(with_sasl_default ON) +elseif(WITH_LIBDL) + set(with_sasl_default ON) else() - if(PkgConfig_FOUND) - pkg_check_modules(SASL libsasl2) - if(SASL_FOUND) - set(with_sasl_default ON) - else() - try_compile( - WITH_SASL_CYRUS_BOOL - "${CMAKE_CURRENT_BINARY_DIR}/try_compile" - "${TRYCOMPILE_SRC_DIR}/libsasl2_test.c" - LINK_LIBRARIES "-lsasl2" - ) - if(WITH_SASL_CYRUS_BOOL) - set(with_sasl_default ON) - set(SASL_LIBRARIES "-lsasl2") - else() - set(with_sasl_default OFF) - endif() - endif() - endif() + set(with_sasl_default OFF) endif() option(WITH_SASL "With SASL" ${with_sasl_default}) if(WITH_SASL) - if(SASL_FOUND) - link_directories(${SASL_LIBRARY_DIRS}) - endif() if(WITH_SSL) set(WITH_SASL_SCRAM ON) set(WITH_SASL_OAUTHBEARER ON) list(APPEND BUILT_WITH "SASL_SCRAM SASL_OAUTHBEARER") endif() - if(NOT WIN32) + if(NOT WIN32 AND WITH_LIBDL) set(WITH_SASL_CYRUS ON) list(APPEND BUILT_WITH "SASL_CYRUS") endif() diff --git a/README.md b/README.md index 06f196bc0e..accf83f304 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,6 @@ If the version is out of date, please [create an issue or pull request](https:// pthreads zlib-dev (optional, for gzip compression support) libssl-dev (optional, for SSL and SASL SCRAM support) - libsasl2-dev (optional, for SASL GSSAPI support) libzstd-dev (optional, for ZStd compression support) libcurl-dev (optional, for SASL OAUTHBEARER OIDC support) diff --git a/configure.self b/configure.self index 691278348a..0c46a53e7e 100644 --- a/configure.self +++ b/configure.self @@ -19,7 +19,6 @@ mkl_require socket mkl_require zlib mkl_require libzstd mkl_require libssl -mkl_require libsasl2 mkl_require libcurl # Generate version variables from rdkafka.h hex version define @@ -99,12 +98,12 @@ void foo (void) { if [[ $WITH_LIBDL == "y" ]]; then mkl_allvar_set WITH_PLUGINS WITH_PLUGINS y + mkl_allvar_set WITH_SASL_CYRUS WITH_SASL_CYRUS y fi # optional libs mkl_check "zlib" mkl_check "libssl" - mkl_check "libsasl2" mkl_check "libzstd" mkl_check "libcurl" diff --git a/debian/control b/debian/control index c14b664f3e..c24f2a950e 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: librdkafka Priority: optional Maintainer: Faidon Liambotis Uploaders: Christos Trochalakis -Build-Depends: debhelper (>= 9), zlib1g-dev, libssl-dev, libsasl2-dev, liblz4-dev, python3 +Build-Depends: debhelper (>= 9), zlib1g-dev, libssl-dev, liblz4-dev, python3 Standards-Version: 3.9.7 Section: libs Homepage: https://github.com/confluentinc/librdkafka diff --git a/mklove/modules/configure.libsasl2 b/mklove/modules/configure.libsasl2 deleted file mode 100644 index e148e03da5..0000000000 --- a/mklove/modules/configure.libsasl2 +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash -# -# libsasl2 support (for GSSAPI/Kerberos), without source installer. -# -# Usage: -# mkl_require libsasl2 -# -# -# And then call the following function from the correct place/order in checks: -# mkl_check libsasl2 -# - -mkl_toggle_option "Feature" ENABLE_GSSAPI "--enable-gssapi" "Enable SASL GSSAPI support with Cyrus libsasl2" "try" -mkl_toggle_option "Feature" ENABLE_GSSAPI "--enable-sasl" "Deprecated: Alias for --enable-gssapi" - -function manual_checks { - case "$ENABLE_GSSAPI" in - n) return 0 ;; - y) local action=fail ;; - try) local action=disable ;; - *) mkl_err "mklove internal error: invalid value for ENABLE_GSSAPI: $ENABLE_GSSAPI"; exit 1 ;; - esac - - mkl_meta_set "libsasl2" "deb" "libsasl2-dev" - mkl_meta_set "libsasl2" "rpm" "cyrus-sasl" - mkl_meta_set "libsasl2" "apk" "cyrus-sasl-dev" - - local sasl_includes=" -#include -#include -" - - if ! mkl_lib_check "libsasl2" "WITH_SASL_CYRUS" $action CC "-lsasl2" "$sasl_includes" ; then - mkl_lib_check "libsasl" "WITH_SASL_CYRUS" $action CC "-lsasl" "$sasl_includes" - fi -} diff --git a/packaging/RELEASE.md b/packaging/RELEASE.md index f94ddce85e..9780815fbd 100644 --- a/packaging/RELEASE.md +++ b/packaging/RELEASE.md @@ -262,11 +262,6 @@ you will end up with: (`librdkafka.so.1` or `librdkafka.1.dylib` on OSX). -**NOTE**: Due to libsasl2/cyrus-sasl's dynamically loaded plugins, it is -not possible for us to provide a self-contained static library with -GSSAPI/Kerberos support. - - ### The artifact pipeline diff --git a/packaging/alpine/build-alpine.sh b/packaging/alpine/build-alpine.sh index e6d2471c96..02d66ff9e6 100755 --- a/packaging/alpine/build-alpine.sh +++ b/packaging/alpine/build-alpine.sh @@ -14,7 +14,7 @@ if [ "$1" = "--in-docker" ]; then git clone /v /librdkafka cd /librdkafka - ./configure --install-deps --disable-gssapi --disable-lz4-ext --enable-static $* + ./configure --install-deps --disable-lz4-ext --enable-static $* make -j examples/rdkafka_example -X builtin.features CI=true make -C tests run_local_quick diff --git a/packaging/archlinux/PKGBUILD b/packaging/archlinux/PKGBUILD index 36fef055b7..ece5c45143 100644 --- a/packaging/archlinux/PKGBUILD +++ b/packaging/archlinux/PKGBUILD @@ -7,7 +7,7 @@ license=('BSD') arch=('x86_64') source=('git+https://github.com/confluentinc/librdkafka#branch=master') sha256sums=('SKIP') -depends=(glibc libsasl lz4 openssl zlib zstd) +depends=(glibc lz4 openssl zlib zstd) makedepends=(bash git python3) pkgver() { diff --git a/packaging/cmake/try_compile/libsasl2_test.c b/packaging/cmake/try_compile/libsasl2_test.c deleted file mode 100644 index 3f3ab34098..0000000000 --- a/packaging/cmake/try_compile/libsasl2_test.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -int main() { - sasl_done(); - return 0; -} diff --git a/packaging/debian/control b/packaging/debian/control index 87f8a8490f..afcf658d0e 100644 --- a/packaging/debian/control +++ b/packaging/debian/control @@ -1,7 +1,7 @@ Source: librdkafka Priority: optional Maintainer: Faidon Liambotis -Build-Depends: debhelper (>= 9), zlib1g-dev, libssl-dev, libsasl2-dev, python3 +Build-Depends: debhelper (>= 9), zlib1g-dev, libssl-dev, python3 Standards-Version: 3.9.6 Section: libs Homepage: https://github.com/confluentinc/librdkafka diff --git a/packaging/debian/librdkafka.dsc b/packaging/debian/librdkafka.dsc index 1514513450..c2513b028a 100644 --- a/packaging/debian/librdkafka.dsc +++ b/packaging/debian/librdkafka.dsc @@ -8,7 +8,7 @@ Homepage: https://github.com/confluentinc/librdkafka Standards-Version: 3.9.6 Vcs-Browser: https://github.com/confluentinc/librdkafka/tree/master Vcs-Git: git://github.com/confluentinc/librdkafka.git -b master -Build-Depends: debhelper (>= 9), zlib1g-dev, libssl-dev, libsasl2-dev, python3 +Build-Depends: debhelper (>= 9), zlib1g-dev, libssl-dev, python3 Package-List: librdkafka-dev deb libdevel optional arch=any librdkafka1 deb libs optional arch=any diff --git a/packaging/nuget/nugetpackage.py b/packaging/nuget/nugetpackage.py index ab3655782f..eea27c6539 100644 --- a/packaging/nuget/nugetpackage.py +++ b/packaging/nuget/nugetpackage.py @@ -18,32 +18,32 @@ class NugetPackage (Package): mappings = [ Mapping({'arch': 'x64', 'plat': 'linux', - 'lnk': 'std'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/include/librdkafka/rdkafka.h', 'build/native/include/librdkafka/rdkafka.h'), Mapping({'arch': 'x64', 'plat': 'linux', - 'lnk': 'std'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/include/librdkafka/rdkafkacpp.h', 'build/native/include/librdkafka/rdkafkacpp.h'), Mapping({'arch': 'x64', 'plat': 'linux', - 'lnk': 'std'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/include/librdkafka/rdkafka_mock.h', 'build/native/include/librdkafka/rdkafka_mock.h'), Mapping({'arch': 'x64', 'plat': 'linux', - 'lnk': 'std'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/share/doc/librdkafka/README.md', 'README.md'), Mapping({'arch': 'x64', 'plat': 'linux', - 'lnk': 'std'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/share/doc/librdkafka/CONFIGURATION.md', 'CONFIGURATION.md'), @@ -67,23 +67,15 @@ class NugetPackage (Package): './usr/local/lib/librdkafka.1.dylib', 'runtimes/osx-arm64/native/librdkafka.dylib'), - # Linux glibc centos8 x64 with GSSAPI - Mapping({'arch': 'x64', - 'plat': 'linux', - 'dist': 'centos8', - 'lnk': 'std'}, - 'librdkafka.tgz', - './usr/local/lib/librdkafka.so.1', - 'runtimes/linux-x64/native/librdkafka.so'), - # Linux glibc centos8 x64 without GSSAPI (no external deps) + # Linux glibc centos8 x64 Mapping({'arch': 'x64', 'plat': 'linux', 'dist': 'centos8', 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/librdkafka.so.1', - 'runtimes/linux-x64/native/centos8-librdkafka.so'), - # Linux glibc centos8 arm64 without GSSAPI (no external deps) + 'runtimes/linux-x64/native/librdkafka.so'), + # Linux glibc centos8 arm64 Mapping({'arch': 'arm64', 'plat': 'linux', 'dist': 'centos8', @@ -92,7 +84,7 @@ class NugetPackage (Package): './usr/local/lib/librdkafka.so.1', 'runtimes/linux-arm64/native/librdkafka.so'), - # Linux musl alpine x64 without GSSAPI (no external deps) + # Linux musl alpine x64 Mapping({'arch': 'x64', 'plat': 'linux', 'dist': 'alpine', diff --git a/packaging/nuget/packaging.py b/packaging/nuget/packaging.py index 87338d3872..171b86bd42 100755 --- a/packaging/nuget/packaging.py +++ b/packaging/nuget/packaging.py @@ -91,7 +91,6 @@ def magic_mismatch(path, a): # bid - builder's build-id # bldtype - Release, Debug (appveyor) # lnk - Linkage ("std", "static", "all" (both std and static)) -# extra - Extra build options, typically "gssapi" (for cyrus-sasl linking). # # Example: diff --git a/packaging/nuget/staticpackage.py b/packaging/nuget/staticpackage.py index 9a555eb32e..ad45d929ec 100644 --- a/packaging/nuget/staticpackage.py +++ b/packaging/nuget/staticpackage.py @@ -14,24 +14,17 @@ class StaticPackage (Package): """ Create a tar-ball with self-contained static libraries. These are later imported into confluent-kafka-go. """ - # Make sure gssapi (cyrus-sasl) is not linked, since that is a - # dynamic linkage, by specifying negative match '!extra': 'gssapi'. - # Except for on OSX where cyrus-sasl is always available, and - # Windows where it is never linked. - # # Match statically linked artifacts (which are included in 'all' builds) mappings = [ Mapping({'arch': 'x64', 'plat': 'linux', - 'dist': 'centos8', - '!extra': 'gssapi'}, + 'dist': 'centos8'}, 'librdkafka.tgz', './usr/local/include/librdkafka/rdkafka.h', 'rdkafka.h'), Mapping({'arch': 'x64', 'plat': 'linux', - 'dist': 'centos8', - '!extra': 'gssapi'}, + 'dist': 'centos8'}, 'librdkafka.tgz', './usr/local/share/doc/librdkafka/LICENSES.txt', 'LICENSES.txt'), @@ -40,16 +33,14 @@ class StaticPackage (Package): Mapping({'arch': 'x64', 'plat': 'linux', 'dist': 'centos8', - 'lnk': 'all', - '!extra': 'gssapi'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/librdkafka-static.a', 'librdkafka_glibc_linux_amd64.a'), Mapping({'arch': 'x64', 'plat': 'linux', 'dist': 'centos8', - 'lnk': 'all', - '!extra': 'gssapi'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/pkgconfig/rdkafka-static.pc', 'librdkafka_glibc_linux_amd64.pc'), @@ -58,16 +49,14 @@ class StaticPackage (Package): Mapping({'arch': 'arm64', 'plat': 'linux', 'dist': 'centos8', - 'lnk': 'all', - '!extra': 'gssapi'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/librdkafka-static.a', 'librdkafka_glibc_linux_arm64.a'), Mapping({'arch': 'arm64', 'plat': 'linux', 'dist': 'centos8', - 'lnk': 'all', - '!extra': 'gssapi'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/pkgconfig/rdkafka-static.pc', 'librdkafka_glibc_linux_arm64.pc'), @@ -76,16 +65,14 @@ class StaticPackage (Package): Mapping({'arch': 'x64', 'plat': 'linux', 'dist': 'alpine', - 'lnk': 'all', - '!extra': 'gssapi'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/librdkafka-static.a', 'librdkafka_musl_linux_amd64.a'), Mapping({'arch': 'x64', 'plat': 'linux', 'dist': 'alpine', - 'lnk': 'all', - '!extra': 'gssapi'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/pkgconfig/rdkafka-static.pc', 'librdkafka_musl_linux_amd64.pc'), @@ -94,16 +81,14 @@ class StaticPackage (Package): Mapping({'arch': 'arm64', 'plat': 'linux', 'dist': 'alpine', - 'lnk': 'all', - '!extra': 'gssapi'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/librdkafka-static.a', 'librdkafka_musl_linux_arm64.a'), Mapping({'arch': 'arm64', 'plat': 'linux', 'dist': 'alpine', - 'lnk': 'all', - '!extra': 'gssapi'}, + 'lnk': 'all'}, 'librdkafka.tgz', './usr/local/lib/pkgconfig/rdkafka-static.pc', 'librdkafka_musl_linux_arm64.pc'), diff --git a/packaging/tools/build-configurations-checks.sh b/packaging/tools/build-configurations-checks.sh index 6001fa9cc8..6d6f945592 100755 --- a/packaging/tools/build-configurations-checks.sh +++ b/packaging/tools/build-configurations-checks.sh @@ -2,7 +2,7 @@ set -e # Disable all flags to make sure it # compiles correctly in all cases -./configure --install-deps --disable-ssl --disable-gssapi \ +./configure --install-deps --disable-ssl \ --disable-curl --disable-zlib \ --disable-zstd --disable-lz4-ext --disable-regex-ext \ --disable-c11threads --disable-syslog \ diff --git a/packaging/tools/build-deb-package.sh b/packaging/tools/build-deb-package.sh index 86b806ee92..9817f7f3d0 100755 --- a/packaging/tools/build-deb-package.sh +++ b/packaging/tools/build-deb-package.sh @@ -20,7 +20,7 @@ apt-get update # Install debian packaging tools and librdkafka build dependencies apt-get install -y git-buildpackage debhelper \ - zlib1g-dev libssl-dev libsasl2-dev liblz4-dev + zlib1g-dev libssl-dev liblz4-dev # Clone the librdkafka git repo to a new location to avoid messing diff --git a/packaging/tools/build-debian.sh b/packaging/tools/build-debian.sh index e62ee5f678..d32bfeda1e 100755 --- a/packaging/tools/build-debian.sh +++ b/packaging/tools/build-debian.sh @@ -5,7 +5,7 @@ # # Statically linked # WITH openssl 1.0, zlib -# WITHOUT libsasl2, lz4(ext, using builtin instead) +# WITHOUT lz4(ext, using builtin instead) # # Usage (from top-level librdkafka dir): # docker run -it -v $PWD:/v mcr.microsoft.com/dotnet/sdk /v/packaging/tools/build-debian.sh /v /v/librdkafka-debian9.tgz @@ -48,7 +48,7 @@ git config --global --add safe.directory /v (cd $LRK_DIR ; git archive --format tar HEAD) | tar xf - -./configure --install-deps --disable-gssapi --disable-lz4-ext --enable-static --prefix=$DEST_DIR $CONFIG_ARGS +./configure --install-deps --disable-lz4-ext --enable-static --prefix=$DEST_DIR $CONFIG_ARGS make -j examples/rdkafka_example -X builtin.features CI=true make -C tests run_local_quick diff --git a/packaging/tools/build-manylinux.sh b/packaging/tools/build-manylinux.sh index 4aeaa9622b..213bb28c86 100755 --- a/packaging/tools/build-manylinux.sh +++ b/packaging/tools/build-manylinux.sh @@ -7,7 +7,6 @@ # # Statically linked # WITH openssl 1.1.1, zlib, lz4(bundled) -# WITHOUT libsasl2 # # # Run: @@ -47,7 +46,7 @@ git config --global --add safe.directory /v (cd $LRK_DIR ; git archive --format tar HEAD) | tar xf - -./configure --install-deps --source-deps-only --disable-gssapi --disable-lz4-ext --enable-static --prefix=$DEST_DIR $CONFIG_ARGS +./configure --install-deps --source-deps-only --disable-lz4-ext --enable-static --prefix=$DEST_DIR $CONFIG_ARGS make -j diff --git a/packaging/tools/build-release-artifacts.sh b/packaging/tools/build-release-artifacts.sh index 3d2363b0cb..5b9947b848 100755 --- a/packaging/tools/build-release-artifacts.sh +++ b/packaging/tools/build-release-artifacts.sh @@ -13,7 +13,7 @@ # quay.io/pypa/manylinux_2_28_x86_64 (centos8) # # Usage: -# packaging/tools/build-release-artifacts.sh [--disable-gssapi] +# packaging/tools/build-release-artifacts.sh # # The output path must be a relative path and inside the librdkafka directory # structure. @@ -24,23 +24,7 @@ set -e docker_image="" extra_pkgs_rpm="" extra_pkgs_apk="" -extra_config_args="" -expected_features="gzip snappy ssl sasl regex lz4 sasl_plain sasl_scram plugins zstd sasl_oauthbearer http oidc" - -# Since cyrus-sasl is the only non-statically-linkable dependency, -# we provide a --disable-gssapi option so that two different libraries -# can be built: one with GSSAPI/Kerberos support, and one without, depending -# on this option. -if [ "$1" = "--disable-gssapi" ]; then - extra_config_args="${extra_config_args} --disable-gssapi" - disable_gssapi="$1" - shift -else - extra_pkgs_rpm="${extra_pkgs_rpm} cyrus-sasl cyrus-sasl-devel" - extra_pkgs_apk="${extra_pkgs_apk} cyrus-sasl cyrus-sasl-dev" - expected_features="${expected_features} sasl_gssapi" - disable_gssapi="" -fi +expected_features="gzip snappy ssl sasl regex lz4 sasl_gssapi sasl_plain sasl_scram plugins zstd sasl_oauthbearer http oidc" # Check if we're running on the host or the (docker) build target. if [ "$1" = "--in-docker" -a $# -eq 2 ]; then @@ -49,13 +33,13 @@ elif [ $# -eq 2 ]; then docker_image="$1" output="$2" else - echo "Usage: $0 [--disable-gssapi] " + echo "Usage: $0 " exit 1 fi if [ -n "$docker_image" ]; then # Running on the host, spin up the docker builder. - exec docker run -v "$PWD:/v" $docker_image /v/packaging/tools/build-release-artifacts.sh $disable_gssapi --in-docker "/v/$output" + exec docker run -v "$PWD:/v" $docker_image /v/packaging/tools/build-release-artifacts.sh --in-docker "/v/$output" # Only reached on exec error exit $? fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bbe63cff48..acb165eada 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -255,11 +255,6 @@ endif() find_package(Threads REQUIRED) target_link_libraries(rdkafka PUBLIC Threads::Threads) -if(WITH_SASL_CYRUS) - target_include_directories(rdkafka PRIVATE ${SASL_INCLUDE_DIRS}) - target_link_libraries(rdkafka PUBLIC ${SASL_LIBRARIES}) -endif() - if(WITH_LIBDL) target_link_libraries(rdkafka PUBLIC ${CMAKE_DL_LIBS}) endif() @@ -317,10 +312,6 @@ if(NOT RDKAFKA_BUILD_STATIC) string(APPEND PKG_CONFIG_REQUIRES_PRIVATE "libcrypto libssl ") endif() - if(WITH_SASL_CYRUS) - string(APPEND PKG_CONFIG_REQUIRES_PRIVATE "libsasl2 ") - endif() - if(WITH_ZSTD) string(APPEND PKG_CONFIG_REQUIRES_PRIVATE "libzstd ") endif() diff --git a/src/rdkafka_conf.c b/src/rdkafka_conf.c index 92f3cb5fc8..ffc22a8a7a 100644 --- a/src/rdkafka_conf.c +++ b/src/rdkafka_conf.c @@ -226,7 +226,7 @@ struct rd_kafka_property { #define _UNSUPPORTED_GSSAPI .unsupported = NULL #else #define _UNSUPPORTED_GSSAPI \ - .unsupported = "cyrus-sasl/libsasl2 not available at build time" + .unsupported = "libdl / dlopen(3) not available at build time" #endif #define _UNSUPPORTED_OAUTHBEARER _UNSUPPORTED_SSL diff --git a/src/rdkafka_sasl.c b/src/rdkafka_sasl.c index 4cd5027eec..fbe380ae2d 100644 --- a/src/rdkafka_sasl.c +++ b/src/rdkafka_sasl.c @@ -383,7 +383,16 @@ int rd_kafka_sasl_select_provider(rd_kafka_t *rk, #ifdef _WIN32 provider = &rd_kafka_sasl_win32_provider; #elif WITH_SASL_CYRUS - provider = &rd_kafka_sasl_cyrus_provider; + if (rd_kafka_sasl_cyrus_is_library_loaded()) { + provider = &rd_kafka_sasl_cyrus_provider; + } else { + rd_snprintf( + errstr, errstr_size, + "SASL GSSAPI mechanism requires " + "cyrus-sasl/libsasl2 to be installed: %s", + rd_kafka_sasl_cyrus_get_library_loading_error()); + return -1; + } #endif } else if (!strcmp(rk->rk_conf.sasl.mechanisms, "PLAIN")) { @@ -415,7 +424,7 @@ int rd_kafka_sasl_select_provider(rd_kafka_t *rk, "No provider for SASL mechanism %s" ": recompile librdkafka with " #ifndef _WIN32 - "libsasl2 or " + "libdl or " #endif "openssl support. " "Current build options:" diff --git a/src/rdkafka_sasl_cyrus.c b/src/rdkafka_sasl_cyrus.c index 89ff15c427..eabae07378 100644 --- a/src/rdkafka_sasl_cyrus.c +++ b/src/rdkafka_sasl_cyrus.c @@ -32,6 +32,7 @@ #include "rdkafka_transport_int.h" #include "rdkafka_sasl.h" #include "rdkafka_sasl_int.h" +#include "rddl.h" #include "rdstring.h" #if defined(__FreeBSD__) || defined(__OpenBSD__) @@ -39,12 +40,224 @@ #endif #ifdef __APPLE__ -/* Apple has deprecated most of the SASL API for unknown reason, - * silence those warnings. */ -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +const char *const rd_kafka_sasl_cyrus_library_names[] = {"libsasl2.2.dylib"}; +#else +const char *const rd_kafka_sasl_cyrus_library_names[] = {"libsasl2.so.2", + "libsasl2.so.3"}; #endif -#include +/** + * Handle for the loaded Cyrus SASL library + */ +static rd_dl_hnd_t *rd_kafka_sasl_cyrus_library_handle = NULL; + +/** + * Global loading error string + */ +static char rd_kafka_sasl_cyrus_library_errstr[1024]; + + +/** + * Cyrus SASL API + * Copied from sasl/sasl.h. + * These are only the symbols we use, not the full API. + */ +#define SASL_CONTINUE 1 +#define SASL_OK 0 +#define SASL_FAIL -1 +#define SASL_INTERACT 2 + +#define SASL_CB_LIST_END 0 +#define SASL_CB_LOG 2 +#define SASL_CB_USER 0x4001 +#define SASL_CB_AUTHNAME 0x4002 +#define SASL_CB_PASS 0x4004 +#define SASL_CB_ECHOPROMPT 0x4005 +#define SASL_CB_NOECHOPROMPT 0x4006 +#define SASL_CB_GETREALM (0x4008) +#define SASL_CB_CANON_USER (0x8007) + +#define SASL_USERNAME 0 +#define SASL_AUTHSOURCE 14 +#define SASL_MECHNAME 15 + +typedef struct sasl_conn sasl_conn_t; + +typedef struct sasl_secret { + unsigned long len; + unsigned char data[1]; +} sasl_secret_t; + +typedef struct sasl_callback { + unsigned long id; + int (*proc)(void); + void *context; +} sasl_callback_t; + +typedef struct sasl_interact { + unsigned long id; + const char *challenge; + const char *prompt; + const char *defresult; + const void *result; + unsigned len; +} sasl_interact_t; + + +/** + * Function pointers for the Cyrus SASL API + */ +static int (*sasl_client_init_p)(const sasl_callback_t *) = NULL; +static int (*sasl_client_new_p)(const char *service, + const char *serverFQDN, + const char *iplocalport, + const char *ipremoteport, + const sasl_callback_t *prompt_supp, + unsigned flags, + sasl_conn_t **pconn) = NULL; +static int (*sasl_client_start_p)(sasl_conn_t *conn, + const char *mechlist, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + const char **mech) = NULL; +static int (*sasl_client_step_p)(sasl_conn_t *conn, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen) = NULL; +static void (*sasl_dispose_p)(sasl_conn_t **pconn) = NULL; +static const char *(*sasl_errdetail_p)(sasl_conn_t *conn) = NULL; +static const char *(*sasl_errstring_p)(int saslerr, + const char *langlist, + const char **outlang) = NULL; +static int (*sasl_getprop_p)(sasl_conn_t *conn, + int propnum, + const void **pvalue) = NULL; +static int (*sasl_listmech_p)(sasl_conn_t *conn, + const char *user, + const char *prefix, + const char *sep, + const char *suffix, + const char **result, + unsigned *plen, + int *pcount) = NULL; + + +/** + * Resolve a symbol from the Cyrus SASL library + */ +#define RESOLVE_SYM(handle, sym) \ + do { \ + sym##_p = rd_dl_sym( \ + (handle), #sym, rd_kafka_sasl_cyrus_library_errstr, \ + sizeof(rd_kafka_sasl_cyrus_library_errstr)); \ + if (!(sym##_p)) { \ + rd_dl_close(handle); \ + (handle) = NULL; \ + return -1; \ + } \ + } while (0) + + +/** + * @brief Load the Cyrus SASL library and resolve the symbols we use. + * This function is called once per runtime. + * + * @returns 0 on success, -1 on error. + */ +int rd_kafka_sasl_cyrus_load_library(void) { + size_t count = sizeof(rd_kafka_sasl_cyrus_library_names) / + sizeof(rd_kafka_sasl_cyrus_library_names[0]); + char *errstrs[count]; + + size_t i; + for (i = 0; i < count; i++) { + char errstr[512]; + rd_kafka_sasl_cyrus_library_handle = + rd_dl_open(rd_kafka_sasl_cyrus_library_names[i], errstr, + sizeof(errstr)); + if (rd_kafka_sasl_cyrus_library_handle) + break; + errstrs[i] = rd_strdup(errstr); + } + + if (!rd_kafka_sasl_cyrus_library_handle) { + size_t offset = 0; + size_t maxlen = sizeof(rd_kafka_sasl_cyrus_library_errstr); + for (i = 0; i < count; i++) { + if (offset < maxlen - 1) { + int written = rd_snprintf( + rd_kafka_sasl_cyrus_library_errstr + offset, + maxlen - offset, "%s%s", errstrs[i], + (i < count - 1) ? "; " : ""); + if (written < 0) + offset = maxlen; + else + offset += written; + } + rd_free(errstrs[i]); + } + return -1; + } + + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_client_init); + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_client_new); + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_client_start); + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_client_step); + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_dispose); + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_errdetail); + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_errstring); + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_getprop); + RESOLVE_SYM(rd_kafka_sasl_cyrus_library_handle, sasl_listmech); + + rd_kafka_sasl_cyrus_library_errstr[0] = '\0'; + + return 0; +} + + +/** + * @brief Unload the Cyrus SASL library. + */ +void rd_kafka_sasl_cyrus_unload_library(void) { + if (rd_kafka_sasl_cyrus_library_handle != NULL) { + rd_dl_close(rd_kafka_sasl_cyrus_library_handle); + rd_kafka_sasl_cyrus_library_handle = NULL; + rd_kafka_sasl_cyrus_library_errstr[0] = '\0'; + sasl_client_init_p = NULL; + sasl_client_new_p = NULL; + sasl_client_start_p = NULL; + sasl_client_step_p = NULL; + sasl_dispose_p = NULL; + sasl_errdetail_p = NULL; + sasl_errstring_p = NULL; + sasl_getprop_p = NULL; + sasl_listmech_p = NULL; + } +} + + +/** + * @brief Check if the Cyrus SASL library is loaded. + * + * @returns 1 if the library is loaded, 0 otherwise. + */ +int rd_kafka_sasl_cyrus_is_library_loaded(void) { + return rd_kafka_sasl_cyrus_library_handle != NULL; +} + + +/** + * @brief Get the error string from the last library loading attempt. + * + * @returns The error string. + */ +char *rd_kafka_sasl_cyrus_get_library_loading_error(void) { + return rd_kafka_sasl_cyrus_library_errstr; +} + /** * @brief Process-global lock to avoid simultaneous invocation of @@ -93,8 +306,8 @@ static int rd_kafka_sasl_cyrus_recv(struct rd_kafka_transport_s *rktrans, unsigned int outlen; mtx_lock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); - r = sasl_client_step(state->conn, size > 0 ? buf : NULL, size, - &interact, &out, &outlen); + r = sasl_client_step_p(state->conn, size > 0 ? buf : NULL, size, + &interact, &out, &outlen); mtx_unlock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); if (r >= 0) { @@ -119,7 +332,7 @@ static int rd_kafka_sasl_cyrus_recv(struct rd_kafka_transport_s *rktrans, else if (r != SASL_OK) { rd_snprintf(errstr, errstr_size, "SASL handshake failed (step): %s", - sasl_errdetail(state->conn)); + sasl_errdetail_p(state->conn)); return -1; } @@ -152,17 +365,17 @@ static int rd_kafka_sasl_cyrus_recv(struct rd_kafka_transport_s *rktrans, const char *user, *mech, *authsrc; mtx_lock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); - if (sasl_getprop(state->conn, SASL_USERNAME, - (const void **)&user) != SASL_OK) + if (sasl_getprop_p(state->conn, SASL_USERNAME, + (const void **)&user) != SASL_OK) user = "(unknown)"; mtx_unlock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); - if (sasl_getprop(state->conn, SASL_MECHNAME, - (const void **)&mech) != SASL_OK) + if (sasl_getprop_p(state->conn, SASL_MECHNAME, + (const void **)&mech) != SASL_OK) mech = "(unknown)"; - if (sasl_getprop(state->conn, SASL_AUTHSOURCE, - (const void **)&authsrc) != SASL_OK) + if (sasl_getprop_p(state->conn, SASL_AUTHSOURCE, + (const void **)&authsrc) != SASL_OK) authsrc = "(unknown)"; rd_rkb_dbg(rktrans->rktrans_rkb, SECURITY, "SASL", @@ -486,7 +699,7 @@ static void rd_kafka_sasl_cyrus_close(struct rd_kafka_transport_s *rktrans) { if (state->conn) { mtx_lock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); - sasl_dispose(&state->conn); + sasl_dispose_p(&state->conn); mtx_unlock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); } rd_free(state); @@ -545,20 +758,20 @@ static int rd_kafka_sasl_cyrus_client_new(rd_kafka_transport_t *rktrans, memcpy(state->callbacks, callbacks, sizeof(callbacks)); mtx_lock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); - r = sasl_client_new(rk->rk_conf.sasl.service_name, hostname, NULL, - NULL, /* no local & remote IP checks */ - state->callbacks, 0, &state->conn); + r = sasl_client_new_p(rk->rk_conf.sasl.service_name, hostname, NULL, + NULL, /* no local & remote IP checks */ + state->callbacks, 0, &state->conn); mtx_unlock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); if (r != SASL_OK) { rd_snprintf(errstr, errstr_size, "%s", - sasl_errstring(r, NULL, NULL)); + sasl_errstring_p(r, NULL, NULL)); return -1; } if (rk->rk_conf.debug & RD_KAFKA_DBG_SECURITY) { const char *avail_mechs; - sasl_listmech(state->conn, NULL, NULL, " ", NULL, &avail_mechs, - NULL, NULL); + sasl_listmech_p(state->conn, NULL, NULL, " ", NULL, + &avail_mechs, NULL, NULL); rd_rkb_dbg(rkb, SECURITY, "SASL", "My supported SASL mechanisms: %s", avail_mechs); } @@ -569,8 +782,9 @@ static int rd_kafka_sasl_cyrus_client_new(rd_kafka_transport_t *rktrans, const char *mech = NULL; mtx_lock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); - r = sasl_client_start(state->conn, rk->rk_conf.sasl.mechanisms, - NULL, &out, &outlen, &mech); + r = sasl_client_start_p(state->conn, + rk->rk_conf.sasl.mechanisms, NULL, &out, + &outlen, &mech); mtx_unlock(&rktrans->rktrans_rkb->rkb_rk->rk_conf.sasl.lock); if (r >= 0) @@ -589,7 +803,7 @@ static int rd_kafka_sasl_cyrus_client_new(rd_kafka_transport_t *rktrans, } else if (r != SASL_CONTINUE) { rd_snprintf(errstr, errstr_size, "SASL handshake failed (start (%d)): %s", r, - sasl_errdetail(state->conn)); + sasl_errdetail_p(state->conn)); return -1; } @@ -688,6 +902,7 @@ void rd_kafka_sasl_cyrus_global_term(void) { /* NOTE: Should not be called since the application may be using SASL * too*/ /* sasl_done(); */ + rd_kafka_sasl_cyrus_unload_library(); mtx_destroy(&rd_kafka_sasl_cyrus_kinit_lock); } @@ -700,10 +915,14 @@ int rd_kafka_sasl_cyrus_global_init(void) { mtx_init(&rd_kafka_sasl_cyrus_kinit_lock, mtx_plain); - r = sasl_client_init(NULL); + if (rd_kafka_sasl_cyrus_load_library() < 0) { + return -1; + } + + r = sasl_client_init_p(NULL); if (r != SASL_OK) { fprintf(stderr, "librdkafka: sasl_client_init() failed: %s\n", - sasl_errstring(r, NULL, NULL)); + sasl_errstring_p(r, NULL, NULL)); return -1; } diff --git a/src/rdkafka_sasl_int.h b/src/rdkafka_sasl_int.h index 8a49a6a296..43c1a4e317 100644 --- a/src/rdkafka_sasl_int.h +++ b/src/rdkafka_sasl_int.h @@ -67,6 +67,8 @@ extern const struct rd_kafka_sasl_provider rd_kafka_sasl_win32_provider; extern const struct rd_kafka_sasl_provider rd_kafka_sasl_cyrus_provider; void rd_kafka_sasl_cyrus_global_term(void); int rd_kafka_sasl_cyrus_global_init(void); +int rd_kafka_sasl_cyrus_is_library_loaded(void); +char *rd_kafka_sasl_cyrus_get_library_loading_error(void); #endif extern const struct rd_kafka_sasl_provider rd_kafka_sasl_plain_provider;