From 936a734e95f2d89f88a004e84569b26625e8b714 Mon Sep 17 00:00:00 2001 From: Shubham Padkonde Date: Fri, 18 Sep 2026 03:07:46 +0530 Subject: [PATCH 1/4] Fix GnuTLS options when SYSTEM priorities are unavailable Signed-off-by: Shubham Padkonde --- .github/workflows/build.yml | 2 + CHANGES.md | 2 + cups/tls-gnutls.c | 35 +++++- test/testssloptions.py | 220 ++++++++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 test/testssloptions.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7d815a81b..8bdb150b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,6 +65,8 @@ jobs: run: make - name: Test CUPS run: make test + - name: Test GnuTLS SSLOptions + run: python3 test/testssloptions.py - name: Upload Test Results uses: actions/upload-artifact@v7 if: ${{ !cancelled() }} diff --git a/CHANGES.md b/CHANGES.md index a86893ce3..41d553933 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,8 @@ CHANGES - OpenPrinting CUPS v2.5b1 - YYYY-MM-DD ------------------- +- Fixed ignored GnuTLS `SSLOptions` when no system priority is configured + (Issue #1677). - Added multiple language support for IPP Everywhere. - Added `cupsConcatString`, `cupsCopyString`, and `cupsFormatString` string APIs. diff --git a/cups/tls-gnutls.c b/cups/tls-gnutls.c index 5fa9011a4..b5e7adfb3 100644 --- a/cups/tls-gnutls.c +++ b/cups/tls-gnutls.c @@ -1971,16 +1971,43 @@ _httpTLSStart(http_t *http) // I - Connection to server cupsConcatString(priority_string, ":!AES-128-CBC:!AES-256-CBC:!CAMELLIA-128-CBC:!CAMELLIA-256-CBC:!3DES-CBC", sizeof(priority_string)); #ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT - gnutls_priority_set_direct(http->tls, priority_string, NULL); + status = gnutls_priority_set_direct(http->tls, priority_string, NULL); + if (status == GNUTLS_E_INVALID_REQUEST && !(tls_options & _HTTP_TLS_NO_SYSTEM)) + { + // Named priorities are not configured on every system. Retry with NORMAL + // while retaining the requested protocol and cipher restrictions. + status = gnutls_priority_set_direct(http->tls, priority_string + 8, NULL); + } #else gnutls_priority_t priority; // Priority - gnutls_priority_init(&priority, priority_string, NULL); - gnutls_priority_set(http->tls, priority); - gnutls_priority_deinit(priority); + status = gnutls_priority_init(&priority, priority_string, NULL); + if (status == GNUTLS_E_INVALID_REQUEST && !(tls_options & _HTTP_TLS_NO_SYSTEM)) + status = gnutls_priority_init(&priority, priority_string + 8, NULL); + + if (!status) + { + status = gnutls_priority_set(http->tls, priority); + gnutls_priority_deinit(priority); + } #endif // HAVE_GNUTLS_PRIORITY_SET_DIRECT + if (status) + { + http->error = EIO; + http->status = HTTP_STATUS_ERROR; + + DEBUG_printf("4_httpTLSStart: Unable to set TLS priorities: %s", gnutls_strerror(status)); + _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0); + + gnutls_deinit(http->tls); + _httpFreeCredentials(credentials); + http->tls = NULL; + + return (false); + } + gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr_t)http); gnutls_transport_set_pull_function(http->tls, gnutls_http_read); #ifdef HAVE_GNUTLS_TRANSPORT_SET_PULL_TIMEOUT_FUNCTION diff --git a/test/testssloptions.py b/test/testssloptions.py new file mode 100644 index 000000000..d45c56be0 --- /dev/null +++ b/test/testssloptions.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python3 +# +# GnuTLS SSLOptions integration tests for CUPS. +# Copyright (c) 2026 by OpenPrinting. +# Licensed under Apache License v2.0. See LICENSE for details. +# +# Run after building with --with-tls=gnutls: python3 test/testssloptions.py +# Requires a C compiler, Python 3 with TLS 1.3 support, and the openssl command. +# All certificates, configuration, and connections are local to this test. + +import os +import shlex +import socket +import ssl +import subprocess +import tempfile +import threading +from pathlib import Path + +root = Path(__file__).resolve().parent.parent +if "#define HAVE_GNUTLS 1" not in (root / "config.h").read_text(): + raise SystemExit("Configure CUPS with --with-tls=gnutls before running this test.") +failures = 0 +with tempfile.TemporaryDirectory(prefix="cups-ssloptions-") as d: + p = Path(d) + (p / "client.c").write_text(r""" +#include "cups/cups.h" +#include +#include + +int +main(int argc, char *argv[]) +{ + char security[1024]; /* Negotiated TLS settings */ + http_t *http; /* Connection to the test server */ + + if (argc != 2) + return (2); + + http = httpConnect2("localhost", atoi(argv[1]), NULL, AF_INET, + HTTP_ENCRYPTION_ALWAYS, 1, 2000, NULL); + if (!http) + { + fprintf(stderr, "%s\n", cupsGetErrorString()); + return (1); + } + + puts(httpGetSecurity(http, security, sizeof(security))); + httpClose(http); + return (0); +} +""") + subprocess.run( + shlex.split(os.environ.get("CC", "cc")) + + [ + "-I" + str(root), + str(p / "client.c"), + "-L" + str(root / "cups"), + "-Wl,-rpath," + str(root / "cups"), + "-lcups", + "-o", + str(p / "client"), + ], + check=True, + ) + subprocess.run( + [ + "openssl", + "req", + "-x509", + "-newkey", + "rsa:2048", + "-nodes", + "-keyout", + str(p / "key.pem"), + "-out", + str(p / "cert.pem"), + "-days", + "1", + "-subj", + "/CN=localhost", + ], + check=True, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + cases = [ + ( + "missing SYSTEM honors MaxTLS1.2", + "", + "MinTLS1.2 MaxTLS1.2", + ssl.TLSVersion.TLSv1_2, + ssl.TLSVersion.TLSv1_3, + True, + "TLS/1.2", + ), + ( + "missing SYSTEM rejects TLS1.3-only server", + "", + "MinTLS1.2 MaxTLS1.2", + ssl.TLSVersion.TLSv1_3, + ssl.TLSVersion.TLSv1_3, + False, + None, + ), + ( + "missing SYSTEM honors MinTLS1.3", + "", + "MinTLS1.3", + ssl.TLSVersion.TLSv1_2, + ssl.TLSVersion.TLSv1_2, + False, + None, + ), + ( + "NoSystem remains functional", + "", + "NoSystem MinTLS1.2 MaxTLS1.2", + ssl.TLSVersion.TLSv1_2, + ssl.TLSVersion.TLSv1_3, + True, + "TLS/1.2", + ), + ( + "configured SYSTEM remains functional", + "[priorities]\nSYSTEM = NORMAL\n", + "MinTLS1.2 MaxTLS1.2", + ssl.TLSVersion.TLSv1_2, + ssl.TLSVersion.TLSv1_3, + True, + "TLS/1.2", + ), + ( + "configured SYSTEM keeps cipher restriction", + "[priorities]\nSYSTEM = NORMAL:-AES-128-GCM\n", + "MinTLS1.2 MaxTLS1.2", + ssl.TLSVersion.TLSv1_2, + ssl.TLSVersion.TLSv1_2, + False, + "GCM", + ), + ( + "NoSystem bypasses named cipher restriction", + "[priorities]\nSYSTEM = NORMAL:-AES-128-GCM\n", + "NoSystem MinTLS1.2 MaxTLS1.2", + ssl.TLSVersion.TLSv1_2, + ssl.TLSVersion.TLSv1_2, + True, + "GCM", + ), + ( + "missing SYSTEM honors DenyCBC", + "", + "MinTLS1.2 MaxTLS1.2 DenyCBC", + ssl.TLSVersion.TLSv1_2, + ssl.TLSVersion.TLSv1_2, + False, + "CBC", + ), + ] + for name, policy, options, minimum, maximum, success, expected in cases: + (p / "gnutls.conf").write_text(policy) + (p / "client.conf").write_text("SSLOptions " + options + "\n") + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + ctx.minimum_version = minimum + ctx.maximum_version = maximum + ctx.load_cert_chain(p / "cert.pem", p / "key.pem") + if expected == "CBC": + ctx.set_ciphers("ECDHE-RSA-AES128-SHA256") + if expected == "GCM": + ctx.set_ciphers("ECDHE-RSA-AES128-GCM-SHA256") + listener = socket.socket() + listener.bind(("127.0.0.1", 0)) + listener.listen() + listener.settimeout(5) + port = listener.getsockname()[1] + + def serve(listener, ctx): + try: + conn, _ = listener.accept() + with conn: + conn.settimeout(4) + with ctx.wrap_socket(conn, server_side=True) as tls: + tls.recv(1) + except (ssl.SSLError, OSError): + pass + finally: + listener.close() + + thread = threading.Thread(target=serve, args=(listener, ctx)) + thread.start() + env = dict( + os.environ, + GNUTLS_SYSTEM_PRIORITY_FILE=str(p / "gnutls.conf"), + CUPS_SYSCONFIG=d, + CUPS_USERCONFIG=d, + ) + r = subprocess.run( + [str(p / "client"), str(port)], + env=env, + check=False, + capture_output=True, + text=True, + timeout=8, + ) + thread.join(6) + if success: + passed = r.returncode == 0 and expected in r.stdout + else: + passed = r.returncode == 1 and "TLS" in r.stderr + failures += not passed + print( + ("PASS" if passed else "FAIL"), + name, + "=>", + (r.stdout + r.stderr).strip(), + flush=True, + ) +print("Failures:", failures) +raise SystemExit(bool(failures)) From db6e87119b85b897318ebc58c22c4157a3b159e7 Mon Sep 17 00:00:00 2001 From: Shubham Padkonde Date: Sat, 19 Sep 2026 09:02:33 +0530 Subject: [PATCH 2/4] Check for SYSTEM priorities before building the priority string Probe @SYSTEM first and only prepend it when it is configured, instead of retrying without it after the combined priority string fails. Co-Authored-By: Claude Opus 5 --- cups/tls-gnutls.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/cups/tls-gnutls.c b/cups/tls-gnutls.c index b5e7adfb3..09d440a0e 100644 --- a/cups/tls-gnutls.c +++ b/cups/tls-gnutls.c @@ -1927,10 +1927,26 @@ _httpTLSStart(http_t *http) // I - Connection to server return (false); } - if (tls_options & _HTTP_TLS_NO_SYSTEM) - priority_string[0] = '\0'; - else - cupsCopyString(priority_string, "@SYSTEM,", sizeof(priority_string)); + priority_string[0] = '\0'; + + if (!(tls_options & _HTTP_TLS_NO_SYSTEM)) + { + // Named system priorities are not configured on every system; only use + // them when available so the options below are not discarded... +#ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT + if (!gnutls_priority_set_direct(http->tls, "@SYSTEM", NULL)) + cupsCopyString(priority_string, "@SYSTEM,", sizeof(priority_string)); + +#else + gnutls_priority_t system_priority; // System priority + + if (!gnutls_priority_init(&system_priority, "@SYSTEM", NULL)) + { + gnutls_priority_deinit(system_priority); + cupsCopyString(priority_string, "@SYSTEM,", sizeof(priority_string)); + } +#endif // HAVE_GNUTLS_PRIORITY_SET_DIRECT + } cupsConcatString(priority_string, "NORMAL", sizeof(priority_string)); @@ -1972,20 +1988,11 @@ _httpTLSStart(http_t *http) // I - Connection to server #ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT status = gnutls_priority_set_direct(http->tls, priority_string, NULL); - if (status == GNUTLS_E_INVALID_REQUEST && !(tls_options & _HTTP_TLS_NO_SYSTEM)) - { - // Named priorities are not configured on every system. Retry with NORMAL - // while retaining the requested protocol and cipher restrictions. - status = gnutls_priority_set_direct(http->tls, priority_string + 8, NULL); - } #else gnutls_priority_t priority; // Priority status = gnutls_priority_init(&priority, priority_string, NULL); - if (status == GNUTLS_E_INVALID_REQUEST && !(tls_options & _HTTP_TLS_NO_SYSTEM)) - status = gnutls_priority_init(&priority, priority_string + 8, NULL); - if (!status) { status = gnutls_priority_set(http->tls, priority); From ab291b1737bad748b0342444680a3fc55d091019 Mon Sep 17 00:00:00 2001 From: Shubham Padkonde Date: Wed, 23 Sep 2026 17:42:32 +0530 Subject: [PATCH 3/4] test: integrate TLS options checks with dependency detection --- .github/workflows/build.yml | 6 +- Makedefs.in | 5 ++ Makefile | 11 ++- config-scripts/cups-tests.m4 | 24 ++++++ configure | 152 +++++++++++++++++++++++++++++++++++ configure.ac | 1 + test/testssloptions.py | 4 +- 7 files changed, 196 insertions(+), 7 deletions(-) create mode 100644 config-scripts/cups-tests.m4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8bdb150b0..a708632d0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,18 +55,16 @@ jobs: - name: Update build environment run: sudo apt-get update --fix-missing -y - name: Install prerequisites - run: sudo apt-get install -y avahi-daemon libavahi-client-dev libgnutls28-dev libpam-dev libusb-1.0-0-dev zlib1g-dev + run: sudo apt-get install -y avahi-daemon libavahi-client-dev libgnutls28-dev python3 openssl libpam-dev libusb-1.0-0-dev zlib1g-dev - name: Configure CUPS env: CC: /usr/bin/gcc CXX: /usr/bin/g++ - run: ./configure --enable-debug --enable-maintainer --with-tls=gnutls + run: ./configure --enable-debug --enable-maintainer --with-tls=gnutls --enable-test-deps - name: Build CUPS run: make - name: Test CUPS run: make test - - name: Test GnuTLS SSLOptions - run: python3 test/testssloptions.py - name: Upload Test Results uses: actions/upload-artifact@v7 if: ${{ !cancelled() }} diff --git a/Makedefs.in b/Makedefs.in index b3a00d5a5..dd18f811b 100644 --- a/Makedefs.in +++ b/Makedefs.in @@ -265,3 +265,8 @@ USBQUIRKS = @USBQUIRKS@ .cxx.o: echo Compiling $<... $(CXX) $(ARCHFLAGS) $(OPTIM) $(ALL_CXXFLAGS) -c -o $@ $< + +# Optional GnuTLS test dependencies. +TEST_PYTHON = @TEST_PYTHON@ +TEST_OPENSSL = @TEST_OPENSSL@ +SSL_OPTIONS_TEST = @SSL_OPTIONS_TEST@ diff --git a/Makefile b/Makefile index a9dcf2ce5..8164cfb44 100644 --- a/Makefile +++ b/Makefile @@ -238,12 +238,21 @@ testserver: all unittests cd test; ./run-stp-tests.sh $(TESTOPTIONS) -check test: all unittests +check test: all unittests testssloptions cd cups; make test cd scheduler; make test echo Running CUPS test suite... cd test; ./run-stp-tests.sh 1 0 n n +.PHONY: testssloptions +testssloptions: all + @if test "$(SSL_OPTIONS_TEST)" = yes; then \ + CC="$(CC)" OPENSSL="$(TEST_OPENSSL)" "$(TEST_PYTHON)" test/testssloptions.py; \ + else \ + echo "SKIP GnuTLS SSLOptions tests (backend or optional dependencies unavailable)"; \ + fi + + debugcheck debugtest: all unittests echo Running CUPS test suite with debug printfs... cd test; ./run-stp-tests.sh 1 0 n y diff --git a/config-scripts/cups-tests.m4 b/config-scripts/cups-tests.m4 new file mode 100644 index 000000000..257028c35 --- /dev/null +++ b/config-scripts/cups-tests.m4 @@ -0,0 +1,24 @@ +dnl Optional dependencies for the local GnuTLS SSLOptions tests. +AC_ARG_ENABLE([test-deps], AS_HELP_STRING([--enable-test-deps], [require optional test dependencies]), [], [enable_test_deps=no]) +AS_CASE([$enable_test_deps], [yes|no], [], [AC_MSG_ERROR([--enable-test-deps accepts yes or no])]) + +SSL_OPTIONS_TEST=no +AS_IF([test "$with_tls" = gnutls], [ + AC_PATH_PROG([TEST_PYTHON], [python3]) + AC_PATH_PROG([TEST_OPENSSL], [openssl]) + AS_IF([test -n "$TEST_PYTHON" -a -n "$TEST_OPENSSL"], [ + AC_MSG_CHECKING([whether test Python supports TLS 1.3]) + AS_IF(["$TEST_PYTHON" -c 'import ssl, sys; sys.exit(not ssl.HAS_TLSv1_3)' >/dev/null 2>&1], [ + AC_MSG_RESULT([yes]) + SSL_OPTIONS_TEST=yes + ], [AC_MSG_RESULT([no])]) + ]) + AS_IF([test "$SSL_OPTIONS_TEST" = no], [ + AS_IF([test "$enable_test_deps" = yes], [ + AC_MSG_ERROR([GnuTLS SSLOptions tests require Python 3 with TLS 1.3 support and the openssl command]) + ], [AC_MSG_NOTICE([GnuTLS SSLOptions tests will be skipped: optional dependencies unavailable])]) + ]) +]) +AC_SUBST([TEST_PYTHON]) +AC_SUBST([TEST_OPENSSL]) +AC_SUBST([SSL_OPTIONS_TEST]) diff --git a/configure b/configure index 83c9b5f66..81a3e98f5 100755 --- a/configure +++ b/configure @@ -707,6 +707,9 @@ PAMMOD PAMLIBS PAMFILE PAMDIR +SSL_OPTIONS_TEST +TEST_OPENSSL +TEST_PYTHON EXPORT_TLSLIBS TLSLIBS TLSFLAGS @@ -901,6 +904,7 @@ with_domainsocket enable_gssapi with_gssservicename with_tls +enable_test_deps enable_pam with_pam_module enable_largefile @@ -1597,6 +1601,7 @@ Optional Features: --enable-relro build with the relro option --enable-sanitizer build with AddressSanitizer --enable-gssapi enable (deprecated) GSSAPI/Kerberos support + --enable-test-deps require optional test dependencies --disable-pam disable PAM support --disable-largefile omit support for large files --enable-page-logging enable page_log by default @@ -9805,6 +9810,153 @@ fi EXPORT_TLSLIBS="$TLSLIBS" +# Check whether --enable-test-deps was given. +if test ${enable_test_deps+y} +then : + enableval=$enable_test_deps; +else $as_nop + enable_test_deps=no +fi + +case $enable_test_deps in #( + yes|no) : + ;; #( + *) : + as_fn_error $? "--enable-test-deps accepts yes or no" "$LINENO" 5 ;; +esac + +SSL_OPTIONS_TEST=no +if test "$with_tls" = gnutls +then : + + # Extract the first word of "python3", so it can be a program name with args. +set dummy python3; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_TEST_PYTHON+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $TEST_PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_TEST_PYTHON="$TEST_PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_TEST_PYTHON="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +TEST_PYTHON=$ac_cv_path_TEST_PYTHON +if test -n "$TEST_PYTHON"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_PYTHON" >&5 +printf "%s\n" "$TEST_PYTHON" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + # Extract the first word of "openssl", so it can be a program name with args. +set dummy openssl; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_TEST_OPENSSL+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $TEST_OPENSSL in + [\\/]* | ?:[\\/]*) + ac_cv_path_TEST_OPENSSL="$TEST_OPENSSL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_TEST_OPENSSL="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +TEST_OPENSSL=$ac_cv_path_TEST_OPENSSL +if test -n "$TEST_OPENSSL"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_OPENSSL" >&5 +printf "%s\n" "$TEST_OPENSSL" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + if test -n "$TEST_PYTHON" -a -n "$TEST_OPENSSL" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether test Python supports TLS 1.3" >&5 +printf %s "checking whether test Python supports TLS 1.3... " >&6; } + if "$TEST_PYTHON" -c 'import ssl, sys; sys.exit(not ssl.HAS_TLSv1_3)' >/dev/null 2>&1 +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + SSL_OPTIONS_TEST=yes + +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + +fi + if test "$SSL_OPTIONS_TEST" = no +then : + + if test "$enable_test_deps" = yes +then : + + as_fn_error $? "GnuTLS SSLOptions tests require Python 3 with TLS 1.3 support and the openssl command" "$LINENO" 5 + +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: GnuTLS SSLOptions tests will be skipped: optional dependencies unavailable" >&5 +printf "%s\n" "$as_me: GnuTLS SSLOptions tests will be skipped: optional dependencies unavailable" >&6;} +fi + +fi + +fi + + + + # Check whether --enable-pam was given. if test ${enable_pam+y} diff --git a/configure.ac b/configure.ac index 4e2bbe12c..39361cd45 100644 --- a/configure.ac +++ b/configure.ac @@ -32,6 +32,7 @@ sinclude(config-scripts/cups-network.m4) sinclude(config-scripts/cups-gssapi.m4) sinclude(config-scripts/cups-threads.m4) sinclude(config-scripts/cups-tls.m4) +sinclude(config-scripts/cups-tests.m4) sinclude(config-scripts/cups-pam.m4) sinclude(config-scripts/cups-largefile.m4) sinclude(config-scripts/cups-dnssd.m4) diff --git a/test/testssloptions.py b/test/testssloptions.py index d45c56be0..ad74e0788 100644 --- a/test/testssloptions.py +++ b/test/testssloptions.py @@ -4,7 +4,7 @@ # Copyright (c) 2026 by OpenPrinting. # Licensed under Apache License v2.0. See LICENSE for details. # -# Run after building with --with-tls=gnutls: python3 test/testssloptions.py +# Run after building with --with-tls=gnutls: make testssloptions # Requires a C compiler, Python 3 with TLS 1.3 support, and the openssl command. # All certificates, configuration, and connections are local to this test. @@ -65,7 +65,7 @@ ) subprocess.run( [ - "openssl", + os.environ.get("OPENSSL", "openssl"), "req", "-x509", "-newkey", From ac71bd3bf67e34ed4e6f6badca395e5e96abef18 Mon Sep 17 00:00:00 2001 From: Shubham Padkonde Date: Thu, 24 Sep 2026 23:27:25 +0530 Subject: [PATCH 4/4] test: keep GnuTLS options checks in CI only --- .github/workflows/build.yml | 4 +- Makedefs.in | 5 -- Makefile | 11 +-- config-scripts/cups-tests.m4 | 24 ------ configure | 152 ----------------------------------- configure.ac | 1 - test/testssloptions.py | 2 +- 7 files changed, 5 insertions(+), 194 deletions(-) delete mode 100644 config-scripts/cups-tests.m4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a708632d0..c8b756ad5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,11 +60,13 @@ jobs: env: CC: /usr/bin/gcc CXX: /usr/bin/g++ - run: ./configure --enable-debug --enable-maintainer --with-tls=gnutls --enable-test-deps + run: ./configure --enable-debug --enable-maintainer --with-tls=gnutls - name: Build CUPS run: make - name: Test CUPS run: make test + - name: Test GnuTLS SSLOptions + run: python3 test/testssloptions.py - name: Upload Test Results uses: actions/upload-artifact@v7 if: ${{ !cancelled() }} diff --git a/Makedefs.in b/Makedefs.in index dd18f811b..b3a00d5a5 100644 --- a/Makedefs.in +++ b/Makedefs.in @@ -265,8 +265,3 @@ USBQUIRKS = @USBQUIRKS@ .cxx.o: echo Compiling $<... $(CXX) $(ARCHFLAGS) $(OPTIM) $(ALL_CXXFLAGS) -c -o $@ $< - -# Optional GnuTLS test dependencies. -TEST_PYTHON = @TEST_PYTHON@ -TEST_OPENSSL = @TEST_OPENSSL@ -SSL_OPTIONS_TEST = @SSL_OPTIONS_TEST@ diff --git a/Makefile b/Makefile index 8164cfb44..a9dcf2ce5 100644 --- a/Makefile +++ b/Makefile @@ -238,21 +238,12 @@ testserver: all unittests cd test; ./run-stp-tests.sh $(TESTOPTIONS) -check test: all unittests testssloptions +check test: all unittests cd cups; make test cd scheduler; make test echo Running CUPS test suite... cd test; ./run-stp-tests.sh 1 0 n n -.PHONY: testssloptions -testssloptions: all - @if test "$(SSL_OPTIONS_TEST)" = yes; then \ - CC="$(CC)" OPENSSL="$(TEST_OPENSSL)" "$(TEST_PYTHON)" test/testssloptions.py; \ - else \ - echo "SKIP GnuTLS SSLOptions tests (backend or optional dependencies unavailable)"; \ - fi - - debugcheck debugtest: all unittests echo Running CUPS test suite with debug printfs... cd test; ./run-stp-tests.sh 1 0 n y diff --git a/config-scripts/cups-tests.m4 b/config-scripts/cups-tests.m4 deleted file mode 100644 index 257028c35..000000000 --- a/config-scripts/cups-tests.m4 +++ /dev/null @@ -1,24 +0,0 @@ -dnl Optional dependencies for the local GnuTLS SSLOptions tests. -AC_ARG_ENABLE([test-deps], AS_HELP_STRING([--enable-test-deps], [require optional test dependencies]), [], [enable_test_deps=no]) -AS_CASE([$enable_test_deps], [yes|no], [], [AC_MSG_ERROR([--enable-test-deps accepts yes or no])]) - -SSL_OPTIONS_TEST=no -AS_IF([test "$with_tls" = gnutls], [ - AC_PATH_PROG([TEST_PYTHON], [python3]) - AC_PATH_PROG([TEST_OPENSSL], [openssl]) - AS_IF([test -n "$TEST_PYTHON" -a -n "$TEST_OPENSSL"], [ - AC_MSG_CHECKING([whether test Python supports TLS 1.3]) - AS_IF(["$TEST_PYTHON" -c 'import ssl, sys; sys.exit(not ssl.HAS_TLSv1_3)' >/dev/null 2>&1], [ - AC_MSG_RESULT([yes]) - SSL_OPTIONS_TEST=yes - ], [AC_MSG_RESULT([no])]) - ]) - AS_IF([test "$SSL_OPTIONS_TEST" = no], [ - AS_IF([test "$enable_test_deps" = yes], [ - AC_MSG_ERROR([GnuTLS SSLOptions tests require Python 3 with TLS 1.3 support and the openssl command]) - ], [AC_MSG_NOTICE([GnuTLS SSLOptions tests will be skipped: optional dependencies unavailable])]) - ]) -]) -AC_SUBST([TEST_PYTHON]) -AC_SUBST([TEST_OPENSSL]) -AC_SUBST([SSL_OPTIONS_TEST]) diff --git a/configure b/configure index 81a3e98f5..83c9b5f66 100755 --- a/configure +++ b/configure @@ -707,9 +707,6 @@ PAMMOD PAMLIBS PAMFILE PAMDIR -SSL_OPTIONS_TEST -TEST_OPENSSL -TEST_PYTHON EXPORT_TLSLIBS TLSLIBS TLSFLAGS @@ -904,7 +901,6 @@ with_domainsocket enable_gssapi with_gssservicename with_tls -enable_test_deps enable_pam with_pam_module enable_largefile @@ -1601,7 +1597,6 @@ Optional Features: --enable-relro build with the relro option --enable-sanitizer build with AddressSanitizer --enable-gssapi enable (deprecated) GSSAPI/Kerberos support - --enable-test-deps require optional test dependencies --disable-pam disable PAM support --disable-largefile omit support for large files --enable-page-logging enable page_log by default @@ -9810,153 +9805,6 @@ fi EXPORT_TLSLIBS="$TLSLIBS" -# Check whether --enable-test-deps was given. -if test ${enable_test_deps+y} -then : - enableval=$enable_test_deps; -else $as_nop - enable_test_deps=no -fi - -case $enable_test_deps in #( - yes|no) : - ;; #( - *) : - as_fn_error $? "--enable-test-deps accepts yes or no" "$LINENO" 5 ;; -esac - -SSL_OPTIONS_TEST=no -if test "$with_tls" = gnutls -then : - - # Extract the first word of "python3", so it can be a program name with args. -set dummy python3; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_TEST_PYTHON+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $TEST_PYTHON in - [\\/]* | ?:[\\/]*) - ac_cv_path_TEST_PYTHON="$TEST_PYTHON" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_TEST_PYTHON="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -TEST_PYTHON=$ac_cv_path_TEST_PYTHON -if test -n "$TEST_PYTHON"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_PYTHON" >&5 -printf "%s\n" "$TEST_PYTHON" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - - # Extract the first word of "openssl", so it can be a program name with args. -set dummy openssl; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_TEST_OPENSSL+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $TEST_OPENSSL in - [\\/]* | ?:[\\/]*) - ac_cv_path_TEST_OPENSSL="$TEST_OPENSSL" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_TEST_OPENSSL="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -TEST_OPENSSL=$ac_cv_path_TEST_OPENSSL -if test -n "$TEST_OPENSSL"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_OPENSSL" >&5 -printf "%s\n" "$TEST_OPENSSL" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - - if test -n "$TEST_PYTHON" -a -n "$TEST_OPENSSL" -then : - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether test Python supports TLS 1.3" >&5 -printf %s "checking whether test Python supports TLS 1.3... " >&6; } - if "$TEST_PYTHON" -c 'import ssl, sys; sys.exit(not ssl.HAS_TLSv1_3)' >/dev/null 2>&1 -then : - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - SSL_OPTIONS_TEST=yes - -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - -fi - if test "$SSL_OPTIONS_TEST" = no -then : - - if test "$enable_test_deps" = yes -then : - - as_fn_error $? "GnuTLS SSLOptions tests require Python 3 with TLS 1.3 support and the openssl command" "$LINENO" 5 - -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: GnuTLS SSLOptions tests will be skipped: optional dependencies unavailable" >&5 -printf "%s\n" "$as_me: GnuTLS SSLOptions tests will be skipped: optional dependencies unavailable" >&6;} -fi - -fi - -fi - - - - # Check whether --enable-pam was given. if test ${enable_pam+y} diff --git a/configure.ac b/configure.ac index 39361cd45..4e2bbe12c 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,6 @@ sinclude(config-scripts/cups-network.m4) sinclude(config-scripts/cups-gssapi.m4) sinclude(config-scripts/cups-threads.m4) sinclude(config-scripts/cups-tls.m4) -sinclude(config-scripts/cups-tests.m4) sinclude(config-scripts/cups-pam.m4) sinclude(config-scripts/cups-largefile.m4) sinclude(config-scripts/cups-dnssd.m4) diff --git a/test/testssloptions.py b/test/testssloptions.py index ad74e0788..441b5233b 100644 --- a/test/testssloptions.py +++ b/test/testssloptions.py @@ -4,7 +4,7 @@ # Copyright (c) 2026 by OpenPrinting. # Licensed under Apache License v2.0. See LICENSE for details. # -# Run after building with --with-tls=gnutls: make testssloptions +# Run after building with --with-tls=gnutls: python3 test/testssloptions.py # Requires a C compiler, Python 3 with TLS 1.3 support, and the openssl command. # All certificates, configuration, and connections are local to this test.