From 1481ddbf72479a849906b09fae822977f83872d6 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2020 11:45:00 +0000 Subject: import cups-2.2.6-38.el8 --- diff --git a/SOURCES/cups-autostart-when-enabled.patch b/SOURCES/cups-autostart-when-enabled.patch new file mode 100644 index 0000000..1cdefb6 --- /dev/null +++ b/SOURCES/cups-autostart-when-enabled.patch @@ -0,0 +1,10 @@ +diff --git a/scheduler/org.cups.cupsd.service.in b/scheduler/org.cups.cupsd.service.in +index 307d69b..add238b 100644 +--- a/scheduler/org.cups.cupsd.service.in ++++ b/scheduler/org.cups.cupsd.service.in +@@ -10,4 +10,4 @@ Restart=on-failure + + [Install] + Also=cups.socket cups.path +-WantedBy=printer.target ++WantedBy=printer.target multi-user.target diff --git a/SOURCES/cups-dirtyclean.patch b/SOURCES/cups-dirtyclean.patch new file mode 100644 index 0000000..390ed19 --- /dev/null +++ b/SOURCES/cups-dirtyclean.patch @@ -0,0 +1,13 @@ +diff --git a/scheduler/main.c b/scheduler/main.c +index 592531a..a6e2c3a 100644 +--- a/scheduler/main.c ++++ b/scheduler/main.c +@@ -947,7 +947,7 @@ main(int argc, /* I - Number of command-line args */ + * Write dirty config/state files... + */ + +- if (DirtyCleanTime && current_time >= DirtyCleanTime && cupsArrayCount(Clients) == 0) ++ if (DirtyCleanTime && current_time >= DirtyCleanTime) + cupsdCleanDirty(); + + #ifdef __APPLE__ diff --git a/SOURCES/cups-etimedout.patch b/SOURCES/cups-etimedout.patch new file mode 100644 index 0000000..31defda --- /dev/null +++ b/SOURCES/cups-etimedout.patch @@ -0,0 +1,25 @@ +diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c +index e4ffc3d..a989055 100644 +--- a/cups/http-addrlist.c ++++ b/cups/http-addrlist.c +@@ -240,7 +240,10 @@ httpAddrConnect2( + } + + if (!addrlist && nfds == 0) ++ { ++ errno = EHOSTDOWN; + break; ++ } + + /* + * See if we can connect to any of the addresses so far... +@@ -371,6 +374,9 @@ httpAddrConnect2( + remaining -= 250; + } + ++ if (remaining <= 0) ++ errno = ETIMEDOUT; ++ + while (nfds > 0) + { + nfds --; diff --git a/SOURCES/cups-failover-backend.patch b/SOURCES/cups-failover-backend.patch new file mode 100644 index 0000000..a92dad8 --- /dev/null +++ b/SOURCES/cups-failover-backend.patch @@ -0,0 +1,877 @@ +diff --git a/backend/Makefile b/backend/Makefile +index 3038682..6642016 100644 +--- a/backend/Makefile ++++ b/backend/Makefile +@@ -28,6 +28,7 @@ include ../Makedefs + RBACKENDS = \ + ipp \ + lpd \ ++ failover \ + $(DNSSD_BACKEND) + UBACKENDS = \ + snmp \ +@@ -51,6 +52,7 @@ LIBOBJS = \ + OBJS = \ + ipp.o \ + lpd.o \ ++ failover.o \ + dnssd.o \ + snmp.o \ + socket.o \ +@@ -275,6 +277,13 @@ lpd: lpd.o ../cups/$(LIBCUPS) libbackend.a + echo Linking $@... + $(LD_CC) $(LDFLAGS) -o lpd lpd.o libbackend.a $(LIBS) + ++# ++# failover ++# ++ ++failover: failover.o ../cups/$(LIBCUPS) libbackend.a ++ echo Linking $@... ++ $(LD_CC) $(LDFLAGS) -o failover failover.o libbackend.a $(LIBS) + + # + # snmp +diff --git a/backend/failover.c b/backend/failover.c +new file mode 100644 +index 0000000..9affd8f +--- /dev/null ++++ b/backend/failover.c +@@ -0,0 +1,837 @@ ++/* ++ * Failover Backend for the Common UNIX Printing System (CUPS). ++ * ++ * Copyright (c) 2014, Red Hat, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Red Hat, Inc. nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT, ++ * INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * Original version by Clark Hale, Red Hat, Inc. ++ * ++ * This backend presents a fake printer that will choose the first ++ * available printer from a list of IPP URIs. ++ * ++ * Option failover contains a comma separated list of IPP URIs. The ++ * URIs are attempted in-order. ++ * ++ * Option failover-retries contains an integer that indicates how many ++ * times to iterate through the failover list before completely ++ * failing. ++ * ++ * Contents: ++ * main() - Checks each printer in a failover list, and ++ * sends job data to the first available printer ++ * move_job() - Sends and IPP Move-Job request ++ * check_printer() - Checks a printer's attributes to see ++ * if it's enabled and accepting jobs ++ * read_config() - Read the backends configuration from ++ * options ++ * get_printer_attributes() - Sends an IPP Get-Attributes request to ++ * a URI ++ * sigterm_handler() - Handle SIGTERM that cancels the job ++ * password_cb() - Password call back used to disable password ++ * prompt ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "backend-private.h" ++ ++/* ++ * Return Values ++ */ ++typedef enum fo_state_e ++{ ++ FO_PRINTER_GOOD = 0, ++ FO_PRINTER_BAD, ++ FO_PRINTER_BUSY, ++ FO_AUTH_REQUIRED ++} fo_state_t; ++ ++/* ++ * Constants ++ */ ++#define FAILOVER_DEFAULT_RETRIES (3) ++#define FAILOVER_PASSWORD_RETRIES_MAX (3) ++ ++/* ++ * Local Functions ++ */ ++static int check_printer(const char *device_uri); ++static int read_config(cups_array_t *printer_array, int *retries, ++ const char *options); ++static int get_printer_attributes(const char *device_uri, ++ ipp_t **attributes); ++static int move_job(int jobid, const char *dest); ++static void sigterm_handler(int sig); ++static const char *password_cb(const char *); ++ ++/* ++ * Global Variables ++ */ ++static int job_canceled = 0; /* Job canceled */ ++static char *password = NULL; /* password for device */ ++static int password_retries = 0; ++static const char *auth_info_required = "none"; ++ ++/* ++ * 'main()' - Checks each printer in a failover list, and ++ * sends job data to the first available printer ++ * Usage: ++ * printer-uri job-id user title copies options [file] ++ * ++ * The printer-uri option is not used, but it still required to fit ++ * to the backend(7) standards. ++ */ ++int ++main(int argc, char *argv[]) ++{ ++ const char *selected_uri = NULL; /* URI of selected printer */ ++ const char *tmp_device_uri; /* Device URI to check */ ++ cups_array_t *printer_array; /* Array of available printers */ ++ int printer_count = 0; /* current printer array index */ ++ int retry_max = 1; /* maximum retries before exit */ ++ int retry_count = 0; /* current retry number */ ++ int auth_failed_count = 0; /* auth failures per loop */ ++ int rc = CUPS_BACKEND_OK; ++#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) ++ struct sigaction action; /* Actions for POSIX signals */ ++#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ ++ ++ /* ++ * Check args ++ */ ++ if (argc == 1) ++ { ++ /* ++ * print out discovery data ++ */ ++ char *backendName; ++ ++ if ((backendName = strrchr(argv[0], '/')) != NULL) ++ backendName++; ++ else ++ backendName = argv[0]; ++ ++ _cupsLangPrintf(stderr,"network %s \"Unknown\" \"%s (%s)\"\n", ++ backendName, ++ _cupsLangString(cupsLangDefault(), _("Failover Printer")), ++ backendName); ++ ++ return (CUPS_BACKEND_OK); ++ } ++ else if (argc < 6) ++ { ++ _cupsLangPrintf(stderr, ++ _("Usage: %s job-id user title copies options [file]"), ++ argv[0]); ++ return (CUPS_BACKEND_STOP); ++ } ++ ++ fprintf(stderr, "DEBUG: Failover backend starting up.\n"); ++ ++ /* ++ * Don't buffer status messages ++ */ ++ setbuf(stderr, NULL); ++ ++ /* ++ * Ignore SIGPIPE and catch SIGTERM signals... ++ */ ++#ifdef HAVE_SIGSET ++ sigset(SIGPIPE, SIG_IGN); ++ sigset(SIGTERM, sigterm_handler); ++#elif defined(HAVE_SIGACTION) ++ memset(&action, 0, sizeof(action)); ++ action.sa_handler = SIG_IGN; ++ sigaction(SIGPIPE, &action, NULL); ++ ++ sigemptyset(&action.sa_mask); ++ sigaddset(&action.sa_mask, SIGTERM); ++ action.sa_handler = sigterm_handler; ++ sigaction(SIGTERM, &action, NULL); ++#else ++ signal(SIGPIPE, SIG_IGN); ++ signal(SIGTERM, sigterm_handler); ++#endif /* HAVE_SIGSET */ ++ ++ printer_array = cupsArrayNew(NULL, NULL); ++ ++ /* ++ * Read Configuration ++ */ ++ if ((rc = read_config(printer_array, &retry_max, ++ argv[5])) != CUPS_BACKEND_OK) ++ { ++ fprintf(stderr, "ERROR: Failed to read configuration options!\n"); ++ goto cleanup; ++ } ++ ++ /* ++ * Main Retry Loop ++ */ ++ for (retry_count = 0; retry_count < retry_max; retry_count++) ++ { ++ fprintf(stderr, "DEBUG: Retry loop #%d\n", retry_count + 1); ++ ++ /* ++ * Reset Counters ++ */ ++ printer_count = 0; ++ auth_failed_count = 0; ++ ++ tmp_device_uri = (char *)cupsArrayFirst(printer_array); ++ ++ do ++ { ++ if (job_canceled) ++ { ++ fprintf(stderr, "DEBUG: Job Canceled\n"); ++ goto cleanup; ++ } ++ ++ fprintf(stderr,"DEBUG: Checking printer #%d: %s\n", ++ printer_count+1, tmp_device_uri); ++ ++ rc = check_printer(tmp_device_uri); ++ ++ // Printer is available and not busy. ++ if ( rc == FO_PRINTER_GOOD ) ++ { ++ selected_uri = tmp_device_uri; ++ break; ++ } ++ // Printer is busy ++ else if (rc == FO_PRINTER_BUSY) ++ { ++ fprintf(stderr, "DEBUG: Waiting for job to complete.\n"); ++ sleep(2); ++ continue; ++ } ++ // Authorization is required to access the printer. ++ else if (rc == FO_AUTH_REQUIRED) ++ { ++ auth_failed_count++; ++ fprintf(stderr, "DEBUG: auth_failed_count = %d\n", auth_failed_count); ++ } ++ // Printer is stopped or not accepting jobs ++ else ++ { ++ if (!printer_count) ++ fprintf(stderr, "INFO: Primary Printer, %s, not available. " ++ "Attempting Failovers...\n", ++ tmp_device_uri); ++ else ++ fprintf(stderr, "INFO: Failover Printer, %s, not available. " ++ "Attempting Failovers..\n", ++ tmp_device_uri); ++ printer_count++; ++ tmp_device_uri = (char *)cupsArrayNext(printer_array); ++ } ++ } while (tmp_device_uri != NULL); ++ ++ if (selected_uri && !printer_count) ++ fprintf(stderr, "STATE: -primary-printer-failed\n"); ++ else ++ fprintf(stderr, "STATE: +primary-printer-failed\n"); ++ ++ if (job_canceled) ++ { ++ fprintf(stderr, "DEBUG: Job Canceled\n"); ++ goto cleanup; ++ } ++ ++ if (!selected_uri && auth_failed_count == printer_count) ++ { ++ fprintf(stderr, "ERROR: All failover printers failed with " ++ "authorization issues.\n"); ++ rc = CUPS_BACKEND_AUTH_REQUIRED; ++ fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required); ++ goto cleanup; ++ } ++ else if (!selected_uri && retry_count + 1 < retry_max) ++ { ++ fprintf(stderr, "INFO: No suitable printer found...retrying...\n"); ++ sleep(2); ++ continue; ++ } ++ else if (selected_uri) ++ { ++ fprintf(stderr, "DEBUG: Using printer, %s.\n", selected_uri); ++ break; ++ } ++ } ++ ++ if (!selected_uri) ++ { ++ fprintf(stderr, "ERROR: No suitable printer found. Aborting print\n"); ++ rc = CUPS_BACKEND_FAILED; ++ goto cleanup; ++ } ++ ++ rc = move_job(atoi(argv[1]), selected_uri); ++ ++ if (job_canceled) ++ rc = CUPS_BACKEND_OK; ++ ++cleanup : ++ if (job_canceled) ++ rc = CUPS_BACKEND_OK; ++ ++ tmp_device_uri = (char *)cupsArrayFirst(printer_array); ++ do ++ { ++ free((void *)tmp_device_uri); ++ } while ((tmp_device_uri = (char *)cupsArrayNext(printer_array)) != NULL); ++ ++ cupsArrayDelete(printer_array); ++ sleep(2); ++ return (rc); ++} ++ ++/* ++ * 'check_printer()' - Checks the status of a remote printer and returns ++ * back a good/bad/busy status. ++ */ ++int ++check_printer(const char *device_uri) ++{ ++ ipp_t *attributes = NULL; /* attributes for device_uri */ ++ ipp_attribute_t *tmp_attribute; /* for examining attribs */ ++ int rc = FO_PRINTER_GOOD; /* return code */ ++ char *reason; /* printer state reason */ ++ int i; ++ ++ fprintf(stderr, "DEBUG: Checking printer %s\n",device_uri); ++ ++ rc = get_printer_attributes(device_uri, &attributes); ++ if ( rc != CUPS_BACKEND_OK ) ++ { ++ fprintf(stderr, "DEBUG: Failed to get attributes from printer: %s\n", ++ device_uri); ++ if ( rc == CUPS_BACKEND_AUTH_REQUIRED ) ++ return (FO_AUTH_REQUIRED); ++ else ++ return (FO_PRINTER_BAD); ++ } ++ ++ /* ++ * Check if printer is accepting jobs ++ */ ++ if ((tmp_attribute = ippFindAttribute(attributes, ++ "printer-is-accepting-jobs", ++ IPP_TAG_BOOLEAN)) != NULL && ++ !tmp_attribute->values[0].boolean) ++ { ++ fprintf(stderr, ++ "DEBUG: Printer, %s, is not accepting jobs.\n", ++ device_uri); ++ ++ rc = FO_PRINTER_BAD; ++ } ++ ++ /* ++ * Check if printer is stopped or busy processing ++ */ ++ if ((tmp_attribute = ippFindAttribute(attributes, ++ "printer-state", ++ IPP_TAG_ENUM)) != NULL) ++ { ++ // Printer Stopped ++ if ( tmp_attribute->values[0].integer == IPP_PRINTER_STOPPED ) ++ { ++ fprintf(stderr, "DEBUG: Printer, %s, stopped.\n", device_uri); ++ rc = FO_PRINTER_BAD; ++ } ++ // Printer Busy ++ else if ( tmp_attribute->values[0].integer == IPP_PRINTER_PROCESSING ) ++ { ++ fprintf(stderr, "DEBUG: Printer %s is busy.\n", device_uri); ++ rc = FO_PRINTER_BUSY; ++ } ++ } ++ ++ /* ++ * Parse through the printer-state-reasons ++ */ ++ if ((tmp_attribute = ippFindAttribute(attributes, "printer-state-reasons", ++ IPP_TAG_KEYWORD)) != NULL) ++ { ++ for (i = 0; i < tmp_attribute->num_values; i++) ++ { ++ reason = tmp_attribute->values[i].string.text; ++ int len = strlen(reason); ++ ++ if (len > 8 && !strcmp(reason + len - 8, "-warning")) ++ { ++ fprintf(stderr, "DEBUG: Printer Supply Warning, %s\n", reason); ++ rc = FO_PRINTER_BAD; ++ } ++ else if (len > 6 && !strcmp(reason + len - 6, "-error")) ++ { ++ fprintf(stderr, "DEBUG: Printer Supply Error, %s\n", reason); ++ rc = FO_PRINTER_BAD; ++ } ++ } ++ } ++ ++ return (rc); ++} ++ ++/* ++ * 'read_config()' - Parses the failover and failover-retries options ++ * ++ */ ++static int ++read_config(cups_array_t *printer_array, int *retries, const char *options) ++{ ++ ++ const char *tmp; /* temporary ptr */ ++ char *tok_tmp; /* temporary ptr for option parsing */ ++ int jobopts_count = 0; /* number of options */ ++ cups_option_t *jobopts = NULL; /* job options */ ++ ++ ++ fprintf(stderr, "DEBUG: Reading Configuration.\n"); ++ jobopts_count = cupsParseOptions(options, 0, &jobopts); ++ ++ if (!jobopts_count) ++ { ++ fprintf(stderr, ++ "ERROR: No job options! Cannot find failover options!\n"); ++ return (CUPS_BACKEND_STOP); ++ } ++ ++ /* ++ * Get attributes from the primary printer ++ */ ++ fprintf(stderr, "DEBUG: Searching for failover option.\n"); ++ ++ if ((tmp = cupsGetOption("failover", jobopts_count, jobopts)) != NULL) ++ { ++ fprintf(stderr, "DEBUG: Failover option contents: %s.\n", tmp); ++ ++ tok_tmp = strdup(tmp); ++ ++ tmp = strtok(tok_tmp, ","); ++ do ++ { ++ cupsArrayAdd(printer_array, strdup(tmp)); ++ } while ((tmp = strtok(NULL,",")) != NULL); ++ ++ free(tok_tmp); ++ } ++ else ++ { ++ /* ++ * The queue is misconfigured, so return back CUPS_BACKEND_STOP ++ */ ++ fprintf(stderr, "ERROR: failover option not specified!\n"); ++ return (CUPS_BACKEND_STOP); ++ } ++ ++ /* ++ * Get the failover-retries value, if it exists. ++ */ ++ fprintf(stderr, "DEBUG: Searching for failover-retries option.\n"); ++ ++ if ((tmp = cupsGetOption("failover-retries", ++ jobopts_count, jobopts)) != NULL) ++ { ++ fprintf(stderr, "DEBUG: failover-retries option contents: %s.\n", tmp); ++ *retries = atoi(tmp); ++ } ++ else ++ { ++ *retries = FAILOVER_DEFAULT_RETRIES; ++ fprintf(stderr, "DEBUG: Failed to get failover-retries option\n"); ++ fprintf(stderr, "DEBUG: Defaulted to %d retries\n", *retries); ++ } ++ ++ return (CUPS_BACKEND_OK); ++} ++ ++/* ++ * 'get_printer_attributes()' - Sends an IPP Get-Attributes request to ++ * a URI ++ */ ++int ++get_printer_attributes(const char *device_uri, ipp_t **attributes) ++{ ++ char uri[HTTP_MAX_URI]; /* Updated URI without login */ ++ int version; /* IPP version */ ++ char scheme[256]; /* Scheme in URI */ ++ ipp_status_t ipp_status; /* Status of IPP request */ ++ char hostname[1024]; /* Hostname */ ++ char resource[1024]; /* Resource infoo */ ++ char addrname[256]; /* Address name */ ++ int port; /* IPP Port number */ ++ char portname[255]; /* Port as string */ ++ http_t *http; /* HTTP connection */ ++ ipp_t *request; /* IPP request */ ++ int rc = CUPS_BACKEND_OK; /* Return Code */ ++ char username[256]; /* Username for device URI */ ++ char *option_ptr; /* for parsing resource opts */ ++ const char * const pattrs[] = /* Printer attributes wanted */ ++ { ++ "printer-is-accepting-jobs", ++ "printer-state", ++ "printer-state-reasons" ++ }; ++ ++ if (job_canceled) ++ return (CUPS_BACKEND_OK); ++ ++ fprintf(stderr, "DEBUG: Getting Printer Attributes.\n"); ++ fprintf(stderr, "DEBUG: Device URL %s.\n", device_uri); ++ ++ /* ++ * Parse device_uri ++ */ ++ if (httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), ++ username, sizeof(username), hostname, sizeof(hostname), ++ &port, resource, sizeof(resource)) != HTTP_URI_OK) ++ { ++ fprintf(stderr, "ERROR: Problem parsing device_uri, %s\n", device_uri); ++ return (CUPS_BACKEND_STOP); ++ } ++ ++ if (!port) ++ port = IPP_PORT; ++ ++ sprintf(portname, "%d", port); ++ ++ fprintf(stderr, "DEBUG: Getting Printer Attributes.\n"); ++ ++ /* ++ * Configure password ++ */ ++ cupsSetPasswordCB(password_cb); ++ ++ /* ++ * reset, in case a previous attempt for ++ * another printer left residue ++ */ ++ cupsSetUser(NULL); ++ password = NULL; ++ password_retries = 0; ++ ++ if (*username) ++ { ++ if ((password = strchr(username, ':')) != NULL) ++ { ++ *password = '\0'; ++ password++; ++ } ++ ++ cupsSetUser(username); ++ } ++ else if (!getuid()) ++ { ++ const char *username_env; ++ ++ if ((username_env = getenv("AUTH_USERNAME")) != NULL) ++ { ++ cupsSetUser(username_env); ++ password = getenv("AUTH_PASSWORD"); ++ } ++ } ++ ++ /* ++ * Try connecting to the remote server... ++ */ ++ fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port); ++ _cupsLangPuts(stderr, _("INFO: Connecting to printer...\n")); ++ ++ http = httpConnectEncrypt(hostname, port, cupsEncryption()); ++ ++ /* ++ * Deal the socket not being open. ++ */ ++ if (!http) ++ { ++ int error = errno; /* Connection error */ ++ ++ switch (error) ++ { ++ case EHOSTDOWN : ++ _cupsLangPuts(stderr, _("WARNING: " ++ "The printer may not exist or " ++ "is unavailable at this time.\n")); ++ break; ++ case EHOSTUNREACH : ++ _cupsLangPuts(stderr, _("WARNING: " ++ "The printer is unreachable at this " ++ "time.\n")); ++ break; ++ case ECONNREFUSED : ++ _cupsLangPuts(stderr, _("WARNING: " ++ "Connection Refused.\n")); ++ break; ++ default : ++ fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno)); ++ break; ++ } ++ ++ rc = CUPS_BACKEND_FAILED; ++ sleep(5); ++ goto prt_available_cleanup; ++ } ++ ++ ++#ifdef AF_INET6 ++ if (http->hostaddr->addr.sa_family == AF_INET6) ++ fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6)...\n", ++ httpAddrString(http->hostaddr, addrname, sizeof(addrname)), ++ ntohs(http->hostaddr->ipv6.sin6_port)); ++ else ++#endif /* AF_INET6 */ ++ if (http->hostaddr->addr.sa_family == AF_INET) ++ fprintf(stderr, "DEBUG: Connected to %s:%d (IPv4)...\n", ++ httpAddrString(http->hostaddr, addrname, sizeof(addrname)), ++ ntohs(http->hostaddr->ipv4.sin_port)); ++ ++ /* ++ * Search the resource string for options. ++ * We only care about version, for the moment. ++ */ ++ version = 11; ++ ++ if ((option_ptr = strchr(resource, '?')) != NULL) ++ { ++ *option_ptr++ = '\0'; ++ ++ if ((option_ptr = strstr(option_ptr, "version="))!=NULL) ++ { ++ int minor; /* minor version from URI */ ++ int major; /* major version from URI */ ++ char *version_str; /* ipp version */ ++ ++ option_ptr += 8; ++ version_str = option_ptr; ++ ++ while (*option_ptr && *option_ptr != '&' && *option_ptr != '+') ++ option_ptr++; ++ ++ if (*option_ptr) ++ *option_ptr = '\0'; ++ ++ sscanf(version_str, "%d.%d", &major, &minor); ++ ++ version = (major * 10) + minor; ++ ++ switch(version) ++ { ++ case 10 : ++ case 11 : ++ case 20 : ++ case 21 : ++ fprintf(stderr, ++ "DEBUG: Set version to %d from URI\n", ++ version); ++ break; ++ default : ++ _cupsLangPrintf(stderr, ++ _("DEBUG: Invalid version, %d, from URI. " ++ "Using default of 1.1 \n"), ++ version); ++ version = 11; ++ } ++ } ++ } ++ ++ ++ /* ++ * Build a URI for the printer. We can't use the URI in argv[0] ++ * because it might contain username:password information... ++ */ ++ if (httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), scheme, NULL, ++ hostname, port, resource) != HTTP_URI_OK) ++ { ++ fprintf(stderr, "ERROR: Problem assembling printer URI from host %s, " ++ "port %d, resource %s\n", hostname, port, resource); ++ return (CUPS_BACKEND_STOP); ++ } ++ ++ /* ++ * Build the IPP request... ++ */ ++ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); ++ request->request.op.version[0] = version / 10; ++ request->request.op.version[1] = version % 10; ++ ++ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", ++ NULL, uri); ++ ++ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, ++ "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), ++ NULL, pattrs); ++ ++ /* ++ * Do the request... ++ */ ++ fputs("DEBUG: Getting supported attributes...\n", stderr); ++ ++ fprintf(stderr, "DEBUG: IPP Request Structure Built.\n"); ++ ++ *attributes = cupsDoRequest(http, request, resource); ++ ipp_status = cupsLastError(); ++ ++ fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n", ++ ippErrorString(ipp_status), cupsLastErrorString()); ++ ++ if (ipp_status > IPP_OK_CONFLICT) ++ { ++ fprintf(stderr, "DEBUG: Get-Printer-Attributes returned %s.\n", ++ ippErrorString(ipp_status)); ++ switch(ipp_status) ++ { ++ case IPP_FORBIDDEN : ++ case IPP_NOT_AUTHORIZED : ++ _cupsLangPuts(stderr, _("ERROR: Not Authorized.\n")); ++ rc = CUPS_BACKEND_AUTH_REQUIRED; ++ break; ++ case IPP_PRINTER_BUSY : ++ case IPP_SERVICE_UNAVAILABLE : ++ _cupsLangPuts(stderr, _("ERROR: " ++ "The printer is not responding.\n")); ++ rc = CUPS_BACKEND_FAILED; ++ break; ++ case IPP_BAD_REQUEST : ++ case IPP_VERSION_NOT_SUPPORTED : ++ fprintf(stderr, "ERROR: Destination does not support IPP version %d\n", ++ version); ++ case IPP_NOT_FOUND : ++ _cupsLangPuts(stderr, _("ERROR: " ++ "The printer configuration is incorrect or the " ++ "printer no longer exists.\n")); ++ rc = CUPS_BACKEND_STOP; ++ break; ++ default : ++ rc = CUPS_BACKEND_FAILED; ++ } ++ goto prt_available_cleanup; ++ } ++ ++prt_available_cleanup : ++ httpClose(http); ++ return (rc); ++} ++ ++static int ++move_job(int jobid, /* Job ID */ ++ const char *dest) /* Destination ipp address */ ++{ ++ ipp_t *request; /* IPP Request */ ++ char job_uri[HTTP_MAX_URI]; /* job-uri */ ++ ++ http_t* http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); ++ ++ if (!http) ++ { ++ _cupsLangPrintf(stderr, ++ _("failover: Unable to connect to server: %s\n"), ++ strerror(errno)); ++ return (CUPS_BACKEND_FAILED); ++ } ++ ++ /* ++ * Build a CUPS_MOVE_JOB request, which requires the following ++ * attributes: ++ * ++ * job-uri/printer-uri ++ * job-printer-uri ++ * requesting-user-name ++ */ ++ ++ request = ippNewRequest(CUPS_MOVE_JOB); ++ ++ snprintf(job_uri, sizeof(job_uri), "ipp://localhost/jobs/%d", jobid); ++ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, ++ job_uri); ++ ++ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, ++ "requesting-user-name", ++ NULL, cupsUser()); ++ ++ ippAddString(request, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", ++ NULL, dest); ++ ++ /* ++ * Do the request and get back a response... ++ */ ++ ++ ippDelete(cupsDoRequest(http, request, "/jobs")); ++ ++ httpClose(http); ++ ++ if (cupsLastError() > IPP_OK_CONFLICT) ++ { ++ _cupsLangPrintf(stderr, "failover: %s\n", cupsLastErrorString()); ++ return (CUPS_BACKEND_FAILED); ++ } ++ else ++ return (CUPS_BACKEND_OK); ++} ++ ++/* ++ * 'sigterm_handler()' - handles a sigterm, i.e. job canceled ++ */ ++static void ++sigterm_handler(int sig) ++{ ++ if (!job_canceled) ++ { ++ write(2, "DEBUG: Got SIGTERM.\n", 20); ++ job_canceled = 1; ++ } ++ else ++ { ++ /* ++ * Job has already been canceled, so just exit ++ */ ++ exit(1); ++ } ++} ++ ++/* ++ * 'password_cb()' - Disable the password prompt for cupsDoFileRequest(). ++ */ ++static const char * /* O - Password */ ++password_cb(const char *prompt) /* I - Prompt (not used) */ ++{ ++ auth_info_required = "username,password"; ++ password_retries++; ++ ++ if(password_retries < FAILOVER_PASSWORD_RETRIES_MAX) ++ return (password); ++ else ++ return (NULL); ++} diff --git a/SOURCES/cups-memory-consumption.patch b/SOURCES/cups-memory-consumption.patch index 9418f36..5ccfbba 100644 --- a/SOURCES/cups-memory-consumption.patch +++ b/SOURCES/cups-memory-consumption.patch @@ -401,7 +401,7 @@ index 464c09a..cb67468 100644 } } diff --git a/cups/ppd.c b/cups/ppd.c -index 8276988..db849ac 100644 +index 8276988..6782a85 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -34,8 +34,6 @@ @@ -571,7 +571,7 @@ index 8276988..db849ac 100644 /* * Allocate memory for the PPD file record... */ -@@ -651,8 +628,8 @@ _ppdOpen( +@@ -651,12 +628,15 @@ _ppdOpen( { pg->ppd_status = PPD_ALLOC_ERROR; @@ -582,7 +582,14 @@ index 8276988..db849ac 100644 return (NULL); } -@@ -735,6 +712,8 @@ _ppdOpen( + ++ free(string); ++ string = NULL; ++ + ppd->language_level = 2; + ppd->color_device = 0; + ppd->colorspace = PPD_CS_N; +@@ -735,6 +715,8 @@ _ppdOpen( strncmp(ll, keyword, ll_len))) { DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword)); @@ -591,7 +598,7 @@ index 8276988..db849ac 100644 continue; } else if (localization == _PPD_LOCALIZATION_ICC_PROFILES) -@@ -754,6 +733,8 @@ _ppdOpen( +@@ -754,6 +736,8 @@ _ppdOpen( if (i >= (int)(sizeof(color_keywords) / sizeof(color_keywords[0]))) { DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword)); @@ -600,7 +607,7 @@ index 8276988..db849ac 100644 continue; } } -@@ -849,7 +830,7 @@ _ppdOpen( +@@ -849,7 +833,7 @@ _ppdOpen( * Say all PPD files are UTF-8, since we convert to UTF-8... */ @@ -609,7 +616,7 @@ index 8276988..db849ac 100644 encoding = _ppdGetEncoding(string); } else if (!strcmp(keyword, "LanguageVersion")) -@@ -870,10 +851,10 @@ _ppdOpen( +@@ -870,10 +854,10 @@ _ppdOpen( cupsCharsetToUTF8(utf8, string, sizeof(utf8), encoding); @@ -622,7 +629,7 @@ index 8276988..db849ac 100644 } else if (!strcmp(keyword, "Product")) ppd->product = string; -@@ -883,17 +864,17 @@ _ppdOpen( +@@ -883,17 +867,17 @@ _ppdOpen( ppd->ttrasterizer = string; else if (!strcmp(keyword, "JCLBegin")) { @@ -643,7 +650,7 @@ index 8276988..db849ac 100644 ppd_decode(ppd->jcl_ps); /* Decode quoted string */ } else if (!strcmp(keyword, "AccurateScreensSupport")) -@@ -961,10 +942,10 @@ _ppdOpen( +@@ -961,10 +945,10 @@ _ppdOpen( ppd->num_filters ++; /* @@ -656,7 +663,7 @@ index 8276988..db849ac 100644 } else if (!strcmp(keyword, "Throughput")) ppd->throughput = atoi(string); -@@ -987,7 +968,7 @@ _ppdOpen( +@@ -987,7 +971,7 @@ _ppdOpen( } ppd->fonts = tempfonts; @@ -665,7 +672,7 @@ index 8276988..db849ac 100644 ppd->num_fonts ++; } else if (!strncmp(keyword, "ParamCustom", 11)) -@@ -1152,7 +1133,7 @@ _ppdOpen( +@@ -1152,7 +1136,7 @@ _ppdOpen( strlcpy(choice->text, text[0] ? text : _("Custom"), sizeof(choice->text)); @@ -674,13 +681,12 @@ index 8276988..db849ac 100644 if (custom_option->section == PPD_ORDER_JCL) ppd_decode(choice->code); -@@ -1201,59 +1182,23 @@ _ppdOpen( +@@ -1201,59 +1185,23 @@ _ppdOpen( else if (!strcmp(string, "Plus90")) ppd->landscape = 90; } - else if (!strcmp(keyword, "Emulators") && string) -+ else if (!strcmp(keyword, "Emulators") && string && ppd->num_emulations == 0) - { +- { - for (count = 1, sptr = string; sptr != NULL;) - if ((sptr = strchr(sptr, ' ')) != NULL) - { @@ -712,7 +718,8 @@ index 8276988..db849ac 100644 - } - } - else if (!strncmp(keyword, "StartEmulator_", 14)) -- { ++ else if (!strcmp(keyword, "Emulators") && string && ppd->num_emulations == 0) + { - ppd_decode(string); + /* + * Issue #5562: Samsung printer drivers incorrectly use Emulators keyword @@ -748,7 +755,7 @@ index 8276988..db849ac 100644 } else if (!strcmp(keyword, "JobPatchFile")) { -@@ -1408,7 +1353,7 @@ _ppdOpen( +@@ -1408,7 +1356,7 @@ _ppdOpen( option->section = PPD_ORDER_ANY; @@ -757,7 +764,7 @@ index 8276988..db849ac 100644 string = NULL; /* -@@ -1436,7 +1381,7 @@ _ppdOpen( +@@ -1436,7 +1384,7 @@ _ppdOpen( strlcpy(choice->text, custom_attr->text[0] ? custom_attr->text : _("Custom"), sizeof(choice->text)); @@ -766,7 +773,7 @@ index 8276988..db849ac 100644 } } else if (!strcmp(keyword, "JCLOpenUI")) -@@ -1515,7 +1460,7 @@ _ppdOpen( +@@ -1515,7 +1463,7 @@ _ppdOpen( option->section = PPD_ORDER_JCL; group = NULL; @@ -775,7 +782,7 @@ index 8276988..db849ac 100644 string = NULL; /* -@@ -1539,14 +1484,14 @@ _ppdOpen( +@@ -1539,14 +1487,14 @@ _ppdOpen( strlcpy(choice->text, custom_attr->text[0] ? custom_attr->text : _("Custom"), sizeof(choice->text)); @@ -792,7 +799,7 @@ index 8276988..db849ac 100644 string = NULL; } else if (!strcmp(keyword, "OpenGroup")) -@@ -1593,14 +1538,14 @@ _ppdOpen( +@@ -1593,14 +1541,14 @@ _ppdOpen( if (group == NULL) goto error; @@ -809,7 +816,7 @@ index 8276988..db849ac 100644 string = NULL; } else if (!strcmp(keyword, "OrderDependency")) -@@ -1658,7 +1603,7 @@ _ppdOpen( +@@ -1658,7 +1606,7 @@ _ppdOpen( option->order = order; } @@ -818,7 +825,7 @@ index 8276988..db849ac 100644 string = NULL; } else if (!strncmp(keyword, "Default", 7)) -@@ -1901,7 +1846,7 @@ _ppdOpen( +@@ -1901,7 +1849,7 @@ _ppdOpen( * Don't add this one as an attribute... */ @@ -827,7 +834,7 @@ index 8276988..db849ac 100644 string = NULL; } else if (!strcmp(keyword, "PaperDimension")) -@@ -1923,7 +1868,7 @@ _ppdOpen( +@@ -1923,7 +1871,7 @@ _ppdOpen( size->width = (float)_cupsStrScand(string, &sptr, loc); size->length = (float)_cupsStrScand(sptr, NULL, loc); @@ -836,7 +843,7 @@ index 8276988..db849ac 100644 string = NULL; } else if (!strcmp(keyword, "ImageableArea")) -@@ -1947,7 +1892,7 @@ _ppdOpen( +@@ -1947,7 +1895,7 @@ _ppdOpen( size->right = (float)_cupsStrScand(sptr, &sptr, loc); size->top = (float)_cupsStrScand(sptr, NULL, loc); @@ -845,7 +852,7 @@ index 8276988..db849ac 100644 string = NULL; } else if (option != NULL && -@@ -2003,7 +1948,7 @@ _ppdOpen( +@@ -2003,7 +1951,7 @@ _ppdOpen( (mask & (PPD_KEYWORD | PPD_STRING)) == (PPD_KEYWORD | PPD_STRING)) ppd_add_attr(ppd, keyword, name, text, string); else @@ -854,7 +861,7 @@ index 8276988..db849ac 100644 } /* -@@ -2016,7 +1961,8 @@ _ppdOpen( +@@ -2016,7 +1964,8 @@ _ppdOpen( goto error; } @@ -864,7 +871,7 @@ index 8276988..db849ac 100644 /* * Reset language preferences... -@@ -2098,8 +2044,8 @@ _ppdOpen( +@@ -2098,8 +2047,8 @@ _ppdOpen( error: @@ -875,7 +882,7 @@ index 8276988..db849ac 100644 ppdClose(ppd); -@@ -2537,9 +2483,9 @@ ppd_free_filters(ppd_file_t *ppd) /* I - PPD file */ +@@ -2537,9 +2486,9 @@ ppd_free_filters(ppd_file_t *ppd) /* I - PPD file */ if (ppd->num_filters > 0) { for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++) @@ -887,7 +894,7 @@ index 8276988..db849ac 100644 ppd->num_filters = 0; ppd->filters = NULL; -@@ -2566,7 +2512,7 @@ ppd_free_group(ppd_group_t *group) /* I - Group to free */ +@@ -2566,7 +2515,7 @@ ppd_free_group(ppd_group_t *group) /* I - Group to free */ i --, option ++) ppd_free_option(option); @@ -896,7 +903,7 @@ index 8276988..db849ac 100644 } if (group->num_subgroups > 0) -@@ -2576,7 +2522,7 @@ ppd_free_group(ppd_group_t *group) /* I - Group to free */ +@@ -2576,7 +2525,7 @@ ppd_free_group(ppd_group_t *group) /* I - Group to free */ i --, subgroup ++) ppd_free_group(subgroup); @@ -905,7 +912,7 @@ index 8276988..db849ac 100644 } } -@@ -2598,10 +2544,10 @@ ppd_free_option(ppd_option_t *option) /* I - Option to free */ +@@ -2598,10 +2547,10 @@ ppd_free_option(ppd_option_t *option) /* I - Option to free */ i > 0; i --, choice ++) { @@ -918,7 +925,7 @@ index 8276988..db849ac 100644 } } -@@ -3338,7 +3284,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ +@@ -3338,7 +3287,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ lineptr ++; } @@ -927,7 +934,7 @@ index 8276988..db849ac 100644 mask |= PPD_STRING; } -@@ -3460,7 +3406,7 @@ ppd_update_filters(ppd_file_t *ppd, /* I - PPD file */ +@@ -3460,7 +3409,7 @@ ppd_update_filters(ppd_file_t *ppd, /* I - PPD file */ filter += ppd->num_filters; ppd->num_filters ++; diff --git a/SOURCES/cups-ppdopen-heap-overflow.patch b/SOURCES/cups-ppdopen-heap-overflow.patch new file mode 100644 index 0000000..4b725e1 --- /dev/null +++ b/SOURCES/cups-ppdopen-heap-overflow.patch @@ -0,0 +1,42 @@ +diff --git a/cups/ppd.c b/cups/ppd.c +index ff52df2e..199cf034 100644 +--- a/cups/ppd.c ++++ b/cups/ppd.c +@@ -1719,8 +1719,7 @@ _ppdOpen( + constraint->choice1, constraint->option2, + constraint->choice2)) + { +- case 0 : /* Error */ +- case 1 : /* Error */ ++ default : /* Error */ + pg->ppd_status = PPD_BAD_UI_CONSTRAINTS; + goto error; + +diff --git a/ppdc/ppdc-source.cxx b/ppdc/ppdc-source.cxx +index c25d4966..236c00db 100644 +--- a/ppdc/ppdc-source.cxx ++++ b/ppdc/ppdc-source.cxx +@@ -1743,15 +1743,17 @@ ppdcSource::get_resolution(ppdcFile *fp)// I - File to read + + switch (sscanf(name, "%dx%d", &xdpi, &ydpi)) + { +- case 0 : +- _cupsLangPrintf(stderr, +- _("ppdc: Bad resolution name \"%s\" on line %d of " +- "%s."), name, fp->line, fp->filename); +- break; + case 1 : + ydpi = xdpi; + break; +- } ++ case 2 : ++ break; ++ default : ++ _cupsLangPrintf(stderr, ++ _("ppdc: Bad resolution name \"%s\" on line %d of " ++ "%s."), name, fp->line, fp->filename); ++ break; ++} + + // Create the necessary PS commands... + snprintf(command, sizeof(command), diff --git a/SOURCES/cups-rastertoepson-crash.patch b/SOURCES/cups-rastertoepson-crash.patch new file mode 100644 index 0000000..11f6673 --- /dev/null +++ b/SOURCES/cups-rastertoepson-crash.patch @@ -0,0 +1,13 @@ +diff --git a/filter/rastertoepson.c b/filter/rastertoepson.c +index 4efe669..e8fe0c6 100644 +--- a/filter/rastertoepson.c ++++ b/filter/rastertoepson.c +@@ -307,7 +307,7 @@ StartPage( + + if (DotBytes) + { +- if ((LineBuffers[0] = calloc((size_t)DotBytes, header->cupsWidth * (size_t)(Shingling + 1))) == NULL) ++ if ((LineBuffers[0] = calloc((size_t)DotBytes, (header->cupsWidth + 7) * (size_t)(Shingling + 1))) == NULL) + { + fputs("ERROR: Unable to allocate memory\n", stderr); + exit(1); diff --git a/SPECS/cups.spec b/SPECS/cups.spec index e7b121a..5110061 100644 --- a/SPECS/cups.spec +++ b/SPECS/cups.spec @@ -15,7 +15,7 @@ Summary: CUPS printing system Name: cups Epoch: 1 Version: 2.2.6 -Release: 33%{?dist} +Release: 38%{?dist} License: GPLv2+ and LGPLv2 with exceptions and AML Url: http://www.cups.org/ Source0: https://github.com/apple/cups/releases/download/v%{VERSION}/cups-%{VERSION}-source.tar.gz @@ -89,6 +89,18 @@ Patch50: cups-do-not-advertise-http-methods.patch Patch51: 0001-Multiple-security-disclosure-issues.patch # 1775668 - cupsd eats a lot of memory when lots of queue with extensive PPDs are created Patch52: cups-memory-consumption.patch +# 1784884 - cups.service doesn't execute automatically on request +Patch53: cups-autostart-when-enabled.patch +# 1825253 - CVE-2020-3898 cups: heap based buffer overflow in libcups's ppdFindOption() in ppd-mark.c +Patch54: cups-ppdopen-heap-overflow.patch +# 1838449 - ipp/socket backends connect to turned off device for eternity (contimeout is not applied) +Patch55: cups-etimedout.patch +# 1689207 - Add failover backend +Patch56: cups-failover-backend.patch +# 1833516 - DirtyCleanInterval ignored if there are open client connections +Patch57: cups-dirtyclean.patch +# 1775590 - rastertoepson filter crashes with paper size A6 +Patch58: cups-rastertoepson-crash.patch Patch100: cups-lspp.patch @@ -321,6 +333,18 @@ Sends IPP requests to the specified URI and tests and/or displays the results. %patch51 -p1 -b .cve-in-scheduler # 1775668 - cupsd eats a lot of memory when lots of queue with extensive PPDs are created %patch52 -p1 -b .memory-consumption +# 1784884 - cups.service doesn't execute automatically on request +%patch53 -p1 -b .autostart-when-enabled +# 1825253 - CVE-2020-3898 cups: heap based buffer overflow in libcups's ppdFindOption() in ppd-mark.c +%patch54 -p1 -b .ppdopen-heap-overflow +# 1838449 - ipp/socket backends connect to turned off device for eternity (contimeout is not applied) +%patch55 -p1 -b .etimedout +# 1689207 - Add failover backend +%patch56 -p1 -b .failover +# 1833516 - DirtyCleanInterval ignored if there are open client connections +%patch57 -p1 -b .dirtyclean +# 1775590 - rastertoepson filter crashes with paper size A6 +%patch58 -p1 -b .rastertoepson-crash sed -i -e '1iMaxLogSize 0' conf/cupsd.conf.in @@ -516,7 +540,12 @@ do done %endif -%{_bindir}/rm /var/cache/cups/*.data +%{_bindir}/rm /var/cache/cups/*.data > /dev/null 2>&1 + +if [ -e /etc/systemd/system/printer.target.wants/cups.service ] +then + %{_bindir}/systemctl enable cups.service > /dev/null 2>&1 +fi exit 0 @@ -726,6 +755,29 @@ rm -f %{cups_serverbin}/backend/smb %{_mandir}/man5/ipptoolfile.5.gz %changelog +* Tue May 26 2020 Zdenek Dohnal - 1:2.2.6-38 +- 1775590 - rastertoepson filter crashes with paper size A6 + +* Mon May 25 2020 Zdenek Dohnal - 1:2.2.6-37 +- forgot to enable optimization - 1833516 + +* Fri May 22 2020 Zdenek Dohnal - 1:2.2.6-36 +- 1838449 - ipp/socket backends connect to turned off device for eternity (contimeout is not applied) +- 1689207 - Add failover backend +- 1833516 - DirtyCleanInterval ignored if there are open client connections + +* Tue Apr 21 2020 Zdenek Dohnal - 1:2.2.6-35 +- 1825254 - CVE-2020-3898 cups: heap based buffer overflow in libcups's ppdFindOption() in ppd-mark.c + +* Mon Apr 20 2020 Zdenek Dohnal - 1:2.2.6-34 +- 1809002 - scriptlet issue, /usr/bin/rm: cannot remove '/var/cache/cups/*.data' + +* Thu Apr 09 2020 Zdenek Dohnal - 1:2.2.6-34 +- 1784884 - cups.service doesn't execute automatically on request + +* Wed Apr 08 2020 Zdenek Dohnal - 1:2.2.6-34 +- 1822135 - _ppdOpen() leaks 'string' variable + * Fri Feb 14 2020 Zdenek Dohnal - 1:2.2.6-33 - fix more memory leaks found by coverity in 1775668