From 5d5e489315f7964a81ea0da85ee5cc17ccd3381c Mon Sep 17 00:00:00 2001
From: MSVSphere Packaging Team
Date: Fri, 29 Mar 2024 15:26:28 +0300
Subject: [PATCH] import cups-2.2.6-57.el8
---
.cups.metadata | 2 +
.gitignore | 2 +
...MinTLS-and-MaxTLS-options-Issue-5119.patch | 497 ++
...h-idle-exit-timeout-configure-option.patch | 33 +
...emd-timeoutstartsec-configure-option.patch | 33 +
...nux-session-cookies-used-a-predictab.patch | 22 +
SOURCES/0001-Fix-default-TLS-versions.patch | 24 +
...ing-to-lpd-when-reserved-ports-are-e.patch | 21 +
...-handling-of-MaxJobTime-0-Issue-5438.patch | 43 +
...ege-escalation-to-root-and-sandbox-b.patch | 481 ++
...-cupsIPPSupplies-and-cupsSNMPSupplie.patch | 62 +
...y-leaks-found-by-Coverity-Issue-5375.patch | 206 +
...ulti-file-jobs-Issue-5359-Issue-5413.patch | 56 +
...tpGetHostname-BEFORE-closing-the-con.patch | 64 +
...-Multiple-security-disclosure-issues.patch | 183 +
...CUPS-servers-has-been-fixed-Issue-52.patch | 562 +++
SOURCES/0001-Remove-web-log-buttons.patch | 98 +
...authentication-for-CUPS-Get-Document.patch | 31 +
...uld-crash-while-adding-an-IPP-Everyw.patch | 22 +
...ate-man-pages-for-h-option-Issue-357.patch | 899 ++++
...Dest-for-legacy-printing-APIs-Issue-.patch | 109 +
...stead-of-purge-jobs-when-canceling-a.patch | 48 +
...c-Use-guest-user-for-Move-Job-when-n.patch | 16 +
...sGetNamedDest-set-IPP_STATUS_ERROR_N.patch | 65 +
...-Set-listen-backlog-size-to-INT_MAX-.patch | 35 +
.../0001-cups-strlcpy-handle-zero-size.patch | 26 +
...s-gnutls.c-Use-always-GNUTLS_SHUT_WR.patch | 55 +
...-Check-for-error-if-POLLHUP-is-in-va.patch | 43 +
...-Fix-string-comparison-fixes-CVE-202.patch | 35 +
...-Print-to-stderr-if-we-don-t-open-cu.patch | 36 +
...use-gziptoany-for-raw-files-not-just.patch | 38 +
SOURCES/cups-autostart-when-enabled.patch | 10 +
SOURCES/cups-avahi-address.patch | 95 +
SOURCES/cups-avahi-no-threaded.patch | 1025 +++++
SOURCES/cups-banners.patch | 12 +
SOURCES/cups-cupsd-too-chatty.patch | 12 +
SOURCES/cups-cve202010001.patch | 61 +
SOURCES/cups-direct-usb.patch | 27 +
SOURCES/cups-dirtyclean.patch | 13 +
SOURCES/cups-dnssd-deviceid.patch | 38 +
.../cups-do-not-advertise-http-methods.patch | 13 +
SOURCES/cups-driverd-timeout.patch | 21 +
SOURCES/cups-dymo-deviceid.patch | 11 +
SOURCES/cups-eggcups.patch | 130 +
SOURCES/cups-etimedout.patch | 25 +
SOURCES/cups-failover-backend.patch | 877 ++++
SOURCES/cups-filter-debug.patch | 32 +
SOURCES/cups-fips-compliance.patch | 371 ++
SOURCES/cups-fix-preservejob-times.patch | 110 +
SOURCES/cups-freebind.patch | 15 +
SOURCES/cups-hp-deviceid-oid.patch | 21 +
SOURCES/cups-ipp-multifile.patch | 15 +
SOURCES/cups-ippeve-web-support.patch | 315 ++
SOURCES/cups-kerberos.patch | 23 +
SOURCES/cups-logrotate.patch | 63 +
SOURCES/cups-logs.patch | 100 +
SOURCES/cups-lpr-help.patch | 48 +
SOURCES/cups-lspp.patch | 1997 ++++++++
SOURCES/cups-memory-consumption.patch | 1220 +++++
SOURCES/cups-multilib.patch | 16 +
SOURCES/cups-no-export-ssllibs.patch | 10 +
SOURCES/cups-no-gzip-man.patch | 18 +
SOURCES/cups-peercred.patch | 11 +
SOURCES/cups-pid.patch | 37 +
SOURCES/cups-ppdopen-heap-overflow.patch | 42 +
SOURCES/cups-preservejob-leak.patch | 31 +
SOURCES/cups-rastertoepson-crash.patch | 13 +
SOURCES/cups-res_init.patch | 26 +
SOURCES/cups-restart-job-hold-until.patch | 20 +
SOURCES/cups-retry-current-job-man.patch | 52 +
SOURCES/cups-ricoh-deviceid-oid.patch | 21 +
SOURCES/cups-serverbin-compat.patch | 193 +
SOURCES/cups-sssd.patch | 13 +
SOURCES/cups-str3382.patch | 62 +
SOURCES/cups-strict-ppd-line-length.patch | 30 +
SOURCES/cups-substitute-bad-attrs.patch | 141 +
SOURCES/cups-synconclose.patch | 48 +
SOURCES/cups-system-auth.patch | 38 +
SOURCES/cups-systemd-socket.patch | 73 +
SOURCES/cups-uri-compat.patch | 51 +
SOURCES/cups-usb-paperout.patch | 52 +
SOURCES/cups-use-ipp1.1.patch | 12 +
SOURCES/cups-validate-1st.patch | 28 +
SOURCES/cups-web-devices-timeout.patch | 19 +
SOURCES/cups-ypbind.patch | 12 +
SOURCES/cups.logrotate | 5 +
SOURCES/macros.cups | 1 +
SOURCES/ncp.backend | 51 +
SOURCES/upgrade_get_document.py.in | 171 +
SPECS/cups.spec | 4004 +++++++++++++++++
90 files changed, 15848 insertions(+)
create mode 100644 .cups.metadata
create mode 100644 .gitignore
create mode 100644 SOURCES/0001-Add-support-for-MinTLS-and-MaxTLS-options-Issue-5119.patch
create mode 100644 SOURCES/0001-Add-with-idle-exit-timeout-configure-option.patch
create mode 100644 SOURCES/0001-Add-with-systemd-timeoutstartsec-configure-option.patch
create mode 100644 SOURCES/0001-CVE-2018-4700-Linux-session-cookies-used-a-predictab.patch
create mode 100644 SOURCES/0001-Fix-default-TLS-versions.patch
create mode 100644 SOURCES/0001-Fix-delays-printing-to-lpd-when-reserved-ports-are-e.patch
create mode 100644 SOURCES/0001-Fix-handling-of-MaxJobTime-0-Issue-5438.patch
create mode 100644 SOURCES/0001-Fix-local-privilege-escalation-to-root-and-sandbox-b.patch
create mode 100644 SOURCES/0001-Fix-lpadmin-with-cupsIPPSupplies-and-cupsSNMPSupplie.patch
create mode 100644 SOURCES/0001-Fix-memory-leaks-found-by-Coverity-Issue-5375.patch
create mode 100644 SOURCES/0001-Fix-stuck-multi-file-jobs-Issue-5359-Issue-5413.patch
create mode 100644 SOURCES/0001-Log-result-of-httpGetHostname-BEFORE-closing-the-con.patch
create mode 100644 SOURCES/0001-Multiple-security-disclosure-issues.patch
create mode 100644 SOURCES/0001-Printing-to-old-CUPS-servers-has-been-fixed-Issue-52.patch
create mode 100644 SOURCES/0001-Remove-web-log-buttons.patch
create mode 100644 SOURCES/0001-Require-authentication-for-CUPS-Get-Document.patch
create mode 100644 SOURCES/0001-The-scheduler-could-crash-while-adding-an-IPP-Everyw.patch
create mode 100644 SOURCES/0001-Update-man-pages-for-h-option-Issue-357.patch
create mode 100644 SOURCES/0001-Use-cupsGetNamedDest-for-legacy-printing-APIs-Issue-.patch
create mode 100644 SOURCES/0001-Use-purge-job-instead-of-purge-jobs-when-canceling-a.patch
create mode 100644 SOURCES/0001-cgi-bin-ipp-var.c-Use-guest-user-for-Move-Job-when-n.patch
create mode 100644 SOURCES/0001-cups-dests.c-cupsGetNamedDest-set-IPP_STATUS_ERROR_N.patch
create mode 100644 SOURCES/0001-cups-http-addr.c-Set-listen-backlog-size-to-INT_MAX-.patch
create mode 100644 SOURCES/0001-cups-strlcpy-handle-zero-size.patch
create mode 100644 SOURCES/0001-cups-tls-gnutls.c-Use-always-GNUTLS_SHUT_WR.patch
create mode 100644 SOURCES/0001-httpAddrConnect2-Check-for-error-if-POLLHUP-is-in-va.patch
create mode 100644 SOURCES/0001-scheduler-cert.c-Fix-string-comparison-fixes-CVE-202.patch
create mode 100644 SOURCES/0001-scheduler-conf.c-Print-to-stderr-if-we-don-t-open-cu.patch
create mode 100644 SOURCES/0001-scheduler-job.c-use-gziptoany-for-raw-files-not-just.patch
create mode 100644 SOURCES/cups-autostart-when-enabled.patch
create mode 100644 SOURCES/cups-avahi-address.patch
create mode 100644 SOURCES/cups-avahi-no-threaded.patch
create mode 100644 SOURCES/cups-banners.patch
create mode 100644 SOURCES/cups-cupsd-too-chatty.patch
create mode 100644 SOURCES/cups-cve202010001.patch
create mode 100644 SOURCES/cups-direct-usb.patch
create mode 100644 SOURCES/cups-dirtyclean.patch
create mode 100644 SOURCES/cups-dnssd-deviceid.patch
create mode 100644 SOURCES/cups-do-not-advertise-http-methods.patch
create mode 100644 SOURCES/cups-driverd-timeout.patch
create mode 100644 SOURCES/cups-dymo-deviceid.patch
create mode 100644 SOURCES/cups-eggcups.patch
create mode 100644 SOURCES/cups-etimedout.patch
create mode 100644 SOURCES/cups-failover-backend.patch
create mode 100644 SOURCES/cups-filter-debug.patch
create mode 100644 SOURCES/cups-fips-compliance.patch
create mode 100644 SOURCES/cups-fix-preservejob-times.patch
create mode 100644 SOURCES/cups-freebind.patch
create mode 100644 SOURCES/cups-hp-deviceid-oid.patch
create mode 100644 SOURCES/cups-ipp-multifile.patch
create mode 100644 SOURCES/cups-ippeve-web-support.patch
create mode 100644 SOURCES/cups-kerberos.patch
create mode 100644 SOURCES/cups-logrotate.patch
create mode 100644 SOURCES/cups-logs.patch
create mode 100644 SOURCES/cups-lpr-help.patch
create mode 100644 SOURCES/cups-lspp.patch
create mode 100644 SOURCES/cups-memory-consumption.patch
create mode 100644 SOURCES/cups-multilib.patch
create mode 100644 SOURCES/cups-no-export-ssllibs.patch
create mode 100644 SOURCES/cups-no-gzip-man.patch
create mode 100644 SOURCES/cups-peercred.patch
create mode 100644 SOURCES/cups-pid.patch
create mode 100644 SOURCES/cups-ppdopen-heap-overflow.patch
create mode 100644 SOURCES/cups-preservejob-leak.patch
create mode 100644 SOURCES/cups-rastertoepson-crash.patch
create mode 100644 SOURCES/cups-res_init.patch
create mode 100644 SOURCES/cups-restart-job-hold-until.patch
create mode 100644 SOURCES/cups-retry-current-job-man.patch
create mode 100644 SOURCES/cups-ricoh-deviceid-oid.patch
create mode 100644 SOURCES/cups-serverbin-compat.patch
create mode 100644 SOURCES/cups-sssd.patch
create mode 100644 SOURCES/cups-str3382.patch
create mode 100644 SOURCES/cups-strict-ppd-line-length.patch
create mode 100644 SOURCES/cups-substitute-bad-attrs.patch
create mode 100644 SOURCES/cups-synconclose.patch
create mode 100644 SOURCES/cups-system-auth.patch
create mode 100644 SOURCES/cups-systemd-socket.patch
create mode 100644 SOURCES/cups-uri-compat.patch
create mode 100644 SOURCES/cups-usb-paperout.patch
create mode 100644 SOURCES/cups-use-ipp1.1.patch
create mode 100644 SOURCES/cups-validate-1st.patch
create mode 100644 SOURCES/cups-web-devices-timeout.patch
create mode 100644 SOURCES/cups-ypbind.patch
create mode 100644 SOURCES/cups.logrotate
create mode 100644 SOURCES/macros.cups
create mode 100755 SOURCES/ncp.backend
create mode 100755 SOURCES/upgrade_get_document.py.in
create mode 100644 SPECS/cups.spec
diff --git a/.cups.metadata b/.cups.metadata
new file mode 100644
index 0000000..8869656
--- /dev/null
+++ b/.cups.metadata
@@ -0,0 +1,2 @@
+b5e3389fb9450bfed377c95c0230c029c053acc4 SOURCES/cups-2.2.6-source.tar.gz
+79ee155bed4c18088be472a6e364f37ad6e410a6 SOURCES/cupsprinter.png
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c5e2c0a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+SOURCES/cups-2.2.6-source.tar.gz
+SOURCES/cupsprinter.png
diff --git a/SOURCES/0001-Add-support-for-MinTLS-and-MaxTLS-options-Issue-5119.patch b/SOURCES/0001-Add-support-for-MinTLS-and-MaxTLS-options-Issue-5119.patch
new file mode 100644
index 0000000..810b9ca
--- /dev/null
+++ b/SOURCES/0001-Add-support-for-MinTLS-and-MaxTLS-options-Issue-5119.patch
@@ -0,0 +1,497 @@
+diff -up cups-2.2.6/cups/http-private.h.remove-weak-ciphers cups-2.2.6/cups/http-private.h
+--- cups-2.2.6/cups/http-private.h.remove-weak-ciphers 2017-11-01 15:57:53.000000000 +0100
++++ cups-2.2.6/cups/http-private.h 2018-08-07 11:53:54.985633959 +0200
+@@ -180,13 +180,17 @@ extern "C" {
+
+ # define _HTTP_TLS_NONE 0 /* No TLS options */
+ # define _HTTP_TLS_ALLOW_RC4 1 /* Allow RC4 cipher suites */
+-# define _HTTP_TLS_ALLOW_SSL3 2 /* Allow SSL 3.0 */
+-# define _HTTP_TLS_ALLOW_DH 4 /* Allow DH/DHE key negotiation */
+-# define _HTTP_TLS_DENY_TLS10 16 /* Deny TLS 1.0 */
+-# define _HTTP_TLS_DENY_CBC 32 /* Deny CBC cipher suites */
+-# define _HTTP_TLS_ONLY_TLS10 64 /* Only use TLS 1.0 */
++# define _HTTP_TLS_ALLOW_DH 2 /* Allow DH/DHE key negotiation */
++# define _HTTP_TLS_DENY_CBC 4 /* Deny CBC cipher suites */
+ # define _HTTP_TLS_SET_DEFAULT 128 /* Setting the default TLS options */
+
++# define _HTTP_TLS_SSL3 0 /* Min/max version is SSL/3.0 */
++# define _HTTP_TLS_1_0 1 /* Min/max version is TLS/1.0 */
++# define _HTTP_TLS_1_1 2 /* Min/max version is TLS/1.1 */
++# define _HTTP_TLS_1_2 3 /* Min/max version is TLS/1.2 */
++# define _HTTP_TLS_1_3 4 /* Min/max version is TLS/1.3 */
++# define _HTTP_TLS_MAX 5 /* Highest known TLS version */
++
+
+ /*
+ * Types and functions for SSL support...
+@@ -442,7 +446,7 @@ extern void _httpTLSInitialize(void);
+ extern size_t _httpTLSPending(http_t *http);
+ extern int _httpTLSRead(http_t *http, char *buf, int len);
+ extern int _httpTLSSetCredentials(http_t *http);
+-extern void _httpTLSSetOptions(int options);
++extern void _httpTLSSetOptions(int options, int min_version, int max_version);
+ extern int _httpTLSStart(http_t *http);
+ extern void _httpTLSStop(http_t *http);
+ extern int _httpTLSWrite(http_t *http, const char *buf, int len);
+diff -up cups-2.2.6/cups/tlscheck.c.remove-weak-ciphers cups-2.2.6/cups/tlscheck.c
+--- cups-2.2.6/cups/tlscheck.c.remove-weak-ciphers 2017-11-01 15:57:53.000000000 +0100
++++ cups-2.2.6/cups/tlscheck.c 2018-08-07 11:53:54.987633942 +0200
+@@ -54,6 +54,8 @@ main(int argc, /* I - Number of comm
+ int af = AF_UNSPEC, /* Address family */
+ tls_options = _HTTP_TLS_NONE,
+ /* TLS options */
++ tls_min_version = _HTTP_TLS_1_0,
++ tls_max_version = _HTTP_TLS_MAX,
+ verbose = 0; /* Verbosity */
+ ipp_t *request, /* IPP Get-Printer-Attributes request */
+ *response; /* IPP Get-Printer-Attributes response */
+@@ -88,11 +90,12 @@ main(int argc, /* I - Number of comm
+ }
+ else if (!strcmp(argv[i], "--no-tls10"))
+ {
+- tls_options |= _HTTP_TLS_DENY_TLS10;
++ tls_min_version = _HTTP_TLS_1_1;
+ }
+ else if (!strcmp(argv[i], "--tls10"))
+ {
+- tls_options |= _HTTP_TLS_ONLY_TLS10;
++ tls_min_version = _HTTP_TLS_1_0;
++ tls_max_version = _HTTP_TLS_1_0;
+ }
+ else if (!strcmp(argv[i], "--rc4"))
+ {
+@@ -148,7 +151,7 @@ main(int argc, /* I - Number of comm
+ if (!port)
+ port = 631;
+
+- _httpTLSSetOptions(tls_options);
++ _httpTLSSetOptions(tls_options, tls_min_version, tls_max_version);
+
+ http = httpConnect2(server, port, NULL, af, HTTP_ENCRYPTION_ALWAYS, 1, 30000, NULL);
+ if (!http)
+diff -up cups-2.2.6/cups/tls-darwin.c.remove-weak-ciphers cups-2.2.6/cups/tls-darwin.c
+--- cups-2.2.6/cups/tls-darwin.c.remove-weak-ciphers 2017-11-01 15:57:53.000000000 +0100
++++ cups-2.2.6/cups/tls-darwin.c 2018-08-07 11:53:54.986633951 +0200
+@@ -53,7 +53,9 @@ static char *tls_keypath = NULL;
+ /* Server cert keychain path */
+ static _cups_mutex_t tls_mutex = _CUPS_MUTEX_INITIALIZER;
+ /* Mutex for keychain/certs */
+-static int tls_options = -1;/* Options for TLS connections */
++static int tls_options = -1,/* Options for TLS connections */
++ tls_min_version = _HTTP_TLS_1_0,
++ tls_max_version = _HTTP_TLS_MAX;
+
+
+ /*
+@@ -1139,10 +1141,16 @@ _httpTLSRead(http_t *http, /* I - HTTP
+ */
+
+ void
+-_httpTLSSetOptions(int options) /* I - Options */
++_httpTLSSetOptions(int options, /* I - Options */
++ int min_version, /* I - Minimum TLS version */
++ int max_version) /* I - Maximum TLS version */
+ {
+ if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0)
+- tls_options = options;
++ {
++ tls_options = options;
++ tls_min_version = min_version;
++ tls_max_version = max_version;
++ }
+ }
+
+
+@@ -1174,7 +1182,7 @@ _httpTLSStart(http_t *http) /* I - HTTP
+ {
+ DEBUG_puts("4_httpTLSStart: Setting defaults.");
+ _cupsSetDefaults();
+- DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options));
++ DEBUG_printf(("4_httpTLSStart: tls_options=%x, tls_min_version=%d, tls_max_version=%d", tls_options, tls_min_version, tls_max_version));
+ }
+
+ #ifdef HAVE_SECKEYCHAINOPEN
+@@ -1217,22 +1225,23 @@ _httpTLSStart(http_t *http) /* I - HTTP
+
+ if (!error)
+ {
+- SSLProtocol minProtocol;
+-
+- if (tls_options & _HTTP_TLS_DENY_TLS10)
+- minProtocol = kTLSProtocol11;
+- else if (tls_options & _HTTP_TLS_ALLOW_SSL3)
+- minProtocol = kSSLProtocol3;
+- else
+- minProtocol = kTLSProtocol1;
++ static const SSLProtocol protocols[] = /* Min/max protocol versions */
++ {
++ kSSLProtocol3,
++ kTLSProtocol1,
++ kTLSProtocol11,
++ kTLSProtocol12,
++ kTLSProtocol13,
++ kTLSProtocolMaxSupported
++ };
+
+- error = SSLSetProtocolVersionMin(http->tls, minProtocol);
+- DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMin(%d), error=%d", minProtocol, (int)error));
++ error = SSLSetProtocolVersionMin(http->tls, protocols[tls_min_version]);
++ DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMin(%d), error=%d", protocols[tls_min_version], (int)error));
+
+- if (!error && (tls_options & _HTTP_TLS_ONLY_TLS10))
++ if (!error)
+ {
+- error = SSLSetProtocolVersionMax(http->tls, kTLSProtocol1);
+- DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMax(kTLSProtocol1), error=%d", (int)error));
++ error = SSLSetProtocolVersionMax(http->tls, protocols[tls_max_version]);
++ DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMax(%d), error=%d", protocols[tls_max_version], (int)error));
+ }
+ }
+
+diff -up cups-2.2.6/cups/tls-gnutls.c.remove-weak-ciphers cups-2.2.6/cups/tls-gnutls.c
+--- cups-2.2.6/cups/tls-gnutls.c.remove-weak-ciphers 2017-11-01 15:57:53.000000000 +0100
++++ cups-2.2.6/cups/tls-gnutls.c 2018-08-07 11:58:45.164114342 +0200
+@@ -35,7 +35,9 @@ static char *tls_keypath = NULL;
+ /* Server cert keychain path */
+ static _cups_mutex_t tls_mutex = _CUPS_MUTEX_INITIALIZER;
+ /* Mutex for keychain/certs */
+-static int tls_options = -1;/* Options for TLS connections */
++static int tls_options = -1,/* Options for TLS connections */
++ tls_min_version = _HTTP_TLS_1_0,
++ tls_max_version = _HTTP_TLS_MAX;
+
+
+ /*
+@@ -1224,10 +1226,16 @@ _httpTLSSetCredentials(http_t *http) /*
+ */
+
+ void
+-_httpTLSSetOptions(int options) /* I - Options */
++_httpTLSSetOptions(int options, /* I - Options */
++ int min_version, /* I - Minimum TLS version */
++ int max_version) /* I - Maximum TLS version */
+ {
+ if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0)
+- tls_options = options;
++ {
++ tls_options = options;
++ tls_min_version = min_version;
++ tls_max_version = max_version;
++ }
+ }
+
+
+@@ -1245,6 +1253,16 @@ _httpTLSStart(http_t *http) /* I - Conn
+ /* TLS credentials */
+ char priority_string[2048];
+ /* Priority string */
++ int version; /* Current version */
++ static const char * const versions[] =/* SSL/TLS versions */
++ {
++ "VERS-SSL3.0",
++ "VERS-TLS1.0",
++ "VERS-TLS1.1",
++ "VERS-TLS1.2",
++ "VERS-TLS1.3",
++ "VERS-TLS-ALL"
++ };
+
+
+ DEBUG_printf(("3_httpTLSStart(http=%p)", http));
+@@ -1506,14 +1524,40 @@ _httpTLSStart(http_t *http) /* I - Conn
+
+ strlcpy(priority_string, "NORMAL", sizeof(priority_string));
+
+- if (tls_options & _HTTP_TLS_DENY_TLS10)
+- strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-TLS1.0:-VERS-SSL3.0", sizeof(priority_string));
+- else if (tls_options & _HTTP_TLS_ALLOW_SSL3)
++ if (tls_max_version < _HTTP_TLS_MAX)
++ {
++ /*
++ * Require specific TLS versions...
++ */
++
++ strlcat(priority_string, ":-VERS-TLS-ALL", sizeof(priority_string));
++ for (version = tls_min_version; version <= tls_max_version; version ++)
++ {
++ strlcat(priority_string, ":+", sizeof(priority_string));
++ strlcat(priority_string, versions[version], sizeof(priority_string));
++ }
++ }
++ else if (tls_min_version == _HTTP_TLS_SSL3)
++ {
++ /*
++ * Allow all versions of TLS and SSL/3.0...
++ */
++
+ strlcat(priority_string, ":+VERS-TLS-ALL:+VERS-SSL3.0", sizeof(priority_string));
+- else if (tls_options & _HTTP_TLS_ONLY_TLS10)
+- strlcat(priority_string, ":-VERS-TLS-ALL:-VERS-SSL3.0:+VERS-TLS1.0", sizeof(priority_string));
++ }
+ else
+- strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-SSL3.0", sizeof(priority_string));
++ {
++ /*
++ * Require a minimum version...
++ */
++
++ strlcat(priority_string, ":+VERS-TLS-ALL", sizeof(priority_string));
++ for (version = 0; version < tls_min_version; version ++)
++ {
++ strlcat(priority_string, ":-", sizeof(priority_string));
++ strlcat(priority_string, versions[version], sizeof(priority_string));
++ }
++ }
+
+ if (tls_options & _HTTP_TLS_ALLOW_RC4)
+ strlcat(priority_string, ":+ARCFOUR-128", sizeof(priority_string));
+diff -up cups-2.2.6/cups/tls-sspi.c.remove-weak-ciphers cups-2.2.6/cups/tls-sspi.c
+--- cups-2.2.6/cups/tls-sspi.c.remove-weak-ciphers 2017-11-01 15:57:53.000000000 +0100
++++ cups-2.2.6/cups/tls-sspi.c 2018-08-07 11:53:54.986633951 +0200
+@@ -52,7 +52,9 @@
+ * Local globals...
+ */
+
+-static int tls_options = -1;/* Options for TLS connections */
++static int tls_options = -1,/* Options for TLS connections */
++ tls_min_version = _HTTP_TLS_1_0,
++ tls_max_version = _HTTP_TLS_MAX;
+
+
+ /*
+@@ -914,7 +916,11 @@ void
+ _httpTLSSetOptions(int options) /* I - Options */
+ {
+ if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0)
+- tls_options = options;
++ {
++ tls_options = options;
++ tls_min_version = min_version;
++ tls_max_version = max_version;
++ }
+ }
+
+
+@@ -1782,14 +1788,14 @@ http_sspi_find_credentials(
+ #else
+ if (http->mode == _HTTP_MODE_SERVER)
+ {
+- if (tls_options & _HTTP_TLS_ALLOW_SSL3)
++ if (tls_min_version == _HTTP_TLS_SSL3)
+ SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER;
+ else
+ SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER;
+ }
+ else
+ {
+- if (tls_options & _HTTP_TLS_ALLOW_SSL3)
++ if (tls_min_version == _HTTP_TLS_SSL3)
+ SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT | SP_PROT_SSL3_CLIENT;
+ else
+ SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;
+diff -up cups-2.2.6/cups/usersys.c.remove-weak-ciphers cups-2.2.6/cups/usersys.c
+--- cups-2.2.6/cups/usersys.c.remove-weak-ciphers 2018-08-07 11:53:54.945634283 +0200
++++ cups-2.2.6/cups/usersys.c 2018-08-07 11:53:54.987633942 +0200
+@@ -54,7 +54,9 @@
+ typedef struct _cups_client_conf_s /**** client.conf config data ****/
+ {
+ #ifdef HAVE_SSL
+- int ssl_options; /* SSLOptions values */
++ int ssl_options, /* SSLOptions values */
++ ssl_min_version,/* Minimum SSL/TLS version */
++ ssl_max_version;/* Maximum SSL/TLS version */
+ #endif /* HAVE_SSL */
+ int trust_first, /* Trust on first use? */
+ any_root, /* Allow any (e.g., self-signed) root */
+@@ -957,7 +959,7 @@ _cupsSetDefaults(void)
+ cg->validate_certs = cc.validate_certs;
+
+ #ifdef HAVE_SSL
+- _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT);
++ _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT, cc.ssl_min_version, cc.ssl_max_version);
+ #endif /* HAVE_SSL */
+ }
+
+@@ -1336,7 +1338,9 @@ cups_set_ssl_options(
+ * SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyTLS1.0] [None]
+ */
+
+- int options = _HTTP_TLS_NONE; /* SSL/TLS options */
++ int options = _HTTP_TLS_NONE, /* SSL/TLS options */
++ min_version = _HTTP_TLS_1_0, /* Minimum SSL/TLS version */
++ max_version = _HTTP_TLS_MAX; /* Maximum SSL/TLS version */
+ char temp[256], /* Copy of value */
+ *start, /* Start of option */
+ *end; /* End of option */
+@@ -1364,20 +1368,38 @@ cups_set_ssl_options(
+ if (!_cups_strcasecmp(start, "AllowRC4"))
+ options |= _HTTP_TLS_ALLOW_RC4;
+ else if (!_cups_strcasecmp(start, "AllowSSL3"))
+- options |= _HTTP_TLS_ALLOW_SSL3;
++ min_version = _HTTP_TLS_SSL3;
+ else if (!_cups_strcasecmp(start, "AllowDH"))
+ options |= _HTTP_TLS_ALLOW_DH;
+ else if (!_cups_strcasecmp(start, "DenyCBC"))
+ options |= _HTTP_TLS_DENY_CBC;
+ else if (!_cups_strcasecmp(start, "DenyTLS1.0"))
+- options |= _HTTP_TLS_DENY_TLS10;
++ min_version = _HTTP_TLS_1_1;
++ else if (!_cups_strcasecmp(start, "MaxTLS1.0"))
++ max_version = _HTTP_TLS_1_0;
++ else if (!_cups_strcasecmp(start, "MaxTLS1.1"))
++ max_version = _HTTP_TLS_1_1;
++ else if (!_cups_strcasecmp(start, "MaxTLS1.2"))
++ max_version = _HTTP_TLS_1_2;
++ else if (!_cups_strcasecmp(start, "MaxTLS1.3"))
++ max_version = _HTTP_TLS_1_3;
++ else if (!_cups_strcasecmp(start, "MinTLS1.0"))
++ min_version = _HTTP_TLS_1_0;
++ else if (!_cups_strcasecmp(start, "MinTLS1.1"))
++ min_version = _HTTP_TLS_1_1;
++ else if (!_cups_strcasecmp(start, "MinTLS1.2"))
++ min_version = _HTTP_TLS_1_2;
++ else if (!_cups_strcasecmp(start, "MinTLS1.3"))
++ min_version = _HTTP_TLS_1_3;
+ else if (!_cups_strcasecmp(start, "None"))
+ options = _HTTP_TLS_NONE;
+ }
+
+- cc->ssl_options = options;
++ cc->ssl_options = options;
++ cc->ssl_max_version = max_version;
++ cc->ssl_min_version = min_version;
+
+- DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x", (void *)cc, value, options));
++ DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x, min_version=%d, max_version=%d", (void *)cc, value, options, min_version, max_version));
+ }
+ #endif /* HAVE_SSL */
+
+diff -up cups-2.2.6/man/client.conf.man.in.remove-weak-ciphers cups-2.2.6/man/client.conf.man.in
+--- cups-2.2.6/man/client.conf.man.in.remove-weak-ciphers 2017-11-01 15:57:53.000000000 +0100
++++ cups-2.2.6/man/client.conf.man.in 2018-08-07 11:53:54.987633942 +0200
+@@ -10,7 +10,7 @@
+ .\" which should have been included with this file. If this file is
+ .\" file is missing or damaged, see the license at "http://www.cups.org/".
+ .\"
+-.TH client.conf 5 "CUPS" "19 October 2017" "Apple Inc."
++.TH client.conf 5 "CUPS" "3 November 2017" "Apple Inc."
+ .SH NAME
+ client.conf \- client configuration file for cups
+ .SH DESCRIPTION
+@@ -56,7 +56,7 @@ Specifies the address and optionally the
+ \fBServerName \fIhostname-or-ip-address\fR[\fI:port\fR]\fB/version=1.1\fR
+ Specifies the address and optionally the port to use when connecting to a server running CUPS 1.3.12 and earlier.
+ .TP 5
+-\fBSSLOptions \fR[\fIAllowDH\fR] [\fIAllowRC4\fR] [\fIAllowSSL3\fR] [\fIDenyCBC\fR] [\fIDenyTLS1.0\fR]
++\fBSSLOptions \fR[\fIAllowDH\fR] [\fIAllowRC4\fR] [\fIAllowSSL3\fR] [\fIDenyCBC\fR] [\fIDenyTLS1.0\fR] [\fIMaxTLS1.0\fR] [\fIMaxTLS1.1\fR] [\fIMaxTLS1.2\fR] [\fIMaxTLS1.3\fR] [\fIMinTLS1.0\fR] [\fIMinTLS1.1\fR] [\fIMinTLS1.2\fR] [\fIMinTLS1.3\fR]
+ .TP 5
+ \fBSSLOptions None\fR
+ Sets encryption options (only in /etc/cups/client.conf).
+@@ -68,6 +68,9 @@ The \fIAllowRC4\fR option enables the 12
+ The \fIAllowSSL3\fR option enables SSL v3.0, which is required for some older clients that do not support TLS v1.0.
+ The \fIDenyCBC\fR option disables all CBC cipher suites.
+ The \fIDenyTLS1.0\fR option disables TLS v1.0 support - this sets the minimum protocol version to TLS v1.1.
++The \fMinTLS\fR options set the minimum TLS version to support.
++The \fMaxTLS\fR options set the maximum TLS version to support.
++Not all operating systems support TLS 1.3 at this time.
+ .TP 5
+ \fBTrustOnFirstUse Yes\fR
+ .TP 5
+diff -up cups-2.2.6/man/cupsd.conf.man.in.remove-weak-ciphers cups-2.2.6/man/cupsd.conf.man.in
+--- cups-2.2.6/man/cupsd.conf.man.in.remove-weak-ciphers 2018-08-07 11:53:54.981633991 +0200
++++ cups-2.2.6/man/cupsd.conf.man.in 2018-08-07 11:53:54.987633942 +0200
+@@ -432,10 +432,11 @@ The default is "Minimal".
+ Listens on the specified address and port for encrypted connections.
+ .\"#SSLOptions
+ .TP 5
+-\fBSSLOptions \fR[\fIAllowDH\fR] [\fIAllowRC4\fR] [\fIAllowSSL3\fR] [\fIDenyCBC\fR] [\fIDenyTLS1.0\fR]
++.TP 5
++\fBSSLOptions \fR[\fIAllowDH\fR] [\fIAllowRC4\fR] [\fIAllowSSL3\fR] [\fIDenyCBC\fR] [\fIDenyTLS1.0\fR] [\fIMaxTLS1.0\fR] [\fIMaxTLS1.1\fR] [\fIMaxTLS1.2\fR] [\fIMaxTLS1.3\fR] [\fIMinTLS1.0\fR] [\fIMinTLS1.1\fR] [\fIMinTLS1.2\fR] [\fIMinTLS1.3\fR]
+ .TP 5
+ \fBSSLOptions None\fR
+-Sets encryption options.
++Sets encryption options (only in /etc/cups/client.conf).
+ By default, CUPS only supports encryption using TLS v1.0 or higher using known secure cipher suites.
+ Security is reduced when \fIAllow\fR options are used.
+ Security is enhanced when \fIDeny\fR options are used.
+@@ -444,6 +445,9 @@ The \fIAllowRC4\fR option enables the 12
+ The \fIAllowSSL3\fR option enables SSL v3.0, which is required for some older clients that do not support TLS v1.0.
+ The \fIDenyCBC\fR option disables all CBC cipher suites.
+ The \fIDenyTLS1.0\fR option disables TLS v1.0 support - this sets the minimum protocol version to TLS v1.1.
++The \fMinTLS\fR options set the minimum TLS version to support.
++The \fMaxTLS\fR options set the maximum TLS version to support.
++Not all operating systems support TLS 1.3 at this time.
+ .\"#SSLPort
+ .TP 5
+ \fBSSLPort \fIport\fR
+diff -up cups-2.2.6/scheduler/conf.c.remove-weak-ciphers cups-2.2.6/scheduler/conf.c
+--- cups-2.2.6/scheduler/conf.c.remove-weak-ciphers 2018-08-07 11:53:54.981633991 +0200
++++ cups-2.2.6/scheduler/conf.c 2018-08-07 11:53:54.988633934 +0200
+@@ -630,7 +630,7 @@ cupsdReadConfiguration(void)
+ cupsdSetString(&ServerKeychain, "/Library/Keychains/System.keychain");
+ # endif /* HAVE_GNUTLS */
+
+- _httpTLSSetOptions(0);
++ _httpTLSSetOptions(_HTTP_TLS_NONE, _HTTP_TLS_1_0, _HTTP_TLS_MAX);
+ #endif /* HAVE_SSL */
+
+ language = cupsLangDefault();
+@@ -3024,7 +3024,9 @@ read_cupsd_conf(cups_file_t *fp) /* I -
+ * SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyCBC] [DenyTLS1.0] [None]
+ */
+
+- int options = 0; /* SSL/TLS options */
++ int options = _HTTP_TLS_NONE,/* SSL/TLS options */
++ min_version = _HTTP_TLS_1_0,
++ max_version = _HTTP_TLS_MAX;
+
+ if (value)
+ {
+@@ -3048,24 +3050,40 @@ read_cupsd_conf(cups_file_t *fp) /* I -
+ * Compare...
+ */
+
+- if (!_cups_strcasecmp(start, "AllowRC4"))
++ if (!_cups_strcasecmp(start, "AllowRC4"))
+ options |= _HTTP_TLS_ALLOW_RC4;
+- else if (!_cups_strcasecmp(start, "AllowSSL3"))
+- options |= _HTTP_TLS_ALLOW_SSL3;
++ else if (!_cups_strcasecmp(start, "AllowSSL3"))
++ min_version = _HTTP_TLS_SSL3;
+ else if (!_cups_strcasecmp(start, "AllowDH"))
+ options |= _HTTP_TLS_ALLOW_DH;
+ else if (!_cups_strcasecmp(start, "DenyCBC"))
+ options |= _HTTP_TLS_DENY_CBC;
+ else if (!_cups_strcasecmp(start, "DenyTLS1.0"))
+- options |= _HTTP_TLS_DENY_TLS10;
+- else if (!_cups_strcasecmp(start, "None"))
+- options = 0;
++ min_version = _HTTP_TLS_1_1;
++ else if (!_cups_strcasecmp(start, "MaxTLS1.0"))
++ max_version = _HTTP_TLS_1_0;
++ else if (!_cups_strcasecmp(start, "MaxTLS1.1"))
++ max_version = _HTTP_TLS_1_1;
++ else if (!_cups_strcasecmp(start, "MaxTLS1.2"))
++ max_version = _HTTP_TLS_1_2;
++ else if (!_cups_strcasecmp(start, "MaxTLS1.3"))
++ max_version = _HTTP_TLS_1_3;
++ else if (!_cups_strcasecmp(start, "MinTLS1.0"))
++ min_version = _HTTP_TLS_1_0;
++ else if (!_cups_strcasecmp(start, "MinTLS1.1"))
++ min_version = _HTTP_TLS_1_1;
++ else if (!_cups_strcasecmp(start, "MinTLS1.2"))
++ min_version = _HTTP_TLS_1_2;
++ else if (!_cups_strcasecmp(start, "MinTLS1.3"))
++ min_version = _HTTP_TLS_1_3;
++ else if (!_cups_strcasecmp(start, "None"))
++ options = _HTTP_TLS_NONE;
+ else if (_cups_strcasecmp(start, "NoEmptyFragments"))
+ cupsdLogMessage(CUPSD_LOG_WARN, "Unknown SSL option %s at line %d.", start, linenum);
+ }
+ }
+
+- _httpTLSSetOptions(options);
++ _httpTLSSetOptions(options, min_version, max_version);
+ }
+ #endif /* HAVE_SSL */
+ else if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")
diff --git a/SOURCES/0001-Add-with-idle-exit-timeout-configure-option.patch b/SOURCES/0001-Add-with-idle-exit-timeout-configure-option.patch
new file mode 100644
index 0000000..5a638e1
--- /dev/null
+++ b/SOURCES/0001-Add-with-idle-exit-timeout-configure-option.patch
@@ -0,0 +1,33 @@
+diff -up cups-2.2.6/conf/cupsd.conf.in.idleexittimeout cups-2.2.6/conf/cupsd.conf.in
+--- cups-2.2.6/conf/cupsd.conf.in.idleexittimeout 2017-11-01 15:57:53.000000000 +0100
++++ cups-2.2.6/conf/cupsd.conf.in 2021-11-29 11:45:37.416058954 +0100
+@@ -22,6 +22,9 @@ DefaultAuthType Basic
+ # Web interface setting...
+ WebInterface @CUPS_WEBIF@
+
++# Timeout after cupsd exits if idle (applied only if cupsd runs on-demand - with -l)
++IdleExitTimeout @EXIT_TIMEOUT@
++
+ # Restrict access to the server...
+
+ Order allow,deny
+diff -up cups-2.2.6/config-scripts/cups-defaults.m4.idleexittimeout cups-2.2.6/config-scripts/cups-defaults.m4
+--- cups-2.2.6/config-scripts/cups-defaults.m4.idleexittimeout 2021-11-29 11:45:37.416058954 +0100
++++ cups-2.2.6/config-scripts/cups-defaults.m4 2021-11-29 11:46:31.680612421 +0100
+@@ -425,3 +425,16 @@ esac
+
+ AC_SUBST(CUPS_WEBIF)
+ AC_DEFINE_UNQUOTED(CUPS_DEFAULT_WEBIF, $CUPS_DEFAULT_WEBIF)
++
++dnl Set default value of IdleExitTimeout
++AC_ARG_WITH([idle_exit_timeout], AS_HELP_STRING([--with-idle-exit-timeout], [set the default value for IdleExitTimeout, default=60]), [
++ AS_IF([test "x$withval" = "xno"], [
++ EXIT_TIMEOUT=0
++ ], [
++ EXIT_TIMEOUT=$withval
++ ])
++], [
++ EXIT_TIMEOUT=60
++])
++
++AC_SUBST([EXIT_TIMEOUT])
diff --git a/SOURCES/0001-Add-with-systemd-timeoutstartsec-configure-option.patch b/SOURCES/0001-Add-with-systemd-timeoutstartsec-configure-option.patch
new file mode 100644
index 0000000..af83a6c
--- /dev/null
+++ b/SOURCES/0001-Add-with-systemd-timeoutstartsec-configure-option.patch
@@ -0,0 +1,33 @@
+diff -up cups-2.3.3op2/config-scripts/cups-defaults.m4.conf-timeoutstartsec cups-2.3.3op2/config-scripts/cups-defaults.m4
+--- cups-2.3.3op2/config-scripts/cups-defaults.m4.conf-timeoutstartsec 2021-11-29 13:50:14.568976028 +0100
++++ cups-2.3.3op2/config-scripts/cups-defaults.m4 2021-11-29 13:51:02.785567762 +0100
+@@ -482,3 +482,18 @@ AC_ARG_WITH([idle_exit_timeout], AS_HELP
+ ])
+
+ AC_SUBST([EXIT_TIMEOUT])
++
++dnl set TimeoutStartSec for cups.service
++dnl - if used as --without-*, it sets TimeoutStartSec to infinity
++AC_ARG_WITH([systemd-timeoutstartsec],
++ AS_HELP_STRING([--with-systemd-timeoutstartsec],
++ [set TimeoutStartSec value in cups.service, default=default value in systemd]), [
++ AS_IF([ test "x$withval" = "xno" ], [
++ TIMEOUTSTARTSEC="TimeoutStartSec=infinity"
++ ], [
++ TIMEOUTSTARTSEC="TimeoutStartSec=$withval"
++ ])
++], [
++ TIMEOUTSTARTSEC=""
++])
++AC_SUBST([TIMEOUTSTARTSEC])
+diff -up cups-2.3.3op2/scheduler/org.cups.cupsd.service.in.conf-timeoutstartsec cups-2.3.3op2/scheduler/org.cups.cupsd.service.in
+--- cups-2.3.3op2/scheduler/org.cups.cupsd.service.in.conf-timeoutstartsec 2021-11-29 13:50:14.551976172 +0100
++++ cups-2.3.3op2/scheduler/org.cups.cupsd.service.in 2021-11-29 13:50:14.568976028 +0100
+@@ -8,6 +8,7 @@ Requires=cups.socket
+ ExecStart=@sbindir@/cupsd -l
+ Type=notify
+ Restart=on-failure
++@TIMEOUTSTARTSEC@
+
+ [Install]
+ Also=cups.socket cups.path
diff --git a/SOURCES/0001-CVE-2018-4700-Linux-session-cookies-used-a-predictab.patch b/SOURCES/0001-CVE-2018-4700-Linux-session-cookies-used-a-predictab.patch
new file mode 100644
index 0000000..2745b5d
--- /dev/null
+++ b/SOURCES/0001-CVE-2018-4700-Linux-session-cookies-used-a-predictab.patch
@@ -0,0 +1,22 @@
+diff --git a/cgi-bin/var.c b/cgi-bin/var.c
+index 316b67f05..12f3c8344 100644
+--- a/cgi-bin/var.c
++++ b/cgi-bin/var.c
+@@ -1186,6 +1186,7 @@ cgi_set_sid(void)
+ const char *remote_addr, /* REMOTE_ADDR */
+ *server_name, /* SERVER_NAME */
+ *server_port; /* SERVER_PORT */
++ struct timeval curtime; /* Current time */
+
+
+ if ((remote_addr = getenv("REMOTE_ADDR")) == NULL)
+@@ -1195,7 +1196,8 @@ cgi_set_sid(void)
+ if ((server_port = getenv("SERVER_PORT")) == NULL)
+ server_port = "SERVER_PORT";
+
+- CUPS_SRAND(time(NULL));
++ gettimeofday(&curtime, NULL);
++ CUPS_SRAND(curtime.tv_sec + curtime.tv_usec);
+ snprintf(buffer, sizeof(buffer), "%s:%s:%s:%02X%02X%02X%02X%02X%02X%02X%02X",
+ remote_addr, server_name, server_port,
+ (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
diff --git a/SOURCES/0001-Fix-default-TLS-versions.patch b/SOURCES/0001-Fix-default-TLS-versions.patch
new file mode 100644
index 0000000..b3821d6
--- /dev/null
+++ b/SOURCES/0001-Fix-default-TLS-versions.patch
@@ -0,0 +1,24 @@
+diff -up cups-2.2.6/cups/usersys.c.defaulttls cups-2.2.6/cups/usersys.c
+--- cups-2.2.6/cups/usersys.c.defaulttls 2018-09-03 12:10:36.111230611 +0200
++++ cups-2.2.6/cups/usersys.c 2018-09-03 12:12:41.307074414 +0200
+@@ -1166,11 +1166,15 @@ cups_init_client_conf(
+
+ memset(cc, 0, sizeof(_cups_client_conf_t));
+
+- cc->encryption = (http_encryption_t)-1;
+- cc->trust_first = -1;
+- cc->any_root = -1;
+- cc->expired_certs = -1;
+- cc->validate_certs = -1;
++#ifdef HAVE_SSL
++ cc->ssl_min_version = _HTTP_TLS_1_0;
++ cc->ssl_max_version = _HTTP_TLS_MAX;
++#endif /* HAVE_SSL */
++ cc->encryption = (http_encryption_t)-1;
++ cc->trust_first = -1;
++ cc->any_root = -1;
++ cc->expired_certs = -1;
++ cc->validate_certs = -1;
+
+ /*
+ * Load settings from the org.cups.PrintingPrefs plist (which trump
diff --git a/SOURCES/0001-Fix-delays-printing-to-lpd-when-reserved-ports-are-e.patch b/SOURCES/0001-Fix-delays-printing-to-lpd-when-reserved-ports-are-e.patch
new file mode 100644
index 0000000..fdec951
--- /dev/null
+++ b/SOURCES/0001-Fix-delays-printing-to-lpd-when-reserved-ports-are-e.patch
@@ -0,0 +1,21 @@
+diff -up cups-2.3.3op2/backend/lpd.c.lpd-delay cups-2.3.3op2/backend/lpd.c
+--- cups-2.3.3op2/backend/lpd.c.lpd-delay 2021-02-01 22:10:25.000000000 +0100
++++ cups-2.3.3op2/backend/lpd.c 2023-06-28 17:28:52.465476261 +0200
+@@ -63,7 +63,7 @@ static int abort_job = 0; /* Non-zero i
+
+ #define RESERVE_NONE 0 /* Don't reserve a priviledged port */
+ #define RESERVE_RFC1179 1 /* Reserve port 721-731 */
+-#define RESERVE_ANY 2 /* Reserve port 1-1023 */
++#define RESERVE_ANY 2 /* Reserve port 512-1023 */
+
+
+ /*
+@@ -778,7 +778,7 @@ lpd_queue(const char *hostname, /*
+
+ if (lport < 721 && reserve == RESERVE_RFC1179)
+ lport = 731;
+- else if (lport < 1)
++ else if (lport < 512)
+ lport = 1023;
+
+ #ifdef HAVE_GETEUID
diff --git a/SOURCES/0001-Fix-handling-of-MaxJobTime-0-Issue-5438.patch b/SOURCES/0001-Fix-handling-of-MaxJobTime-0-Issue-5438.patch
new file mode 100644
index 0000000..e7f586c
--- /dev/null
+++ b/SOURCES/0001-Fix-handling-of-MaxJobTime-0-Issue-5438.patch
@@ -0,0 +1,43 @@
+From 3e4dd41459dabc5d18edbe06eb5b81291885204b Mon Sep 17 00:00:00 2001
+From: Michael R Sweet
+Date: Wed, 5 Dec 2018 12:18:19 -0500
+Subject: [PATCH] Fix handling of MaxJobTime 0 (Issue #5438)
+
+---
+ CHANGES.md | 5 +++--
+ scheduler/job.c | 4 +++-
+ scheduler/printers.c | 2 +-
+ 3 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/scheduler/job.c b/scheduler/job.c
+index 3cbe56aa8..638f256db 100644
+--- a/scheduler/job.c
++++ b/scheduler/job.c
+@@ -5148,8 +5148,10 @@ update_job(cupsd_job_t *job) /* I - Job to check */
+
+ if (cancel_after)
+ job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0);
+- else
++ else if (MaxJobTime > 0)
+ job->cancel_time = time(NULL) + MaxJobTime;
++ else
++ job->cancel_time = 0;
+ }
+ }
+ }
+diff --git a/scheduler/printers.c b/scheduler/printers.c
+index bb99907ad..68239d85d 100644
+--- a/scheduler/printers.c
++++ b/scheduler/printers.c
+@@ -3370,7 +3370,7 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */
+ "document-format-default", NULL, "application/octet-stream");
+
+ if (!cupsGetOption("job-cancel-after", p->num_options, p->options))
+- ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
++ ippAddInteger(p->attrs, IPP_TAG_PRINTER, MaxJobTime > 0 ? IPP_TAG_INTEGER : IPP_TAG_NOVALUE,
+ "job-cancel-after-default", MaxJobTime);
+
+ if (!cupsGetOption("job-hold-until", p->num_options, p->options))
+--
+2.31.1
+
diff --git a/SOURCES/0001-Fix-local-privilege-escalation-to-root-and-sandbox-b.patch b/SOURCES/0001-Fix-local-privilege-escalation-to-root-and-sandbox-b.patch
new file mode 100644
index 0000000..dfb74a1
--- /dev/null
+++ b/SOURCES/0001-Fix-local-privilege-escalation-to-root-and-sandbox-b.patch
@@ -0,0 +1,481 @@
+From d47f6aec436e0e9df6554436e391471097686ecc Mon Sep 17 00:00:00 2001
+From: Michael R Sweet
+Date: Tue, 8 May 2018 15:24:21 -0700
+Subject: [PATCH] Fix local privilege escalation to root and sandbox bypasses
+ in scheduler (rdar://37836779, rdar://37836995, rdar://37837252,
+ rdar://37837581)
+
+---
+ man/cups-files.conf.man.in | 10 ++
+ man/cupsd.conf.man.in | 8 --
+ scheduler/conf.c | 201 +++++++++++++++++++++++--------------
+ scheduler/job.c | 12 +++
+ scheduler/process.c | 16 +--
+ scheduler/server.c | 20 +++-
+ test/run-stp-tests.sh | 11 +-
+ 7 files changed, 179 insertions(+), 99 deletions(-)
+
+diff --git a/man/cups-files.conf.man.in b/man/cups-files.conf.man.in
+index 7b96d687d..baf3cb6af 100644
+--- a/man/cups-files.conf.man.in
++++ b/man/cups-files.conf.man.in
+@@ -153,6 +153,11 @@ The server name may be included in filenames using the string "%s", for example:
+
+ .fi
+ The default is "/var/log/cups/page_log".
++.\"#PassEnv
++.TP 5
++\fBPassEnv \fIvariable \fR[ ... \fIvariable \fR]
++Passes the specified environment variable(s) to child processes.
++Note: the standard CUPS filter and backend environment variables cannot be overridden using this directive.
+ .\"#RemoteRoot
+ .TP 5
+ \fBRemoteRoot \fIusername\fR
+@@ -187,6 +192,11 @@ macOS uses its keychain database to store certificates and keys while other plat
+ \fBServerRoot \fIdirectory\fR
+ Specifies the directory containing the server configuration files.
+ The default is "/etc/cups".
++.\"#SetEnv
++.TP 5
++\fBSetEnv \fIvariable value\fR
++Set the specified environment variable to be passed to child processes.
++Note: the standard CUPS filter and backend environment variables cannot be overridden using this directive.
+ .\"#StateDir
+ .TP 5
+ \fBStateDir \fIdirectory\fR
+diff --git a/man/cupsd.conf.man.in b/man/cupsd.conf.man.in
+index 3ffc80e42..36c849398 100644
+--- a/man/cupsd.conf.man.in
++++ b/man/cupsd.conf.man.in
+@@ -349,10 +349,6 @@ The default is "1048576" (1MB).
+ \fBMultipleOperationTimeout \fIseconds\fR
+ Specifies the maximum amount of time to allow between files in a multiple file print job.
+ The default is "300" (5 minutes).
+-.\"#PassEnv
+-.TP 5
+-\fBPassEnv \fIvariable \fR[ ... \fIvariable \fR]
+-Passes the specified environment variable(s) to child processes.
+ .\"#Policy
+ .TP 5
+ \fB \fR... \fB\fR
+@@ -433,10 +429,6 @@ Specifies what information is included in the Server header of HTTP responses.
+ command.
+ "Full" reports "CUPS 2.0.0 (UNAME) IPP/2.0".
+ The default is "Minimal".
+-.\"#SetEnv
+-.TP 5
+-\fBSetEnv \fIvariable value\fR
+-Set the specified environment variable to be passed to child processes.
+ .\"#SSLListen
+ .TP 5
+ \fBSSLListen \fIipv4-address\fB:\fIport\fR
+diff --git a/scheduler/conf.c b/scheduler/conf.c
+index 67a91e7a6..b51c6060c 100644
+--- a/scheduler/conf.c
++++ b/scheduler/conf.c
+@@ -2929,13 +2929,10 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
+ /* Line from file */
+ temp[HTTP_MAX_BUFFER],
+ /* Temporary buffer for value */
+- *value, /* Pointer to value */
+- *valueptr; /* Pointer into value */
++ *value; /* Pointer to value */
+ int valuelen; /* Length of value */
+ http_addrlist_t *addrlist, /* Address list */
+ *addr; /* Current address */
+- cups_file_t *incfile; /* Include file */
+- char incname[1024]; /* Include filename */
+
+
+ /*
+@@ -2950,28 +2947,7 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
+ * Decode the directive...
+ */
+
+- if (!_cups_strcasecmp(line, "Include") && value)
+- {
+- /*
+- * Include filename
+- */
+-
+- if (value[0] == '/')
+- strlcpy(incname, value, sizeof(incname));
+- else
+- snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value);
+-
+- if ((incfile = cupsFileOpen(incname, "rb")) == NULL)
+- cupsdLogMessage(CUPSD_LOG_ERROR,
+- "Unable to include config file \"%s\" - %s",
+- incname, strerror(errno));
+- else
+- {
+- read_cupsd_conf(incfile);
+- cupsFileClose(incfile);
+- }
+- }
+- else if (!_cups_strcasecmp(line, "
+@@ -3367,31 +3343,6 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
+ cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d of %s.",
+ value, linenum, ConfigurationFile);
+ }
+- else if (!_cups_strcasecmp(line, "PassEnv") && value)
+- {
+- /*
+- * PassEnv variable [... variable]
+- */
+-
+- for (; *value;)
+- {
+- for (valuelen = 0; value[valuelen]; valuelen ++)
+- if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
+- break;
+-
+- if (value[valuelen])
+- {
+- value[valuelen] = '\0';
+- valuelen ++;
+- }
+-
+- cupsdSetEnv(value, NULL);
+-
+- for (value += valuelen; *value; value ++)
+- if (!_cups_isspace(*value) || *value != ',')
+- break;
+- }
+- }
+ else if (!_cups_strcasecmp(line, "ServerAlias") && value)
+ {
+ /*
+@@ -3420,30 +3371,6 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
+ break;
+ }
+ }
+- else if (!_cups_strcasecmp(line, "SetEnv") && value)
+- {
+- /*
+- * SetEnv variable value
+- */
+-
+- for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+-
+- if (*valueptr)
+- {
+- /*
+- * Found a value...
+- */
+-
+- while (isspace(*valueptr & 255))
+- *valueptr++ = '\0';
+-
+- cupsdSetEnv(value, valueptr);
+- }
+- else
+- cupsdLogMessage(CUPSD_LOG_ERROR,
+- "Missing value for SetEnv directive on line %d of %s.",
+- linenum, ConfigurationFile);
+- }
+ else if (!_cups_strcasecmp(line, "AccessLog") ||
+ !_cups_strcasecmp(line, "CacheDir") ||
+ !_cups_strcasecmp(line, "ConfigFilePerm") ||
+@@ -3457,6 +3384,7 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
+ !_cups_strcasecmp(line, "LogFilePerm") ||
+ !_cups_strcasecmp(line, "LPDConfigFile") ||
+ !_cups_strcasecmp(line, "PageLog") ||
++ !_cups_strcasecmp(line, "PassEnv") ||
+ !_cups_strcasecmp(line, "Printcap") ||
+ !_cups_strcasecmp(line, "PrintcapFormat") ||
+ !_cups_strcasecmp(line, "RemoteRoot") ||
+@@ -3466,6 +3394,7 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
+ !_cups_strcasecmp(line, "ServerKey") ||
+ !_cups_strcasecmp(line, "ServerKeychain") ||
+ !_cups_strcasecmp(line, "ServerRoot") ||
++ !_cups_strcasecmp(line, "SetEnv") ||
+ !_cups_strcasecmp(line, "SMBConfigFile") ||
+ !_cups_strcasecmp(line, "StateDir") ||
+ !_cups_strcasecmp(line, "SystemGroup") ||
+@@ -3495,10 +3424,49 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
+ static int /* O - 1 on success, 0 on failure */
+ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */
+ {
+- int linenum; /* Current line number */
++ int i, /* Looping var */
++ linenum; /* Current line number */
+ char line[HTTP_MAX_BUFFER], /* Line from file */
+ *value; /* Value from line */
+ struct group *group; /* Group */
++ static const char * const prohibited_env[] =
++ { /* Prohibited environment variables */
++ "APPLE_LANGUAGE",
++ "AUTH_DOMAIN",
++ "AUTH_INFO_REQUIRED",
++ "AUTH_NEGOTIATE",
++ "AUTH_PASSWORD",
++ "AUTH_UID",
++ "AUTH_USERNAME",
++ "CHARSET",
++ "CLASS",
++ "CLASSIFICATION",
++ "CONTENT_TYPE",
++ "CUPS_CACHEDIR",
++ "CUPS_DATADIR",
++ "CUPS_DOCROOT",
++ "CUPS_FILETYPE",
++ "CUPS_FONTPATH",
++ "CUPS_MAX_MESSAGE",
++ "CUPS_REQUESTROOT",
++ "CUPS_SERVERBIN",
++ "CUPS_SERVERROOT",
++ "CUPS_STATEDIR",
++ "DEVICE_URI",
++ "FINAL_CONTENT_TYPE",
++ "HOME",
++ "LANG",
++ "PPD",
++ "PRINTER",
++ "PRINTER_INFO",
++ "PRINTER_LOCATION",
++ "PRINTER_STATE_REASONS",
++ "RIP_CACHE",
++ "SERVER_ADMIN",
++ "SOFTWARE",
++ "TMPDIR",
++ "USER"
++ };
+
+
+ /*
+@@ -3536,6 +3504,47 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */
+ }
+ }
+ }
++ else if (!_cups_strcasecmp(line, "PassEnv") && value)
++ {
++ /*
++ * PassEnv variable [... variable]
++ */
++
++ int valuelen; /* Length of variable name */
++
++ for (; *value;)
++ {
++ for (valuelen = 0; value[valuelen]; valuelen ++)
++ if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
++ break;
++
++ if (value[valuelen])
++ {
++ value[valuelen] = '\0';
++ valuelen ++;
++ }
++
++ for (i = 0; i < (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])); i ++)
++ {
++ if (!strcmp(value, prohibited_env[i]))
++ {
++ cupsdLogMessage(CUPSD_LOG_ERROR, "Environment variable \"%s\" cannot be passed through on line %d of %s.", value, linenum, CupsFilesFile);
++
++ if (FatalErrors & CUPSD_FATAL_CONFIG)
++ return (0);
++ else
++ break;
++ }
++ }
++
++ if (i >= (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])))
++ cupsdSetEnv(value, NULL);
++
++ for (value += valuelen; *value; value ++)
++ if (!_cups_isspace(*value) || *value != ',')
++ break;
++ }
++ }
+ else if (!_cups_strcasecmp(line, "PrintcapFormat") && value)
+ {
+ /*
+@@ -3581,6 +3590,46 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */
+ return (0);
+ }
+ }
++ else if (!_cups_strcasecmp(line, "SetEnv") && value)
++ {
++ /*
++ * SetEnv variable value
++ */
++
++ char *valueptr; /* Pointer to environment variable value */
++
++ for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
++
++ if (*valueptr)
++ {
++ /*
++ * Found a value...
++ */
++
++ while (isspace(*valueptr & 255))
++ *valueptr++ = '\0';
++
++ for (i = 0; i < (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])); i ++)
++ {
++ if (!strcmp(value, prohibited_env[i]))
++ {
++ cupsdLogMessage(CUPSD_LOG_ERROR, "Environment variable \"%s\" cannot be set on line %d of %s.", value, linenum, CupsFilesFile);
++
++ if (FatalErrors & CUPSD_FATAL_CONFIG)
++ return (0);
++ else
++ break;
++ }
++ }
++
++ if (i >= (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])))
++ cupsdSetEnv(value, valueptr);
++ }
++ else
++ cupsdLogMessage(CUPSD_LOG_ERROR,
++ "Missing value for SetEnv directive on line %d of %s.",
++ linenum, ConfigurationFile);
++ }
+ else if (!_cups_strcasecmp(line, "SystemGroup") && value)
+ {
+ /*
+diff --git a/scheduler/job.c b/scheduler/job.c
+index 61cda44e2..5ced0b9d1 100644
+--- a/scheduler/job.c
++++ b/scheduler/job.c
+@@ -4779,6 +4779,18 @@ start_job(cupsd_job_t *job, /* I - Job ID */
+ job->profile = cupsdCreateProfile(job->id, 0);
+ job->bprofile = cupsdCreateProfile(job->id, 1);
+
++#ifdef HAVE_SANDBOX_H
++ if ((!job->profile || !job->bprofile) && UseSandboxing && Sandboxing != CUPSD_SANDBOXING_OFF)
++ {
++ /*
++ * Failure to create the sandbox profile means something really bad has
++ * happened and we need to shutdown immediately.
++ */
++
++ return;
++ }
++#endif /* HAVE_SANDBOX_H */
++
+ /*
+ * Create the status pipes and buffer...
+ */
+diff --git a/scheduler/process.c b/scheduler/process.c
+index b8d49d8f0..3c1c6ba4f 100644
+--- a/scheduler/process.c
++++ b/scheduler/process.c
+@@ -98,9 +98,13 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */
+
+ if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL)
+ {
++ /*
++ * This should never happen, and is fatal when sandboxing is enabled.
++ */
++
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking);
+- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s",
+- strerror(errno));
++ cupsdLogMessage(CUPSD_LOG_EMERG, "Unable to create security profile: %s", strerror(errno));
++ kill(getpid(), SIGTERM);
+ return (NULL);
+ }
+
+@@ -197,10 +201,8 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */
+ " #\"^%s/\"" /* TempDir/... */
+ " #\"^%s$\"" /* CacheDir */
+ " #\"^%s/\"" /* CacheDir/... */
+- " #\"^%s$\"" /* StateDir */
+- " #\"^%s/\"" /* StateDir/... */
+ "))\n",
+- temp, temp, cache, cache, state, state);
++ temp, temp, cache, cache);
+ /* Read common folders */
+ cupsFilePrintf(fp,
+ "(allow file-read-data file-read-metadata\n"
+@@ -242,8 +244,10 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */
+ " #\"^%s/\"" /* ServerBin/... */
+ " #\"^%s$\"" /* ServerRoot */
+ " #\"^%s/\"" /* ServerRoot/... */
++ " #\"^%s$\"" /* StateDir */
++ " #\"^%s/\"" /* StateDir/... */
+ "))\n",
+- request, request, bin, bin, root, root);
++ request, request, bin, bin, root, root, state, state);
+ if (Sandboxing == CUPSD_SANDBOXING_RELAXED)
+ {
+ /* Limited write access to /Library/Printers/... */
+diff --git a/scheduler/server.c b/scheduler/server.c
+index cecbabe67..a4033791b 100644
+--- a/scheduler/server.c
++++ b/scheduler/server.c
+@@ -34,16 +34,28 @@ void
+ cupsdStartServer(void)
+ {
+ /*
+- * Start color management (as needed)...
++ * Create the default security profile...
+ */
+
+- cupsdStartColor();
++ DefaultProfile = cupsdCreateProfile(0, 1);
++
++#ifdef HAVE_SANDBOX_H
++ if (!DefaultProfile && UseSandboxing && Sandboxing != CUPSD_SANDBOXING_OFF)
++ {
++ /*
++ * Failure to create the sandbox profile means something really bad has
++ * happened and we need to shutdown immediately.
++ */
++
++ return;
++ }
++#endif /* HAVE_SANDBOX_H */
+
+ /*
+- * Create the default security profile...
++ * Start color management (as needed)...
+ */
+
+- DefaultProfile = cupsdCreateProfile(0, 1);
++ cupsdStartColor();
+
+ /*
+ * Startup all the networking stuff...
+diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh
+index 7eb269a67..f83bd5d91 100755
+--- a/test/run-stp-tests.sh
++++ b/test/run-stp-tests.sh
+@@ -489,11 +489,6 @@ StrictConformance Yes
+ Browsing Off
+ Listen localhost:$port
+ Listen $BASE/sock
+-PassEnv DYLD_LIBRARY_PATH
+-PassEnv LD_LIBRARY_PATH
+-PassEnv LD_PRELOAD
+-PassEnv LOCALEDIR
+-PassEnv SHLIB_PATH
+ MaxSubscriptions 3
+ MaxLogSize 0
+ AccessLogLevel actions
+@@ -529,6 +524,12 @@ TempDir $BASE/spool/temp
+ AccessLog $BASE/log/access_log
+ ErrorLog $BASE/log/error_log
+ PageLog $BASE/log/page_log
++
++PassEnv DYLD_LIBRARY_PATH
++PassEnv LD_LIBRARY_PATH
++PassEnv LD_PRELOAD
++PassEnv LOCALEDIR
++PassEnv SHLIB_PATH
+ EOF
+
+ if test $ssltype != 0 -a `uname` = Darwin; then
+--
+2.17.1
+
diff --git a/SOURCES/0001-Fix-lpadmin-with-cupsIPPSupplies-and-cupsSNMPSupplie.patch b/SOURCES/0001-Fix-lpadmin-with-cupsIPPSupplies-and-cupsSNMPSupplie.patch
new file mode 100644
index 0000000..8f8fa71
--- /dev/null
+++ b/SOURCES/0001-Fix-lpadmin-with-cupsIPPSupplies-and-cupsSNMPSupplie.patch
@@ -0,0 +1,62 @@
+From 9539c53065170e97836503074e770d7b5fbf9f83 Mon Sep 17 00:00:00 2001
+From: Michael R Sweet
+Date: Tue, 16 Jul 2019 09:27:13 -0400
+Subject: [PATCH] Fix lpadmin with cupsIPPSupplies and cupsSNMPSupplies (Issue
+ #5610)
+
+---
+ CHANGES.md | 2 ++
+ systemv/lpadmin.c | 9 +++++++--
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/systemv/lpadmin.c b/systemv/lpadmin.c
+index f428368d4..ca6d386b2 100644
+--- a/systemv/lpadmin.c
++++ b/systemv/lpadmin.c
+@@ -1467,6 +1467,7 @@ set_printer_options(
+ (boolval = cupsGetOption("cupsIPPSupplies", num_options,
+ options)) != NULL)
+ {
++ ppdchanged = 1;
+ wrote_ipp_supplies = 1;
+ cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
+ (!_cups_strcasecmp(boolval, "true") ||
+@@ -1477,6 +1478,7 @@ set_printer_options(
+ (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
+ options)) != NULL)
+ {
++ ppdchanged = 1;
+ wrote_snmp_supplies = 1;
+ cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
+ (!_cups_strcasecmp(boolval, "true") ||
+@@ -1537,6 +1539,8 @@ set_printer_options(
+ (boolval = cupsGetOption("cupsIPPSupplies", num_options,
+ options)) != NULL)
+ {
++ ppdchanged = 1;
++
+ cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
+ (!_cups_strcasecmp(boolval, "true") ||
+ !_cups_strcasecmp(boolval, "yes") ||
+@@ -1547,6 +1551,8 @@ set_printer_options(
+ (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
+ options)) != NULL)
+ {
++ ppdchanged = 1;
++
+ cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
+ (!_cups_strcasecmp(boolval, "true") ||
+ !_cups_strcasecmp(boolval, "yes") ||
+@@ -1561,8 +1567,7 @@ set_printer_options(
+ * Do the request...
+ */
+
+- ippDelete(cupsDoFileRequest(http, request, "/admin/",
+- ppdchanged ? tempfile : file));
++ ippDelete(cupsDoFileRequest(http, request, "/admin/", ppdchanged ? tempfile : file));
+
+ /*
+ * Clean up temp files... (TODO: catch signals in case we CTRL-C during
+--
+2.31.1
+
diff --git a/SOURCES/0001-Fix-memory-leaks-found-by-Coverity-Issue-5375.patch b/SOURCES/0001-Fix-memory-leaks-found-by-Coverity-Issue-5375.patch
new file mode 100644
index 0000000..ec224c3
--- /dev/null
+++ b/SOURCES/0001-Fix-memory-leaks-found-by-Coverity-Issue-5375.patch
@@ -0,0 +1,206 @@
+diff --git a/backend/ipp.c b/backend/ipp.c
+index 32eb3aaa4..2a880bd75 100644
+--- a/backend/ipp.c
++++ b/backend/ipp.c
+@@ -3612,6 +3612,8 @@ update_reasons(ipp_attribute_t *attr, /* I - printer-state-reasons or NULL */
+ }
+ }
+
++ cupsArrayDelete(new_reasons);
++
+ _cupsMutexUnlock(&report_mutex);
+
+ /*
+diff --git a/cgi-bin/search.c b/cgi-bin/search.c
+index 3956afc33..ad1f5ed0e 100644
+--- a/cgi-bin/search.c
++++ b/cgi-bin/search.c
+@@ -361,4 +362,5 @@ void
+ cgiFreeSearch(void *search) /* I - Search context */
+ {
+ regfree((regex_t *)search);
++ free(search);
+ }
+diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c
+index 5d510140b..688901a7d 100644
+--- a/cups/http-addrlist.c
++++ b/cups/http-addrlist.c
+@@ -612,6 +613,7 @@ httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for p
+ if (!temp)
+ {
+ httpAddrFreeList(first);
++ freeaddrinfo(results);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
+ return (NULL);
+ }
+diff --git a/cups/http.c b/cups/http.c
+index a9235b087..d9332cc83 100644
+--- a/cups/http.c
++++ b/cups/http.c
+@@ -3915,7 +3915,7 @@ http_create(
+ if ((http = calloc(sizeof(http_t), 1)) == NULL)
+ {
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
+- httpAddrFreeList(addrlist);
++ httpAddrFreeList(myaddrlist);
+ return (NULL);
+ }
+
+diff --git a/ppdc/ppdc-source.cxx b/ppdc/ppdc-source.cxx
+index be24cebae..4e8cba7bb 100644
+--- a/ppdc/ppdc-source.cxx
++++ b/ppdc/ppdc-source.cxx
+@@ -2665,6 +2666,7 @@ ppdcSource::scan_file(ppdcFile *fp, // I - File to read
+ // Add it to the current option...
+ if (!o)
+ {
++ c->release();
+ _cupsLangPrintf(stderr,
+ _("ppdc: Choice found on line %d of %s with no "
+ "Option."), fp->line, fp->filename);
+diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx
+index 657eee0a0..b518a9325 100644
+--- a/scheduler/cups-driverd.cxx
++++ b/scheduler/cups-driverd.cxx
+@@ -153,7 +153,7 @@ static ppd_info_t *add_ppd(const char *filename, const char *name,
+ size_t size, int model_number, int type,
+ const char *scheme);
+ static int cat_drv(const char *name, int request_id);
+-static int cat_ppd(const char *name, int request_id);
++static void cat_ppd(const char *name, int request_id);
+ static int cat_static(const char *name, int request_id);
+ static int cat_tar(const char *name, int request_id);
+ static int compare_inodes(struct stat *a, struct stat *b);
+@@ -163,12 +163,12 @@ static int compare_names(const ppd_info_t *p0,
+ const ppd_info_t *p1);
+ static int compare_ppds(const ppd_info_t *p0,
+ const ppd_info_t *p1);
+-static int dump_ppds_dat(const char *filename);
++static void dump_ppds_dat(const char *filename);
+ static void free_array(cups_array_t *a);
+ static cups_file_t *get_file(const char *name, int request_id,
+ const char *subdir, char *buffer,
+ size_t bufsize, char **subfile);
+-static int list_ppds(int request_id, int limit, const char *opt);
++static void list_ppds(int request_id, int limit, const char *opt);
+ static int load_drivers(cups_array_t *include,
+ cups_array_t *exclude);
+ static int load_drv(const char *filename, const char *name,
+@@ -204,13 +204,13 @@ main(int argc, /* I - Number of command-line args */
+ */
+
+ if (argc == 3 && !strcmp(argv[1], "cat"))
+- return (cat_ppd(argv[2], 0));
++ cat_ppd(argv[2], 0);
+ else if ((argc == 2 || argc == 3) && !strcmp(argv[1], "dump"))
+- return (dump_ppds_dat(argv[2]));
++ dump_ppds_dat(argv[2]);
+ else if (argc == 4 && !strcmp(argv[1], "get"))
+- return (cat_ppd(argv[3], atoi(argv[2])));
++ cat_ppd(argv[3], atoi(argv[2]));
+ else if (argc == 5 && !strcmp(argv[1], "list"))
+- return (list_ppds(atoi(argv[2]), atoi(argv[3]), argv[4]));
++ list_ppds(atoi(argv[2]), atoi(argv[3]), argv[4]);
+ else
+ {
+ fputs("Usage: cups-driverd cat ppd-name\n", stderr);
+@@ -428,7 +428,7 @@ cat_drv(const char *name, /* I - PPD name */
+ * 'cat_ppd()' - Copy a PPD file to stdout.
+ */
+
+-static int /* O - Exit code */
++static void
+ cat_ppd(const char *name, /* I - PPD name */
+ int request_id) /* I - Request ID for response? */
+ {
+@@ -445,7 +445,7 @@ cat_ppd(const char *name, /* I - PPD name */
+ if (strstr(name, "../"))
+ {
+ fputs("ERROR: Invalid PPD name.\n", stderr);
+- return (1);
++ exit(1);
+ }
+
+ strlcpy(scheme, name, sizeof(scheme));
+@@ -475,11 +475,11 @@ cat_ppd(const char *name, /* I - PPD name */
+ puts("Content-Type: application/ipp\n");
+
+ if (!scheme[0])
+- return (cat_static(name, request_id));
++ exit(cat_static(name, request_id));
+ else if (!strcmp(scheme, "drv"))
+- return (cat_drv(name, request_id));
++ exit(cat_drv(name, request_id));
+ else if (!strcmp(scheme, "file"))
+- return (cat_tar(name, request_id));
++ exit(cat_tar(name, request_id));
+ else
+ {
+ /*
+@@ -517,7 +517,7 @@ cat_ppd(const char *name, /* I - PPD name */
+ cupsdSendIPPTrailer();
+ }
+
+- return (1);
++ exit(1);
+ }
+
+ /*
+@@ -547,15 +547,15 @@ cat_ppd(const char *name, /* I - PPD name */
+
+ fprintf(stderr, "ERROR: [cups-driverd] Unable to execute \"%s\" - %s\n",
+ line, strerror(errno));
+- return (1);
++ exit(1);
+ }
+ }
+
+ /*
+- * Return with no errors...
++ * Exit with no errors...
+ */
+
+- return (0);
++ exit(0);
+ }
+
+
+@@ -778,7 +778,7 @@ compare_ppds(const ppd_info_t *p0, /* I - First PPD file */
+ * 'dump_ppds_dat()' - Dump the contents of the ppds.dat file.
+ */
+
+-static int /* O - Exit status */
++static void
+ dump_ppds_dat(const char *filename) /* I - Filename */
+ {
+ char temp[1024]; /* ppds.dat filename */
+@@ -810,7 +810,7 @@ dump_ppds_dat(const char *filename) /* I - Filename */
+ ppd->record.make_and_model, ppd->record.device_id,
+ ppd->record.scheme);
+
+- return (0);
++ exit(0);
+ }
+
+
+@@ -1004,7 +1004,7 @@ get_file(const char *name, /* I - Name */
+ * 'list_ppds()' - List PPD files.
+ */
+
+-static int /* O - Exit code */
++static void
+ list_ppds(int request_id, /* I - Request ID */
+ int limit, /* I - Limit */
+ const char *opt) /* I - Option argument */
+@@ -1566,7 +1566,7 @@ list_ppds(int request_id, /* I - Request ID */
+ if (request_id)
+ cupsdSendIPPTrailer();
+
+- return (0);
++ exit(0);
+ }
+
+
+--
+2.17.1
+
diff --git a/SOURCES/0001-Fix-stuck-multi-file-jobs-Issue-5359-Issue-5413.patch b/SOURCES/0001-Fix-stuck-multi-file-jobs-Issue-5359-Issue-5413.patch
new file mode 100644
index 0000000..2d7ca02
--- /dev/null
+++ b/SOURCES/0001-Fix-stuck-multi-file-jobs-Issue-5359-Issue-5413.patch
@@ -0,0 +1,56 @@
+diff --git a/backend/socket.c b/backend/socket.c
+index 675061dd9..68379e95b 100644
+--- a/backend/socket.c
++++ b/backend/socket.c
+@@ -397,8 +397,10 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ lseek(print_fd, 0, SEEK_SET);
+ }
+
+- tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addrlist->addr), 1,
+- 0, backendNetworkSideCB);
++ if ((bytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addrlist->addr), 1, 0, backendNetworkSideCB)) < 0)
++ tbytes = -1;
++ else
++ tbytes = bytes;
+
+ if (print_fd != 0 && tbytes >= 0)
+ _cupsLangPrintFilter(stderr, "INFO", _("Print file sent."));
+@@ -406,7 +408,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
+
+ fputs("STATE: +cups-waiting-for-job-completed\n", stderr);
+
+- if (waiteof)
++ if (waiteof && tbytes >= 0)
+ {
+ /*
+ * Shutdown the socket and wait for the other end to finish...
+@@ -443,7 +445,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ if (print_fd != 0)
+ close(print_fd);
+
+- return (CUPS_BACKEND_OK);
++ return (tbytes >= 0 ? CUPS_BACKEND_OK : CUPS_BACKEND_FAILED);
+ }
+
+
+diff --git a/scheduler/main.c b/scheduler/main.c
+index 4b3914ade..472b9946d 100644
+--- a/scheduler/main.c
++++ b/scheduler/main.c
+@@ -1472,9 +1472,16 @@ process_children(void)
+ (!job->filters[i] && WIFEXITED(old_status)))
+ { /* Backend and filter didn't crash */
+ if (job->filters[i])
++ {
+ job->status = status; /* Filter failed */
++ }
+ else
++ {
+ job->status = -status; /* Backend failed */
++
++ if (job->current_file < job->num_files)
++ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_FORCE, "Canceling multi-file job due to backend failure.");
++ }
+ }
+
+ if (job->state_value == IPP_JOB_PROCESSING &&
diff --git a/SOURCES/0001-Log-result-of-httpGetHostname-BEFORE-closing-the-con.patch b/SOURCES/0001-Log-result-of-httpGetHostname-BEFORE-closing-the-con.patch
new file mode 100644
index 0000000..7c647bf
--- /dev/null
+++ b/SOURCES/0001-Log-result-of-httpGetHostname-BEFORE-closing-the-con.patch
@@ -0,0 +1,64 @@
+From ffd290b4ab247f82722927ba9b21358daa16dbf1 Mon Sep 17 00:00:00 2001
+From: Rose <83477269+AtariDreams@users.noreply.github.com>
+Date: Thu, 1 Jun 2023 11:33:39 -0400
+Subject: [PATCH] Log result of httpGetHostname BEFORE closing the connection
+
+httpClose frees the memory of con->http. This is problematic because httpGetHostname then tries to access the memory it points to.
+
+We have to log the hostname first.
+---
+ scheduler/client.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 deletions(-)
+
+diff --git a/scheduler/client.c b/scheduler/client.c
+index 91e441188..327473a4d 100644
+--- a/scheduler/client.c
++++ b/scheduler/client.c
+@@ -193,13 +193,11 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
+ /*
+ * Can't have an unresolved IP address with double-lookups enabled...
+ */
+-
+- httpClose(con->http);
+-
+ cupsdLogClient(con, CUPSD_LOG_WARN,
+- "Name lookup failed - connection from %s closed!",
++ "Name lookup failed - closing connection from %s!",
+ httpGetHostname(con->http, NULL, 0));
+
++ httpClose(con->http);
+ free(con);
+ return;
+ }
+@@ -235,11 +233,11 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
+ * with double-lookups enabled...
+ */
+
+- httpClose(con->http);
+-
+ cupsdLogClient(con, CUPSD_LOG_WARN,
+- "IP lookup failed - connection from %s closed!",
++ "IP lookup failed - closing connection from %s!",
+ httpGetHostname(con->http, NULL, 0));
++
++ httpClose(con->http);
+ free(con);
+ return;
+ }
+@@ -256,11 +254,11 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
+
+ if (!hosts_access(&wrap_req))
+ {
+- httpClose(con->http);
+-
+ cupsdLogClient(con, CUPSD_LOG_WARN,
+ "Connection from %s refused by /etc/hosts.allow and "
+ "/etc/hosts.deny rules.", httpGetHostname(con->http, NULL, 0));
++
++ httpClose(con->http);
+ free(con);
+ return;
+ }
+--
+2.41.0
+
diff --git a/SOURCES/0001-Multiple-security-disclosure-issues.patch b/SOURCES/0001-Multiple-security-disclosure-issues.patch
new file mode 100644
index 0000000..88f81f9
--- /dev/null
+++ b/SOURCES/0001-Multiple-security-disclosure-issues.patch
@@ -0,0 +1,183 @@
+From 2c030c7a06e0c2b8227c7e85f5c58dfb339731d0 Mon Sep 17 00:00:00 2001
+From: Michael R Sweet
+Date: Thu, 15 Aug 2019 14:06:47 -0400
+Subject: [PATCH] Multiple security/disclosure issues:
+
+- CVE-2019-8696 and CVE-2019-8675: Fixed SNMP buffer overflows (rdar://51685251)
+- Fixed IPP buffer overflow (rdar://50035411)
+- Fixed memory disclosure issue in the scheduler (rdar://51373853)
+- Fixed DoS issues in the scheduler (rdar://51373929)
+
+diff --git a/cups/http.c b/cups/http.c
+index 266a15791..fbb1bf13c 100644
+--- a/cups/http.c
++++ b/cups/http.c
+@@ -1860,7 +1860,7 @@ httpPrintf(http_t *http, /* I - HTTP connection */
+ ...) /* I - Additional args as needed */
+ {
+ ssize_t bytes; /* Number of bytes to write */
+- char buf[16384]; /* Buffer for formatted string */
++ char buf[65536]; /* Buffer for formatted string */
+ va_list ap; /* Variable argument pointer */
+
+
+@@ -1872,7 +1872,12 @@ httpPrintf(http_t *http, /* I - HTTP connection */
+
+ DEBUG_printf(("3httpPrintf: (" CUPS_LLFMT " bytes) %s", CUPS_LLCAST bytes, buf));
+
+- if (http->data_encoding == HTTP_ENCODING_FIELDS)
++ if (bytes > (ssize_t)(sizeof(buf) - 1))
++ {
++ http->error = ENOMEM;
++ return (-1);
++ }
++ else if (http->data_encoding == HTTP_ENCODING_FIELDS)
+ return ((int)httpWrite2(http, buf, (size_t)bytes));
+ else
+ {
+diff --git a/cups/ipp.c b/cups/ipp.c
+index 6fae52a00..1bd59cef1 100644
+--- a/cups/ipp.c
++++ b/cups/ipp.c
+@@ -4550,9 +4550,7 @@ ippSetValueTag(
+ break;
+
+ case IPP_TAG_NAME :
+- if (temp_tag != IPP_TAG_KEYWORD && temp_tag != IPP_TAG_URI &&
+- temp_tag != IPP_TAG_URISCHEME && temp_tag != IPP_TAG_LANGUAGE &&
+- temp_tag != IPP_TAG_MIMETYPE)
++ if (temp_tag != IPP_TAG_KEYWORD)
+ return (0);
+
+ (*attr)->value_tag = (ipp_tag_t)(IPP_TAG_NAME | ((*attr)->value_tag & IPP_TAG_CUPS_CONST));
+@@ -4560,10 +4558,7 @@ ippSetValueTag(
+
+ case IPP_TAG_NAMELANG :
+ case IPP_TAG_TEXTLANG :
+- if (value_tag == IPP_TAG_NAMELANG &&
+- (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD &&
+- temp_tag != IPP_TAG_URI && temp_tag != IPP_TAG_URISCHEME &&
+- temp_tag != IPP_TAG_LANGUAGE && temp_tag != IPP_TAG_MIMETYPE))
++ if (value_tag == IPP_TAG_NAMELANG && (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD))
+ return (0);
+
+ if (value_tag == IPP_TAG_TEXTLANG && temp_tag != IPP_TAG_TEXT)
+diff --git a/cups/snmp.c b/cups/snmp.c
+index 5cefee454..1d9da01f2 100644
+--- a/cups/snmp.c
++++ b/cups/snmp.c
+@@ -1233,6 +1233,9 @@ asn1_get_integer(
+ int value; /* Integer value */
+
+
++ if (*buffer >= bufend)
++ return (0);
++
+ if (length > sizeof(int))
+ {
+ (*buffer) += length;
+@@ -1259,6 +1262,9 @@ asn1_get_length(unsigned char **buffer, /* IO - Pointer in buffer */
+ unsigned length; /* Length */
+
+
++ if (*buffer >= bufend)
++ return (0);
++
+ length = **buffer;
+ (*buffer) ++;
+
+@@ -1301,6 +1307,9 @@ asn1_get_oid(
+ int number; /* OID number */
+
+
++ if (*buffer >= bufend)
++ return (0);
++
+ valend = *buffer + length;
+ oidptr = oid;
+ oidend = oid + oidsize - 1;
+@@ -1349,9 +1358,12 @@ asn1_get_packed(
+ int value; /* Value */
+
+
++ if (*buffer >= bufend)
++ return (0);
++
+ value = 0;
+
+- while ((**buffer & 128) && *buffer < bufend)
++ while (*buffer < bufend && (**buffer & 128))
+ {
+ value = (value << 7) | (**buffer & 127);
+ (*buffer) ++;
+@@ -1379,6 +1391,9 @@ asn1_get_string(
+ char *string, /* I - String buffer */
+ size_t strsize) /* I - String buffer size */
+ {
++ if (*buffer >= bufend)
++ return (NULL);
++
+ if (length > (unsigned)(bufend - *buffer))
+ length = (unsigned)(bufend - *buffer);
+
+@@ -1421,6 +1436,9 @@ asn1_get_type(unsigned char **buffer, /* IO - Pointer in buffer */
+ int type; /* Type */
+
+
++ if (*buffer >= bufend)
++ return (0);
++
+ type = **buffer;
+ (*buffer) ++;
+
+diff --git a/scheduler/client.c b/scheduler/client.c
+index 923a6e67a..f693e7c49 100644
+--- a/scheduler/client.c
++++ b/scheduler/client.c
+@@ -564,6 +564,17 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
+
+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cupsdReadClient: error=%d, used=%d, state=%s, data_encoding=HTTP_ENCODING_%s, data_remaining=" CUPS_LLFMT ", request=%p(%s), file=%d", httpError(con->http), (int)httpGetReady(con->http), httpStateString(httpGetState(con->http)), httpIsChunked(con->http) ? "CHUNKED" : "LENGTH", CUPS_LLCAST httpGetRemaining(con->http), con->request, con->request ? ippStateString(ippGetState(con->request)) : "", con->file);
+
++ if (httpError(con->http) == EPIPE && !httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1)
++ {
++ /*
++ * Connection closed...
++ */
++
++ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF.");
++ cupsdCloseClient(con);
++ return;
++ }
++
+ if (httpGetState(con->http) == HTTP_STATE_GET_SEND ||
+ httpGetState(con->http) == HTTP_STATE_POST_SEND ||
+ httpGetState(con->http) == HTTP_STATE_STATUS)
+@@ -573,17 +584,6 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
+ * connection and we need to shut it down...
+ */
+
+- if (!httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1)
+- {
+- /*
+- * Connection closed...
+- */
+-
+- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF.");
+- cupsdCloseClient(con);
+- return;
+- }
+-
+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on unexpected HTTP read state %s.", httpStateString(httpGetState(con->http)));
+ cupsdCloseClient(con);
+ return;
+@@ -1950,6 +1950,7 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */
+ strlcpy(location, httpGetField(con->http, HTTP_FIELD_LOCATION), sizeof(location));
+
+ httpClearFields(con->http);
++ httpClearCookie(con->http);
+
+ httpSetField(con->http, HTTP_FIELD_LOCATION, location);
+
+--
+2.21.0
+
diff --git a/SOURCES/0001-Printing-to-old-CUPS-servers-has-been-fixed-Issue-52.patch b/SOURCES/0001-Printing-to-old-CUPS-servers-has-been-fixed-Issue-52.patch
new file mode 100644
index 0000000..de7ef28
--- /dev/null
+++ b/SOURCES/0001-Printing-to-old-CUPS-servers-has-been-fixed-Issue-52.patch
@@ -0,0 +1,562 @@
+diff --git a/cups/cups-private.h b/cups/cups-private.h
+index 6fd66a9..1f66fd7 100644
+--- a/cups/cups-private.h
++++ b/cups/cups-private.h
+@@ -237,13 +237,9 @@ extern void _cupsBufferRelease(char *b);
+
+ extern http_t *_cupsConnect(void);
+ extern char *_cupsCreateDest(const char *name, const char *info, const char *device_id, const char *device_uri, char *uri, size_t urisize);
+-extern int _cupsGet1284Values(const char *device_id,
+- cups_option_t **values);
+-extern const char *_cupsGetDestResource(cups_dest_t *dest, char *resource,
+- size_t resourcesize);
+-extern int _cupsGetDests(http_t *http, ipp_op_t op,
+- const char *name, cups_dest_t **dests,
+- cups_ptype_t type, cups_ptype_t mask);
++extern int _cupsGet1284Values(const char *device_id, cups_option_t **values);
++extern const char *_cupsGetDestResource(cups_dest_t *dest, unsigned flags, char *resource, size_t resourcesize);
++extern int _cupsGetDests(http_t *http, ipp_op_t op, const char *name, cups_dest_t **dests, cups_ptype_t type, cups_ptype_t mask);
+ extern const char *_cupsGetPassword(const char *prompt);
+ extern void _cupsGlobalLock(void);
+ extern _cups_globals_t *_cupsGlobals(void);
+@@ -253,13 +249,10 @@ extern const char *_cupsGSSServiceName(void);
+ # endif /* HAVE_GSSAPI */
+ extern int _cupsNextDelay(int current, int *previous);
+ extern void _cupsSetDefaults(void);
+-extern void _cupsSetError(ipp_status_t status, const char *message,
+- int localize);
++extern void _cupsSetError(ipp_status_t status, const char *message, int localize);
+ extern void _cupsSetHTTPError(http_status_t status);
+ # ifdef HAVE_GSSAPI
+-extern int _cupsSetNegotiateAuthString(http_t *http,
+- const char *method,
+- const char *resource);
++extern int _cupsSetNegotiateAuthString(http_t *http, const char *method, const char *resource);
+ # endif /* HAVE_GSSAPI */
+ extern char *_cupsUserDefault(char *name, size_t namesize);
+
+diff --git a/cups/dest-options.c b/cups/dest-options.c
+index 51705a5..cfa28ce 100644
+--- a/cups/dest-options.c
++++ b/cups/dest-options.c
+@@ -572,6 +572,7 @@ cupsCopyDestInfo(
+ cups_dest_t *dest) /* I - Destination */
+ {
+ cups_dinfo_t *dinfo; /* Destination information */
++ unsigned dflags; /* Destination flags */
+ ipp_t *request, /* Get-Printer-Attributes request */
+ *response; /* Supported attributes */
+ int tries, /* Number of tries so far */
+@@ -581,6 +582,7 @@ cupsCopyDestInfo(
+ char resource[1024]; /* Resource path */
+ int version; /* IPP version */
+ ipp_status_t status; /* Status of request */
++ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
+ static const char * const requested_attrs[] =
+ { /* Requested attributes */
+ "job-template",
+@@ -589,14 +591,25 @@ cupsCopyDestInfo(
+ };
+
+
+- DEBUG_printf(("cupsCopyDestSupported(http=%p, dest=%p(%s))", (void *)http, (void *)dest, dest ? dest->name : ""));
++ DEBUG_printf(("cupsCopyDestInfo(http=%p, dest=%p(%s))", (void *)http, (void *)dest, dest ? dest->name : ""));
+
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+- http = _cupsConnect();
++ {
++ http = _cupsConnect();
++ dflags = CUPS_DEST_FLAGS_NONE;
++ }
++#ifdef AF_LOCAL
++ else if (strcmp(http->hostname, cg->server) || (httpAddrFamily(http->hostaddr) != AF_LOCAL && cg->ipp_port != httpAddrPort(http->hostaddr)))
++#else
++ else if (strcmp(http->hostname, cg->server) || cg->ipp_port != httpAddrPort(http->hostaddr))
++#endif /* AF_LOCAL */
++ dflags = CUPS_DEST_FLAGS_DEVICE;
++ else
++ dflags = CUPS_DEST_FLAGS_NONE;
+
+ /*
+ * Range check input...
+@@ -609,8 +622,11 @@ cupsCopyDestInfo(
+ * Get the printer URI and resource path...
+ */
+
+- if ((uri = _cupsGetDestResource(dest, resource, sizeof(resource))) == NULL)
++ if ((uri = _cupsGetDestResource(dest, dflags, resource, sizeof(resource))) == NULL)
++ {
++ DEBUG_puts("1cupsCopyDestInfo: Unable to get resource.");
+ return (NULL);
++ }
+
+ /*
+ * Get the supported attributes...
+@@ -628,28 +644,25 @@ cupsCopyDestInfo(
+ */
+
+ request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+- uri);
+- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+- "requesting-user-name", NULL, cupsUser());
+- ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+- "requested-attributes",
+- (int)(sizeof(requested_attrs) / sizeof(requested_attrs[0])),
+- NULL, requested_attrs);
++
++ ippSetVersion(request, version / 10, version % 10);
++ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
++ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
++ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(requested_attrs) / sizeof(requested_attrs[0])), NULL, requested_attrs);
+ response = cupsDoRequest(http, request, resource);
+ status = cupsLastError();
+
+ if (status > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
+ {
+- DEBUG_printf(("cupsCopyDestSupported: Get-Printer-Attributes for '%s' "
+- "returned %s (%s)", dest->name, ippErrorString(status),
+- cupsLastErrorString()));
++ DEBUG_printf(("1cupsCopyDestInfo: Get-Printer-Attributes for '%s' returned %s (%s)", dest->name, ippErrorString(status), cupsLastErrorString()));
+
+ ippDelete(response);
+ response = NULL;
+
+- if (status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED && version > 11)
++ if ((status == IPP_STATUS_ERROR_BAD_REQUEST || status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) && version > 11)
++ {
+ version = 11;
++ }
+ else if (status == IPP_STATUS_ERROR_BUSY)
+ {
+ sleep((unsigned)delay);
+@@ -665,7 +678,10 @@ cupsCopyDestInfo(
+ while (!response && tries < 10);
+
+ if (!response)
++ {
++ DEBUG_puts("1cupsCopyDestInfo: Unable to get printer attributes.");
+ return (NULL);
++ }
+
+ /*
+ * Allocate a cups_dinfo_t structure and return it...
+@@ -678,6 +694,8 @@ cupsCopyDestInfo(
+ return (NULL);
+ }
+
++ DEBUG_printf(("1cupsCopyDestInfo: version=%d, uri=\"%s\", resource=\"%s\".", version, uri, resource));
++
+ dinfo->version = version;
+ dinfo->uri = uri;
+ dinfo->resource = _cupsStrAlloc(resource);
+diff --git a/cups/dest.c b/cups/dest.c
+index 57a8dc9..3537572 100644
+--- a/cups/dest.c
++++ b/cups/dest.c
+@@ -1103,13 +1103,16 @@ cupsGetDest(const char *name, /* I - Destination name or @code NULL@ for the d
+ * '_cupsGetDestResource()' - Get the resource path and URI for a destination.
+ */
+
+-const char * /* O - Printer URI */
++const char * /* O - URI */
+ _cupsGetDestResource(
+ cups_dest_t *dest, /* I - Destination */
++ unsigned flags, /* I - Destination flags */
+ char *resource, /* I - Resource buffer */
+ size_t resourcesize) /* I - Size of resource buffer */
+ {
+- const char *uri; /* Printer URI */
++ const char *uri, /* URI */
++ *device_uri, /* Device URI */
++ *printer_uri; /* Printer URI */
+ char scheme[32], /* URI scheme */
+ userpass[256], /* Username and password (unused) */
+ hostname[256]; /* Hostname */
+@@ -1132,25 +1135,46 @@ _cupsGetDestResource(
+ }
+
+ /*
+- * Grab the printer URI...
++ * Grab the printer and device URIs...
+ */
+
+- if ((uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options)) == NULL)
++ device_uri = cupsGetOption("device-uri", dest->num_options, dest->options);
++ printer_uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options);
++
++ DEBUG_printf(("1_cupsGetDestResource: device-uri=\"%s\", printer-uri-supported=\"%s\".", device_uri, printer_uri));
++
++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
++ if (((flags & CUPS_DEST_FLAGS_DEVICE) || !printer_uri) && strstr(device_uri, "._tcp"))
+ {
+- if ((uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL)
++ if ((device_uri = cups_dnssd_resolve(dest, device_uri, 5000, NULL, NULL, NULL)) != NULL)
+ {
+-#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+- if (strstr(uri, "._tcp"))
+- uri = cups_dnssd_resolve(dest, uri, 5000, NULL, NULL, NULL);
+-#endif /* HAVE_DNSSD || HAVE_AVAHI */
++ DEBUG_printf(("1_cupsGetDestResource: Resolved device-uri=\"%s\".", device_uri));
+ }
+-
+- if (uri)
++ else
+ {
+- DEBUG_printf(("1_cupsGetDestResource: Resolved printer-uri-supported=\"%s\"", uri));
++ DEBUG_puts("1_cupsGetDestResource: Unable to resolve device.");
+
+- uri = _cupsCreateDest(dest->name, cupsGetOption("printer-info", dest->num_options, dest->options), NULL, uri, resource, resourcesize);
++ if (resource)
++ *resource = '\0';
++
++ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0);
++
++ return (NULL);
+ }
++ }
++#endif /* HAVE_DNSSD || HAVE_AVAHI */
++
++ if (flags & CUPS_DEST_FLAGS_DEVICE)
++ {
++ uri = device_uri;
++ }
++ else if (printer_uri)
++ {
++ uri = printer_uri;
++ }
++ else
++ {
++ uri = _cupsCreateDest(dest->name, cupsGetOption("printer-info", dest->num_options, dest->options), NULL, device_uri, resource, resourcesize);
+
+ if (uri)
+ {
+@@ -1160,30 +1184,24 @@ _cupsGetDestResource(
+
+ uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options);
+ }
+- else
+- {
+- DEBUG_puts("1_cupsGetDestResource: No printer-uri-supported found.");
++ }
+
+- if (resource)
+- *resource = '\0';
++ if (!uri)
++ {
++ DEBUG_puts("1_cupsGetDestResource: No printer-uri-supported or device-uri found.");
+
+- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0);
++ if (resource)
++ *resource = '\0';
+
+- return (NULL);
+- }
++ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0);
++
++ return (NULL);
+ }
+- else
++ else if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, (int)resourcesize) < HTTP_URI_STATUS_OK)
+ {
+- DEBUG_printf(("1_cupsGetDestResource: printer-uri-supported=\"%s\"", uri));
++ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad URI."), 1);
+
+- if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme),
+- userpass, sizeof(userpass), hostname, sizeof(hostname),
+- &port, resource, (int)resourcesize) < HTTP_URI_STATUS_OK)
+- {
+- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad printer-uri."), 1);
+-
+- return (NULL);
+- }
++ return (NULL);
+ }
+
+ DEBUG_printf(("1_cupsGetDestResource: resource=\"%s\"", resource));
+diff --git a/cups/testdest.c b/cups/testdest.c
+index c5c2052..27060f6 100644
+--- a/cups/testdest.c
++++ b/cups/testdest.c
+@@ -43,9 +43,12 @@ int /* O - Exit status */
+ main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+ {
++ int i; /* Looping var */
+ http_t *http; /* Connection to destination */
+ cups_dest_t *dest = NULL; /* Destination */
+ cups_dinfo_t *dinfo; /* Destination info */
++ unsigned dflags = CUPS_DEST_FLAGS_NONE;
++ /* Destination flags */
+
+
+ if (argc < 2)
+@@ -103,9 +106,17 @@ main(int argc, /* I - Number of command-line arguments */
+
+ return (0);
+ }
+- else if (!strncmp(argv[1], "ipp://", 6) || !strncmp(argv[1], "ipps://", 7))
+- dest = cupsGetDestWithURI(NULL, argv[1]);
+- else if (!strcmp(argv[1], "default"))
++
++ i = 1;
++ if (!strcmp(argv[i], "--device"))
++ {
++ dflags = CUPS_DEST_FLAGS_DEVICE;
++ i ++;
++ }
++
++ if (!strncmp(argv[i], "ipp://", 6) || !strncmp(argv[i], "ipps://", 7))
++ dest = cupsGetDestWithURI(NULL, argv[i]);
++ else if (!strcmp(argv[i], "default"))
+ {
+ dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL);
+ if (dest && dest->instance)
+@@ -114,67 +125,70 @@ main(int argc, /* I - Number of command-line arguments */
+ printf("default is \"%s\".\n", dest->name);
+ }
+ else
+- dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, argv[1], NULL);
++ dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, argv[i], NULL);
+
+ if (!dest)
+ {
+- printf("testdest: Unable to get destination \"%s\": %s\n", argv[1], cupsLastErrorString());
++ printf("testdest: Unable to get destination \"%s\": %s\n", argv[i], cupsLastErrorString());
+ return (1);
+ }
+
+- if ((http = cupsConnectDest(dest, CUPS_DEST_FLAGS_NONE, 30000, NULL, NULL, 0, NULL, NULL)) == NULL)
++ i ++;
++
++ if ((http = cupsConnectDest(dest, dflags, 30000, NULL, NULL, 0, NULL, NULL)) == NULL)
+ {
+- printf("testdest: Unable to connect to destination \"%s\": %s\n", argv[1], cupsLastErrorString());
++ printf("testdest: Unable to connect to destination \"%s\": %s\n", dest->name, cupsLastErrorString());
+ return (1);
+ }
+
+ if ((dinfo = cupsCopyDestInfo(http, dest)) == NULL)
+ {
+- printf("testdest: Unable to get information for destination \"%s\": %s\n", argv[1], cupsLastErrorString());
++ printf("testdest: Unable to get information for destination \"%s\": %s\n", dest->name, cupsLastErrorString());
+ return (1);
+ }
+
+- if (argc == 2 || (!strcmp(argv[2], "supported") && argc < 6))
++ if (i == argc || !strcmp(argv[i], "supported"))
+ {
+- if (argc > 3)
+- show_supported(http, dest, dinfo, argv[3], argv[4]);
++ i ++;
++
++ if ((i + 1) < argc)
++ show_supported(http, dest, dinfo, argv[i], argv[i + 1]);
+ else if (argc > 2)
+- show_supported(http, dest, dinfo, argv[3], NULL);
++ show_supported(http, dest, dinfo, argv[i], NULL);
+ else
+ show_supported(http, dest, dinfo, NULL, NULL);
+ }
+- else if (!strcmp(argv[2], "conflicts") && argc > 3)
++ else if (!strcmp(argv[i], "conflicts") && (i + 1) < argc)
+ {
+- int i, /* Looping var */
+- num_options = 0;/* Number of options */
++ int num_options = 0;/* Number of options */
+ cups_option_t *options = NULL;/* Options */
+
+- for (i = 3; i < argc; i ++)
++ for (i ++; i < argc; i ++)
+ num_options = cupsParseOptions(argv[i], num_options, &options);
+
+ show_conflicts(http, dest, dinfo, num_options, options);
+ }
+- else if (!strcmp(argv[2], "default") && argc == 4)
++ else if (!strcmp(argv[i], "default") && (i + 1) < argc)
+ {
+- show_default(http, dest, dinfo, argv[3]);
++ show_default(http, dest, dinfo, argv[i + 1]);
+ }
+- else if (!strcmp(argv[2], "localize") && argc < 6)
++ else if (!strcmp(argv[i], "localize"))
+ {
+- if (argc > 3)
+- localize(http, dest, dinfo, argv[3], argv[4]);
++ i ++;
++ if ((i + 1) < argc)
++ localize(http, dest, dinfo, argv[i], argv[i + 1]);
+ else if (argc > 2)
+- localize(http, dest, dinfo, argv[3], NULL);
++ localize(http, dest, dinfo, argv[i], NULL);
+ else
+ localize(http, dest, dinfo, NULL, NULL);
+ }
+- else if (!strcmp(argv[2], "media"))
++ else if (!strcmp(argv[i], "media"))
+ {
+- int i; /* Looping var */
+ const char *name = NULL; /* Media name, if any */
+ unsigned flags = CUPS_MEDIA_FLAGS_DEFAULT;
+ /* Media selection flags */
+
+- for (i = 3; i < argc; i ++)
++ for (i ++; i < argc; i ++)
+ {
+ if (!strcmp(argv[i], "borderless"))
+ flags = CUPS_MEDIA_FLAGS_BORDERLESS;
+@@ -192,19 +206,19 @@ main(int argc, /* I - Number of command-line arguments */
+
+ show_media(http, dest, dinfo, flags, name);
+ }
+- else if (!strcmp(argv[2], "print") && argc > 3)
++ else if (!strcmp(argv[i], "print") && (i + 1) < argc)
+ {
+- int i, /* Looping var */
+- num_options = 0;/* Number of options */
++ int num_options = 0;/* Number of options */
+ cups_option_t *options = NULL;/* Options */
++ const char *filename = argv[i + 1];
+
+- for (i = 4; i < argc; i ++)
++ for (i += 2; i < argc; i ++)
+ num_options = cupsParseOptions(argv[i], num_options, &options);
+
+- print_file(http, dest, dinfo, argv[3], num_options, options);
++ print_file(http, dest, dinfo, filename, num_options, options);
+ }
+ else
+- usage(argv[2]);
++ usage(argv[i]);
+
+ return (0);
+ }
+@@ -740,9 +754,9 @@ usage(const char *arg) /* I - Argument for usage message */
+ printf("testdest: Unknown option \"%s\".\n", arg);
+
+ puts("Usage:");
+- puts(" ./testdest name [operation ...]");
+- puts(" ./testdest ipp://... [operation ...]");
+- puts(" ./testdest ipps://... [operation ...]");
++ puts(" ./testdest [--device] name [operation ...]");
++ puts(" ./testdest [--device] ipp://... [operation ...]");
++ puts(" ./testdest [--device] ipps://... [operation ...]");
+ puts(" ./testdest --enum [grayscale] [color] [duplex] [staple] [small]\n"
+ " [medium] [large]");
+ puts("");
+diff --git a/test/ippserver.c b/test/ippserver.c
+index 38b304f..c593d3a 100644
+--- a/test/ippserver.c
++++ b/test/ippserver.c
+@@ -461,6 +461,7 @@ static AvahiClient *DNSSDClient = NULL;
+ #endif /* HAVE_DNSSD */
+
+ static int KeepFiles = 0,
++ MaxVersion = 20,
+ Verbosity = 0;
+
+
+@@ -533,6 +534,23 @@ main(int argc, /* I - Number of command-line args */
+ pin = 1;
+ break;
+
++ case 'V' : /* -V max-version */
++ i ++;
++ if (i >= argc)
++ usage(1);
++
++ if (!strcmp(argv[i], "2.2"))
++ MaxVersion = 22;
++ else if (!strcmp(argv[i], "2.1"))
++ MaxVersion = 21;
++ else if (!strcmp(argv[i], "2.0"))
++ MaxVersion = 20;
++ else if (!strcmp(argv[i], "1.1"))
++ MaxVersion = 11;
++ else
++ usage(1);
++ break;
++
+ case 'a' : /* -a attributes-file */
+ i ++;
+ if (i >= argc)
+@@ -1324,9 +1342,10 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default)
+ };
+ static const char * const versions[] =/* ipp-versions-supported values */
+ {
+- "1.0",
+ "1.1",
+- "2.0"
++ "2.0",
++ "2.1",
++ "2.2"
+ };
+ static const char * const features[] =/* ipp-features-supported values */
+ {
+@@ -1738,7 +1757,12 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default)
+
+ /* ipp-versions-supported */
+ if (!ippFindAttribute(printer->attrs, "ipp-versions-supported", IPP_TAG_ZERO))
+- ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]), NULL, versions);
++ {
++ int num_versions = MaxVersion == 11 ? 1 : MaxVersion == 20 ? 2 : MaxVersion == 21 ? 3 : 4;
++ /* Number of supported versions */
++
++ ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-versions-supported", num_versions, NULL, versions);
++ }
+
+ /* job-account-id-default */
+ if (!ippFindAttribute(printer->attrs, "job-account-id-default", IPP_TAG_ZERO))
+@@ -5800,15 +5824,24 @@ process_ipp(_ipp_client_t *client) /* I - Client */
+ * Return an error, since we only support IPP 1.x and 2.x.
+ */
+
+- respond_ipp(client, IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED,
+- "Bad request version number %d.%d.", major, minor);
++ respond_ipp(client, IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED, "Bad request version number %d.%d.", major, minor);
++ }
++ else if ((major * 10 + minor) > MaxVersion)
++ {
++ if (httpGetState(client->http) != HTTP_STATE_POST_SEND)
++ httpFlush(client->http); /* Flush trailing (junk) data */
++
++ respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0);
++ return (0);
+ }
+ else if (ippGetRequestId(client->request) <= 0)
+- respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad request-id %d.",
+- ippGetRequestId(client->request));
++ {
++ respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad request-id %d.", ippGetRequestId(client->request));
++ }
+ else if (!ippFirstAttribute(client->request))
+- respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST,
+- "No attributes in request.");
++ {
++ respond_ipp(client, IPP_STATUS_ERROR_BAD_REQUEST, "No attributes in request.");
++ }
+ else
+ {
+ /*
+@@ -6877,8 +6910,7 @@ usage(int status) /* O - Exit status */
+ {
+ if (!status)
+ {
+- puts(CUPS_SVERSION " - Copyright 2010-2015 by Apple Inc. All rights "
+- "reserved.");
++ puts(CUPS_SVERSION " - Copyright (c) 2010-2018 by Apple Inc. All rights reserved.");
+ puts("");
+ }
+
+@@ -6888,6 +6920,7 @@ usage(int status) /* O - Exit status */
+ puts("-2 Supports 2-sided printing (default=1-sided)");
+ puts("-M manufacturer Manufacturer name (default=Test)");
+ puts("-P PIN printing mode");
++ puts("-V max-version Set maximum supported IPP version");
+ puts("-a attributes-file Load printer attributes from file");
+ puts("-c command Run command for every print job");
+ printf("-d spool-directory Spool directory "
diff --git a/SOURCES/0001-Remove-web-log-buttons.patch b/SOURCES/0001-Remove-web-log-buttons.patch
new file mode 100644
index 0000000..a19d806
--- /dev/null
+++ b/SOURCES/0001-Remove-web-log-buttons.patch
@@ -0,0 +1,98 @@
+diff --git a/templates/admin.tmpl b/templates/admin.tmpl
+index 101f960..5ebd813 100644
+--- a/templates/admin.tmpl
++++ b/templates/admin.tmpl
+@@ -27,9 +27,6 @@
+
+
+
+-
+-
+-
+
+
+ {SETTINGS_ERROR?{SETTINGS_MESSAGE}
+diff --git a/templates/de/admin.tmpl b/templates/de/admin.tmpl
+index fb2851a..f8ddeff 100644
+--- a/templates/de/admin.tmpl
++++ b/templates/de/admin.tmpl
+@@ -27,9 +27,6 @@
+
+
+
+-
+-
+-
+
+
+ {SETTINGS_ERROR?{SETTINGS_MESSAGE}
+diff --git a/templates/es/admin.tmpl b/templates/es/admin.tmpl
+index 097c65c..b83b1a0 100644
+--- a/templates/es/admin.tmpl
++++ b/templates/es/admin.tmpl
+@@ -27,9 +27,6 @@
+
+
+
+-
+-
+-
+
+
+ {SETTINGS_ERROR?{SETTINGS_MESSAGE}
+diff --git a/templates/fr/admin.tmpl b/templates/fr/admin.tmpl
+index 2fcd9c5..e365ff3 100644
+--- a/templates/fr/admin.tmpl
++++ b/templates/fr/admin.tmpl
+@@ -27,9 +27,6 @@
+
+
+
+-
+-
+-
+
+
+ {SETTINGS_ERROR?{SETTINGS_MESSAGE}
+diff --git a/templates/ja/admin.tmpl b/templates/ja/admin.tmpl
+index 13d6f13..f5fa750 100644
+--- a/templates/ja/admin.tmpl
++++ b/templates/ja/admin.tmpl
+@@ -27,9 +27,6 @@
+
+
+
+-
+-
+-
+
+
+ {SETTINGS_ERROR?{SETTINGS_MESSAGE}
+diff --git a/templates/pt_BR/admin.tmpl b/templates/pt_BR/admin.tmpl
+index b847bef..e11d889 100644
+--- a/templates/pt_BR/admin.tmpl
++++ b/templates/pt_BR/admin.tmpl
+@@ -27,9 +27,6 @@
+
+
+
+-
+-
+-
+
+
+ {SETTINGS_ERROR?{SETTINGS_MESSAGE}
+diff --git a/templates/ru/admin.tmpl b/templates/ru/admin.tmpl
+index 49a168c..44b1493 100644
+--- a/templates/ru/admin.tmpl
++++ b/templates/ru/admin.tmpl
+@@ -26,9 +26,6 @@
+
+
+
+-
+-
+-
+
+
+ {SETTINGS_ERROR?{SETTINGS_MESSAGE}
diff --git a/SOURCES/0001-Require-authentication-for-CUPS-Get-Document.patch b/SOURCES/0001-Require-authentication-for-CUPS-Get-Document.patch
new file mode 100644
index 0000000..e2852e1
--- /dev/null
+++ b/SOURCES/0001-Require-authentication-for-CUPS-Get-Document.patch
@@ -0,0 +1,31 @@
+From a0c8b9c9556882f00c68b9727a95a1b6d1452913 Mon Sep 17 00:00:00 2001
+From: Michael R Sweet
+Date: Tue, 6 Dec 2022 09:04:01 -0500
+Subject: [PATCH] Require authentication for CUPS-Get-Document.
+
+---
+ conf/cupsd.conf.in | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/conf/cupsd.conf.in b/conf/cupsd.conf.in
+index b25884907..a07536f3e 100644
+--- a/conf/cupsd.conf.in
++++ b/conf/cupsd.conf.in
+@@ -68,7 +68,13 @@ IdleExitTimeout @EXIT_TIMEOUT@
+ Order deny,allow
+
+
+-
++
++ Require user @OWNER @SYSTEM
++ Order deny,allow
++
++
++
++ AuthType Default
+ Require user @OWNER @SYSTEM
+ Order deny,allow
+
+--
+2.41.0
+
diff --git a/SOURCES/0001-The-scheduler-could-crash-while-adding-an-IPP-Everyw.patch b/SOURCES/0001-The-scheduler-could-crash-while-adding-an-IPP-Everyw.patch
new file mode 100644
index 0000000..e5b9e9e
--- /dev/null
+++ b/SOURCES/0001-The-scheduler-could-crash-while-adding-an-IPP-Everyw.patch
@@ -0,0 +1,22 @@
+diff --git a/scheduler/ipp.c b/scheduler/ipp.c
+index 649995bb5..2396c9b58 100644
+--- a/scheduler/ipp.c
++++ b/scheduler/ipp.c
+@@ -4873,6 +4873,8 @@ copy_printer_attrs(
+ * and document-format attributes that may be provided by the client.
+ */
+
++ _cupsRWLockRead(&printer->lock);
++
+ curtime = time(NULL);
+
+ if (!ra || cupsArrayFind(ra, "marker-change-time"))
+@@ -5034,6 +5036,8 @@ copy_printer_attrs(
+ if (printer->ppd_attrs)
+ copy_attrs(con->response, printer->ppd_attrs, ra, IPP_TAG_ZERO, 0, NULL);
+ copy_attrs(con->response, CommonData, ra, IPP_TAG_ZERO, IPP_TAG_COPY, NULL);
++
++ _cupsRWUnlock(&printer->lock);
+ }
+
+
diff --git a/SOURCES/0001-Update-man-pages-for-h-option-Issue-357.patch b/SOURCES/0001-Update-man-pages-for-h-option-Issue-357.patch
new file mode 100644
index 0000000..c6ec7e5
--- /dev/null
+++ b/SOURCES/0001-Update-man-pages-for-h-option-Issue-357.patch
@@ -0,0 +1,899 @@
+From 4d6787bd98c2fac8dcc58f34125d299d82e622aa Mon Sep 17 00:00:00 2001
+From: Michael R Sweet
+Date: Mon, 2 May 2022 15:35:20 -0400
+Subject: [PATCH] Update man pages for -h option (Issue #357)
+
+---
+ CHANGES.md | 1 +
+ doc/help/man-cancel.html | 7 ++++---
+ doc/help/man-cupsctl.html | 7 ++++---
+ doc/help/man-ipptool.html | 6 ++++++
+ doc/help/man-lp.html | 9 +++++----
+ doc/help/man-lpinfo.html | 9 +++++----
+ doc/help/man-lpmove.html | 9 +++++----
+ doc/help/man-lpoptions.html | 17 +++++++++--------
+ doc/help/man-lpq.html | 5 +++--
+ doc/help/man-lpr.html | 5 +++--
+ doc/help/man-lprm.html | 6 +++---
+ doc/help/man-lpstat.html | 5 +++--
+ man/cancel.1 | 9 +++++----
+ man/cupsctl.8 | 9 +++++----
+ man/lp.1 | 11 ++++++-----
+ man/lpinfo.8 | 11 ++++++-----
+ man/lpmove.8 | 11 ++++++-----
+ man/lpoptions.1 | 19 ++++++++++---------
+ man/lpq.1 | 7 ++++---
+ man/lpr.1 | 7 ++++---
+ man/lprm.1 | 8 ++++----
+ man/lpstat.1 | 11 ++++++-----
+ 22 files changed, 107 insertions(+), 82 deletions(-)
+
+diff --git a/doc/help/man-cancel.html b/doc/help/man-cancel.html
+index d51bb2b91..a0b52369c 100644
+--- a/doc/help/man-cancel.html
++++ b/doc/help/man-cancel.html
+@@ -12,6 +12,9 @@ cancel - cancel jobs
+
+ cancel
+ [
++-h
++hostname[:port]
++] [
+ -E
+ ] [
+ -U
+@@ -19,9 +22,6 @@ cancel - cancel jobs
+ ] [
+ -a
+ ] [
+--h
+-hostname[:port]
+-] [
+ -u
+ username
+ ] [
+@@ -46,6 +46,7 @@ destinations if none is provided.
+ Forces encryption when connecting to the server.
+ -h hostname[:port]
+ Specifies an alternate server.
++Note: This option must occur before all others.
+ -U username
+ Specifies the username to use when connecting to the server.
+ -u username
+diff --git a/doc/help/man-cupsctl.html b/doc/help/man-cupsctl.html
+index b3f892ef9..e5c98dccb 100644
+--- a/doc/help/man-cupsctl.html
++++ b/doc/help/man-cupsctl.html
+@@ -12,14 +12,14 @@ cupsctl - configure cupsd.conf options
+
+ cupsctl
+ [
++-h
++server[:port]
++] [
+ -E
+ ] [
+ -U
+ username
+ ] [
+--h
+-server[:port]
+-] [
+ --[no-]debug-logging
+ ] [
+ --[no-]remote-admin
+@@ -45,6 +45,7 @@ The following options are recognized:
+ Specifies an alternate username to use when authenticating with the scheduler.
+ -h server[:port]
+ Specifies the server address.
++Note: This option must occur before all others.
+ --[no-]debug-logging
+ Enables (disables) debug logging to the error_log file.
+ --[no-]remote-admin
+diff --git a/doc/help/man-ipptool.html b/doc/help/man-ipptool.html
+index 81f67d77f..688454c69 100644
+--- a/doc/help/man-ipptool.html
++++ b/doc/help/man-ipptool.html
+@@ -59,6 +59,8 @@ ipptool - perform internet printing protocol requests
+ -i
+ seconds
+ ] [
++-j
++] [
+ -n
+ repeat-count
+ ] [
+@@ -150,6 +152,10 @@ This option is incompatible with the -i (interval) and -n (repeat-
+ testfile
+ should be repeated at the specified interval.
+ This option is incompatible with the -X (XML plist output) option.
++-j
++Specifies that
++ipptool
++will produce JSON output.
+ -l
+ Specifies that plain text output is desired.
+ -n repeat-count
+diff --git a/doc/help/man-lp.html b/doc/help/man-lp.html
+index f70c088d3..6442e900d 100644
+--- a/doc/help/man-lp.html
++++ b/doc/help/man-lp.html
+@@ -12,6 +12,8 @@ lp - print files
+
+ lp
+ [
++-h hostname[:port]
++] [
+ -E
+ ] [
+ -U
+@@ -21,8 +23,6 @@ lp - print files
+ ] [
+ -d destination[/instance]
+ ] [
+--h hostname[:port]
+-] [
+ -m
+ ] [
+ -n
+@@ -51,6 +51,8 @@ lp - print files
+
+ lp
+ [
++-h hostname[:port]
++] [
+ -E
+ ] [
+ -U
+@@ -58,8 +60,6 @@ lp - print files
+ ] [
+ -c
+ ] [
+--h hostname[:port]
+-] [
+ -i
+ job-id
+ ] [
+@@ -106,6 +106,7 @@ In CUPS, print files are always sent to the scheduler via IPP which has the same
+ Prints files to the named printer.
+ -h hostname[:port]
+ Chooses an alternate server.
++Note: This option must occur before all others.
+ -i job-id
+ Specifies an existing job to modify.
+ -m
+diff --git a/doc/help/man-lpinfo.html b/doc/help/man-lpinfo.html
+index a1aed9421..30df7691c 100644
+--- a/doc/help/man-lpinfo.html
++++ b/doc/help/man-lpinfo.html
+@@ -12,10 +12,10 @@ lpinfo - show available devices or drivers (deprecated)
+
+ lpinfo
+ [
+--E
+-] [
+ -h server[:port]
+ ] [
++-E
++] [
+ -l
+ ] [
+ --device-id
+@@ -40,10 +40,10 @@ lpinfo - show available devices or drivers (deprecated)
+
+ lpinfo
+ [
+--E
+-] [
+ -h server[:port]
+ ] [
++-E
++] [
+ -l
+ ] [
+ --exclude-schemes
+@@ -66,6 +66,7 @@ The first form (-m) lists the available drivers, while the second form (<
+ Forces encryption when connecting to the server.
+ -h server[:port]
+ Selects an alternate server.
++Note: This option must occur before all others.
+ -l
+ Shows a "long" listing of devices or drivers.
+ --device-id device-id-string
+diff --git a/doc/help/man-lpmove.html b/doc/help/man-lpmove.html
+index d8019ee25..b0db753f9 100644
+--- a/doc/help/man-lpmove.html
++++ b/doc/help/man-lpmove.html
+@@ -12,10 +12,10 @@ lpmove - move a job or all jobs to a new destination
+
+ lpmove
+ [
+--E
+-] [
+ -h server[:port]
+ ] [
++-E
++] [
+ -U
+ username
+ ]
+@@ -24,10 +24,10 @@ lpmove - move a job or all jobs to a new destination
+
+ lpmove
+ [
+--E
+-] [
+ -h server[:port]
+ ] [
++-E
++] [
+ -U
+ username
+ ]
+@@ -44,6 +44,7 @@ The lpmove command supports the following options:
+ Specifies an alternate username.
+ -h server[:port]
+ Specifies an alternate server.
++Note: This option must occur before all others.
+
+
+ Move job 123 from "oldprinter" to "newprinter":
+diff --git a/doc/help/man-lpoptions.html b/doc/help/man-lpoptions.html
+index 6dda87f64..6af78290b 100644
+--- a/doc/help/man-lpoptions.html
++++ b/doc/help/man-lpoptions.html
+@@ -12,12 +12,12 @@
+
+ lpoptions
+ [
+--E
+-] [
+--U
+-username
+-] [
+ -h server[:port]
++] [
++-E
++] [
++-U
++username
+ ]
+ -d destination[/instance]
+ [
+@@ -26,26 +26,26 @@
+
+ lpoptions
+ [
+--E
+-] [
+--U
+-username
+-] [
+ -h server[:port]
+ ] [
++-E
++] [
++-U
++username
++] [
+ -p destination[/instance]
+ ]
+ -o option[=value] ...
+
+ lpoptions
+ [
+--E
+-] [
+--U
+-username
+-] [
+ -h server[:port]
+ ] [
++-E
++] [
++-U
++username
++] [
+ -p destination[/instance]
+ ]
+ -r
+@@ -53,12 +53,12 @@
+
+ lpoptions
+ [
+--E
+-] [
+--U
+-username
+-] [
+ -h server[:port]
++] [
++-E
++] [
++-U
++username
+ ]
+ -x destination[/instance]
+
+@@ -84,6 +84,7 @@
+ This option overrides the system default printer for the current user.
+ -h server[:port]
+ Uses an alternate server.
++Note: This option must occur before all others.
+ -l
+ Lists the printer specific options and their current settings.
+ -o option[=value]
+@@ -119,7 +120,7 @@
+ lprm(1),
+ CUPS Online Help (http://localhost:631/help)
+
+-Copyright © 2007-2017 by Apple Inc.
++Copyright © 2021-2022 by OpenPrinting.
+
+