diff --git a/SOURCES/cups-CVE-2014-2856.patch b/SOURCES/cups-CVE-2014-2856.patch new file mode 100644 index 0000000..d72556d --- /dev/null +++ b/SOURCES/cups-CVE-2014-2856.patch @@ -0,0 +1,18 @@ +diff -up cups-1.6.3/scheduler/client.c.CVE-2014-2856 cups-1.6.3/scheduler/client.c +--- cups-1.6.3/scheduler/client.c.CVE-2014-2856 2014-07-25 12:11:48.054960093 +0100 ++++ cups-1.6.3/scheduler/client.c 2014-07-25 12:11:27.764854789 +0100 +@@ -3686,6 +3686,14 @@ is_path_absolute(const char *path) /* I + return (0); + + /* ++ * Check for "<" or quotes in the path and reject since this is probably ++ * someone trying to inject HTML... ++ */ ++ ++ if (strchr(path, '<') != NULL || strchr(path, '\"') != NULL || strchr(path, '\'') != NULL) ++ return (0); ++ ++ /* + * Check for "/.." in the path... + */ + diff --git a/SOURCES/cups-CVE-2014-3537.patch b/SOURCES/cups-CVE-2014-3537.patch new file mode 100644 index 0000000..32bba8f --- /dev/null +++ b/SOURCES/cups-CVE-2014-3537.patch @@ -0,0 +1,48 @@ +diff -up cups-1.6.3/scheduler/client.c.CVE-2014-3537 cups-1.6.3/scheduler/client.c +--- cups-1.6.3/scheduler/client.c.CVE-2014-3537 2014-09-02 11:30:50.021384781 +0100 ++++ cups-1.6.3/scheduler/client.c 2014-09-02 11:31:00.606440125 +0100 +@@ -3197,7 +3197,7 @@ get_file(cupsd_client_t *con, /* I - C + if ((ptr = strchr(filename, '?')) != NULL) + *ptr = '\0'; + +- if ((status = stat(filename, filestats)) != 0) ++ if ((status = lstat(filename, filestats)) != 0) + { + /* + * Drop the language prefix and try the root directory... +@@ -3209,12 +3209,33 @@ get_file(cupsd_client_t *con, /* I - C + if ((ptr = strchr(filename, '?')) != NULL) + *ptr = '\0'; + +- status = stat(filename, filestats); ++ status = lstat(filename, filestats); + } + } + ++ /* ++ * If we've found a symlink, 404 the sucker to avoid disclosing information. ++ */ ++ ++ if (!status && S_ISLNK(filestats->st_mode)) ++ { ++ cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Symlinks such as \"%s\" are not allowed.", con->http.fd, filename); ++ return (NULL); ++ } ++ ++ /* ++ * Similarly, if the file/directory does not have world read permissions, do ++ * not allow access... ++ */ ++ ++ if (!status && !(filestats->st_mode & S_IROTH)) ++ { ++ cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Files/directories such as \"%s\" must be world-readable.", con->http.fd, filename); ++ return (NULL); ++ } ++ + /* +- * If we're found a directory, get the index.html file instead... ++ * If we've found a directory, get the index.html file instead... + */ + + if (!status && S_ISDIR(filestats->st_mode)) diff --git a/SOURCES/cups-CVE-2014-5029-5030-5031.patch b/SOURCES/cups-CVE-2014-5029-5030-5031.patch new file mode 100644 index 0000000..cd595e7 --- /dev/null +++ b/SOURCES/cups-CVE-2014-5029-5030-5031.patch @@ -0,0 +1,88 @@ +diff -up cups-1.6.3/scheduler/client.c.CVE-2014-5029-5030-5031 cups-1.6.3/scheduler/client.c +--- cups-1.6.3/scheduler/client.c.CVE-2014-5029-5030-5031 2014-09-02 11:42:02.465900694 +0100 ++++ cups-1.6.3/scheduler/client.c 2014-09-02 11:42:44.383119863 +0100 +@@ -3180,7 +3180,7 @@ get_file(cupsd_client_t *con, /* I - C + * then fallback to the default one... + */ + +- if ((status = stat(filename, filestats)) != 0 && language[0] && ++ if ((status = lstat(filename, filestats)) != 0 && language[0] && + strncmp(con->uri, "/icons/", 7) && + strncmp(con->uri, "/ppd/", 5) && + strncmp(con->uri, "/rss/", 5) && +@@ -3278,13 +3278,13 @@ get_file(cupsd_client_t *con, /* I - C + plen = len - (ptr - filename); + + strlcpy(ptr, "index.html", plen); +- status = stat(filename, filestats); ++ status = lstat(filename, filestats); + + #ifdef HAVE_JAVA + if (status) + { + strlcpy(ptr, "index.class", plen); +- status = stat(filename, filestats); ++ status = lstat(filename, filestats); + } + #endif /* HAVE_JAVA */ + +@@ -3292,7 +3292,7 @@ get_file(cupsd_client_t *con, /* I - C + if (status) + { + strlcpy(ptr, "index.pl", plen); +- status = stat(filename, filestats); ++ status = lstat(filename, filestats); + } + #endif /* HAVE_PERL */ + +@@ -3300,7 +3300,7 @@ get_file(cupsd_client_t *con, /* I - C + if (status) + { + strlcpy(ptr, "index.php", plen); +- status = stat(filename, filestats); ++ status = lstat(filename, filestats); + } + #endif /* HAVE_PHP */ + +@@ -3308,18 +3308,39 @@ get_file(cupsd_client_t *con, /* I - C + if (status) + { + strlcpy(ptr, "index.pyc", plen); +- status = stat(filename, filestats); ++ status = lstat(filename, filestats); + } + + if (status) + { + strlcpy(ptr, "index.py", plen); +- status = stat(filename, filestats); ++ status = lstat(filename, filestats); + } + #endif /* HAVE_PYTHON */ + + } + while (status && language[0]); ++ ++ /* ++ * If we've found a symlink, 404 the sucker to avoid disclosing information. ++ */ ++ ++ if (!status && S_ISLNK(filestats->st_mode)) ++ { ++ cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Symlinks such as \"%s\" are not allowed.", con->http.fd, filename); ++ return (NULL); ++ } ++ ++ /* ++ * Similarly, if the file/directory does not have world read permissions, do ++ * not allow access... ++ */ ++ ++ if (!status && !(filestats->st_mode & S_IROTH)) ++ { ++ cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Files/directories such as \"%s\" must be world-readable.", con->http.fd, filename); ++ return (NULL); ++ } + } + + cupsdLogMessage(CUPSD_LOG_DEBUG2, diff --git a/SOURCES/cups-colord-interface.patch b/SOURCES/cups-colord-interface.patch new file mode 100644 index 0000000..49057eb --- /dev/null +++ b/SOURCES/cups-colord-interface.patch @@ -0,0 +1,23 @@ +diff -up cups-1.6.3/scheduler/colorman.c.colord-interface cups-1.6.3/scheduler/colorman.c +--- cups-1.6.3/scheduler/colorman.c.colord-interface 2013-06-07 02:12:52.000000000 +0100 ++++ cups-1.6.3/scheduler/colorman.c 2014-09-02 10:47:19.457169176 +0100 +@@ -107,6 +107,10 @@ extern CFUUIDRef ColorSyncCreateUUIDFrom + "org.freedesktop.ColorManager", (p),\ + "org.freedesktop.ColorManager", (m)) + /* Macro to make new colord messages */ ++# define COLORD_DEVICE_DBUS_MSG(p,m) dbus_message_new_method_call( \ ++ "org.freedesktop.ColorManager", (p),\ ++ "org.freedesktop.ColorManager.Device", (m)) ++ /* Macro to make new colord messages */ + # define COLORD_DBUS_PATH "/org/freedesktop/ColorManager" + /* Path for color management system */ + # define COLORD_DBUS_TIMEOUT 5000 /* Timeout for connecting to colord in ms */ +@@ -1196,7 +1200,7 @@ colord_device_add_profile( + DBusError error; /* D-Bus error */ + + +- message = COLORD_DBUS_MSG(device_path, "AddProfile"); ++ message = COLORD_DEVICE_DBUS_MSG(device_path, "AddProfile"); + + dbus_message_iter_init_append(message, &args); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &relation); diff --git a/SOURCES/cups-error-policy-manpage.patch b/SOURCES/cups-error-policy-manpage.patch new file mode 100644 index 0000000..c7528cf --- /dev/null +++ b/SOURCES/cups-error-policy-manpage.patch @@ -0,0 +1,31 @@ +diff -up cups-1.6.3/man/cupsd.conf.man.in.error-policy-manpage cups-1.6.3/man/cupsd.conf.man.in +--- cups-1.6.3/man/cupsd.conf.man.in.error-policy-manpage 2014-09-02 11:23:05.798957567 +0100 ++++ cups-1.6.3/man/cupsd.conf.man.in 2014-09-02 11:24:35.813428214 +0100 +@@ -3,7 +3,7 @@ + .\" + .\" cupsd.conf man page for CUPS. + .\" +-.\" Copyright 2007-2013 by Apple Inc. ++.\" Copyright 2007-2014 by Apple Inc. + .\" Copyright 1997-2006 by Easy Software Products. + .\" + .\" These coded instructions, statements, and computer programs are the +@@ -180,6 +180,18 @@ Encryption Required + Specifies the level of encryption that is required for a particular + location. + .TP 5 ++ErrorPolicy abort-job ++Specifies that a failed print job should be aborted (discarded) unless otherwise specified for the printer. ++.TP 5 ++ErrorPolicy retry-job ++Specifies that a failed print job should be retried at a later time unless otherwise specified for the printer. ++.TP 5 ++ErrorPolicy retry-this-job ++Specifies that a failed print job should be retried immediately unless otherwise specified for the printer. ++.TP 5 ++ErrorPolicy stop-printer ++Specifies that a failed print job should stop the printer unless otherwise specified for the printer. The 'stop-printer' error policy is the default. ++.TP 5 + FilterLimit limit + .br + Specifies the maximum cost of filters that are run concurrently. diff --git a/SOURCES/cups-failover-backend.patch b/SOURCES/cups-failover-backend.patch new file mode 100644 index 0000000..d6182ea --- /dev/null +++ b/SOURCES/cups-failover-backend.patch @@ -0,0 +1,836 @@ +diff -up cups-1.6.3/backend/failover.c.failover-backend cups-1.6.3/backend/failover.c +--- cups-1.6.3/backend/failover.c.failover-backend 2014-10-21 16:58:34.588301166 +0100 ++++ cups-1.6.3/backend/failover.c 2014-10-21 16:58:34.588301166 +0100 +@@ -0,0 +1,799 @@ ++/* ++ * 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" ++ ++/* ++ * 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); ++ ++ if ((rc = check_printer(tmp_device_uri)) == CUPS_BACKEND_OK) ++ { ++ selected_uri = tmp_device_uri; ++ break; ++ } ++ else if (rc == CUPS_BACKEND_AUTH_REQUIRED) { ++ auth_failed_count++; ++ fprintf(stderr, "DEBUG: auth_failed_count = %d\n", auth_failed_count); ++ } ++ 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++; ++ } while ((tmp_device_uri = (char *)cupsArrayNext(printer_array)) != 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 BACKEND_FAILURE if the remote printer is ++ * unable to take the job. ++ */ ++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 = CUPS_BACKEND_OK; /* return code */ ++ char *reason; /* printer state reason */ ++ int i; ++ ++ fprintf(stderr, "DEBUG: Checking printer %s\n",device_uri); ++ ++ if ((rc = get_printer_attributes(device_uri, &attributes)) != CUPS_BACKEND_OK) ++ { ++ fprintf(stderr, "DEBUG: Failed to get attributes from printer: %s\n", ++ device_uri); ++ return (rc); ++ } ++ ++ /* ++ * 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 = CUPS_BACKEND_FAILED; ++ } ++ ++ /* ++ * Check if printer is stopped ++ */ ++ if ((tmp_attribute = ippFindAttribute(attributes, ++ "printer-state", ++ IPP_TAG_ENUM)) != NULL && ++ tmp_attribute->values[0].integer == IPP_PRINTER_STOPPED) ++ { ++ fprintf(stderr, "DEBUG: Printer, %s, stopped.\n", device_uri); ++ ++ rc = CUPS_BACKEND_FAILED; ++ } ++ ++ /* ++ * 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 = CUPS_BACKEND_FAILED; ++ } ++ else if (len > 6 && !strcmp(reason + len - 6, "-error")) ++ { ++ fprintf(stderr, "DEBUG: Printer Supply Error, %s\n", reason); ++ rc = CUPS_BACKEND_FAILED; ++ } ++ } ++ } ++ ++ 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 -up cups-1.6.3/backend/Makefile.failover-backend cups-1.6.3/backend/Makefile +--- cups-1.6.3/backend/Makefile.failover-backend 2014-10-21 16:58:31.298283423 +0100 ++++ cups-1.6.3/backend/Makefile 2014-10-21 16:59:16.972529746 +0100 +@@ -30,6 +30,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 \ +@@ -257,6 +259,13 @@ lpd: lpd.o ../cups/$(LIBCUPS) libbackend + echo Linking $@... + $(CC) $(LDFLAGS) -o lpd lpd.o libbackend.a $(LIBS) + ++# ++# failover ++# ++ ++failover: failover.o ../cups/$(LIBCUPS) libbackend.a ++ echo Linking $@... ++ $(CC) $(LDFLAGS) -o failover failover.o libbackend.a $(LIBS) $(CUPSDLIBS) + + # + # snmp diff --git a/SOURCES/cups-final-content-type.patch b/SOURCES/cups-final-content-type.patch deleted file mode 100644 index 7076e2b..0000000 --- a/SOURCES/cups-final-content-type.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff -up cups-1.6.4/scheduler/job.c.final-content-type cups-1.6.4/scheduler/job.c ---- cups-1.6.4/scheduler/job.c.final-content-type 2013-09-27 16:58:13.934775402 +0100 -+++ cups-1.6.4/scheduler/job.c 2013-09-27 17:00:57.716549576 +0100 -@@ -692,12 +692,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - - if (!job->printer->remote) - { -- for (filter = (mime_filter_t *)cupsArrayLast(filters); -- filter && filter->dst; -- filter = (mime_filter_t *)cupsArrayPrev(filters)) -- if (strcmp(filter->dst->super, "printer") || -- strcmp(filter->dst->type, job->printer->name)) -- break; -+ filter = (mime_filter_t *)cupsArrayLast(filters); - - if (filter && filter->dst) - { diff --git a/SOURCES/cups-nodatadelay.patch b/SOURCES/cups-nodatadelay.patch new file mode 100644 index 0000000..b808a20 --- /dev/null +++ b/SOURCES/cups-nodatadelay.patch @@ -0,0 +1,14 @@ +diff -up cups-1.6.3/scheduler/client.c.nodatadelay cups-1.6.3/scheduler/client.c +--- cups-1.6.3/scheduler/client.c.nodatadelay 2014-09-02 10:50:07.714003098 +0100 ++++ cups-1.6.3/scheduler/client.c 2014-09-02 10:50:30.960118311 +0100 +@@ -2138,7 +2138,9 @@ cupsdReadClient(cupsd_client_t *con) /* + + if (con->http.state != HTTP_POST_SEND) + { +- if ((bytes = httpRead2(HTTP(con), line, sizeof(line))) < 0) ++ if (!httpWait(HTTP(con), 0)) ++ return; ++ else if ((bytes = httpRead2(HTTP(con), line, sizeof(line))) < 0) + { + if (con->http.error && con->http.error != EPIPE) + cupsdLogMessage(CUPSD_LOG_DEBUG, diff --git a/SOURCES/cups-str4380.patch b/SOURCES/cups-str4380.patch new file mode 100644 index 0000000..84753ca --- /dev/null +++ b/SOURCES/cups-str4380.patch @@ -0,0 +1,20 @@ +diff -up cups-1.6.3/cups/dest.c.str4380 cups-1.6.3/cups/dest.c +--- cups-1.6.3/cups/dest.c.str4380 2014-09-02 10:44:24.753303299 +0100 ++++ cups-1.6.3/cups/dest.c 2014-09-02 10:44:24.785303458 +0100 +@@ -951,11 +951,11 @@ cupsEnumDests( + * Get Bonjour-shared printers... + */ + +- data.type = type; +- data.mask = mask; +- data.devices = cupsArrayNew3((cups_array_func_t)cups_dnssd_compare_devices, +- NULL, NULL, 0, NULL, +- (cups_afree_func_t)cups_dnssd_free_device); ++ data.type = type; ++ data.mask = mask; ++ data.cb = cb; ++ data.user_data = user_data; ++ data.devices = cupsArrayNew3((cups_array_func_t)cups_dnssd_compare_devices, NULL, NULL, 0, NULL, (cups_afree_func_t)cups_dnssd_free_device); + + # ifdef HAVE_DNSSD + if (DNSServiceCreateConnection(&data.main_ref) != kDNSServiceErr_NoError) diff --git a/SOURCES/cups-str4440.patch b/SOURCES/cups-str4440.patch new file mode 100644 index 0000000..258d3bc --- /dev/null +++ b/SOURCES/cups-str4440.patch @@ -0,0 +1,13 @@ +diff -up cups-1.6.3/scheduler/client.c.str4440 cups-1.6.3/scheduler/client.c +--- cups-1.6.3/scheduler/client.c.str4440 2014-09-02 11:02:03.363550036 +0100 ++++ cups-1.6.3/scheduler/client.c 2014-09-02 11:02:34.114702446 +0100 +@@ -2075,6 +2075,9 @@ cupsdReadClient(cupsd_client_t *con) /* + * Grab any request data from the connection... + */ + ++ if (!httpWait(HTTP(con), 0)) ++ return; ++ + if ((ipp_state = ippRead(&(con->http), con->request)) == IPP_ERROR) + { + cupsdLogMessage(CUPSD_LOG_ERROR, diff --git a/SOURCES/cups-str4461.patch b/SOURCES/cups-str4461.patch new file mode 100644 index 0000000..5d60d68 --- /dev/null +++ b/SOURCES/cups-str4461.patch @@ -0,0 +1,177 @@ +diff -up cups-1.6.3/notifier/rss.c.str4461 cups-1.6.3/notifier/rss.c +--- cups-1.6.3/notifier/rss.c.str4461 2013-06-07 02:12:52.000000000 +0100 ++++ cups-1.6.3/notifier/rss.c 2014-09-02 12:14:40.911974011 +0100 +@@ -1,27 +1,16 @@ + /* + * "$Id: rss.c 7824 2008-08-01 21:11:55Z mike $" + * +- * RSS notifier for CUPS. ++ * RSS notifier for CUPS. + * +- * Copyright 2007-2012 by Apple Inc. +- * Copyright 2007 by Easy Software Products. ++ * Copyright 2007-2014 by Apple Inc. ++ * Copyright 2007 by Easy Software Products. + * +- * These coded instructions, statements, and computer programs are the +- * property of Apple Inc. and are protected by Federal copyright +- * law. Distribution and use rights are outlined in the file "LICENSE.txt" +- * 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/". +- * +- * Contents: +- * +- * main() - Main entry for the test notifier. +- * compare_rss() - Compare two messages. +- * delete_message() - Free all memory used by a message. +- * load_rss() - Load an existing RSS feed file. +- * new_message() - Create a new RSS message. +- * password_cb() - Return the cached password. +- * save_rss() - Save messages to a RSS file. +- * xml_escape() - Copy a string, escaping &, <, and > as needed. ++ * These coded instructions, statements, and computer programs are the ++ * property of Apple Inc. and are protected by Federal copyright ++ * law. Distribution and use rights are outlined in the file "LICENSE.txt" ++ * 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/". + */ + + /* +@@ -29,6 +18,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -629,6 +619,8 @@ save_rss(cups_array_t *rss, /* I - RSS + return (0); + } + ++ fchmod(fileno(fp), 0644); ++ + fputs("\n", fp); + fputs("\n", fp); + fputs(" \n", fp); +diff -up cups-1.6.3/scheduler/client.c.str4461 cups-1.6.3/scheduler/client.c +--- cups-1.6.3/scheduler/client.c.str4461 2014-09-02 12:12:39.165354482 +0100 ++++ cups-1.6.3/scheduler/client.c 2014-09-02 12:13:49.131710518 +0100 +@@ -3133,6 +3133,7 @@ get_file(cupsd_client_t *con, /* I - C + char *ptr; /* Pointer info filename */ + int plen; /* Remaining length after pointer */ + char language[7]; /* Language subdirectory, if any */ ++ int perm_check = 1; /* Do permissions check? */ + + + /* +@@ -3142,17 +3143,27 @@ get_file(cupsd_client_t *con, /* I - C + language[0] = '\0'; + + if (!strncmp(con->uri, "/ppd/", 5) && !strchr(con->uri + 5, '/')) ++ { + snprintf(filename, len, "%s%s", ServerRoot, con->uri); ++ ++ perm_check = 0; ++ } + else if (!strncmp(con->uri, "/icons/", 7) && !strchr(con->uri + 7, '/')) + { + snprintf(filename, len, "%s/%s", CacheDir, con->uri + 7); + if (access(filename, F_OK) < 0) + snprintf(filename, len, "%s/images/generic.png", DocumentRoot); ++ ++ perm_check = 0; + } + else if (!strncmp(con->uri, "/rss/", 5) && !strchr(con->uri + 5, '/')) + snprintf(filename, len, "%s/rss/%s", CacheDir, con->uri + 5); +- else if (!strncmp(con->uri, "/admin/conf/", 12)) +- snprintf(filename, len, "%s%s", ServerRoot, con->uri + 11); ++ else if (!strcmp(con->uri, "/admin/conf/cupsd.conf")) ++ { ++ strlcpy(filename, ConfigurationFile, len); ++ ++ perm_check = 0; ++ } + else if (!strncmp(con->uri, "/admin/log/", 11)) + { + if (!strncmp(con->uri + 11, "access_log", 10) && AccessLog[0] == '/') +@@ -3163,6 +3174,8 @@ get_file(cupsd_client_t *con, /* I - C + strlcpy(filename, PageLog, len); + else + return (NULL); ++ ++ perm_check = 0; + } + else if (con->language) + { +@@ -3228,7 +3241,7 @@ get_file(cupsd_client_t *con, /* I - C + * not allow access... + */ + +- if (!status && !(filestats->st_mode & S_IROTH)) ++ if (!status && perm_check && !(filestats->st_mode & S_IROTH)) + { + cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Files/directories such as \"%s\" must be world-readable.", con->http.fd, filename); + return (NULL); +@@ -3336,7 +3349,7 @@ get_file(cupsd_client_t *con, /* I - C + * not allow access... + */ + +- if (!status && !(filestats->st_mode & S_IROTH)) ++ if (!status && perm_check && !(filestats->st_mode & S_IROTH)) + { + cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Files/directories such as \"%s\" must be world-readable.", con->http.fd, filename); + return (NULL); +diff -up cups-1.6.3/scheduler/conf.c.str4461 cups-1.6.3/scheduler/conf.c +--- cups-1.6.3/scheduler/conf.c.str4461 2014-09-02 12:12:39.143354370 +0100 ++++ cups-1.6.3/scheduler/conf.c 2014-09-02 12:12:39.169354502 +0100 +@@ -1116,7 +1116,7 @@ cupsdReadConfiguration(void) + + if ((cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser, + Group, 1, 1) < 0 || +- cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser, ++ cupsdCheckPermissions(CacheDir, NULL, 0770, RunUser, + Group, 1, 1) < 0 || + cupsdCheckPermissions(temp, NULL, 0775, RunUser, + Group, 1, 1) < 0 || +diff -up cups-1.6.3/scheduler/ipp.c.str4461 cups-1.6.3/scheduler/ipp.c +--- cups-1.6.3/scheduler/ipp.c.str4461 2014-09-02 12:12:39.150354405 +0100 ++++ cups-1.6.3/scheduler/ipp.c 2014-09-02 12:12:57.752449066 +0100 +@@ -2777,7 +2777,6 @@ add_printer(cupsd_client_t *con, /* I - + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Copied PPD file successfully"); +- chmod(dstfile, 0644); + } + else + { +@@ -4726,7 +4725,7 @@ copy_model(cupsd_client_t *con, /* I - + * Open the destination file for a copy... + */ + +- if ((dst = cupsFileOpen(to, "wb")) == NULL) ++ if ((dst = cupsdCreateConfFile(to, ConfigFilePerm)) == NULL) + { + cupsFreeOptions(num_defaults, defaults); + cupsFileClose(src); +@@ -4781,7 +4780,7 @@ copy_model(cupsd_client_t *con, /* I - + + unlink(tempfile); + +- return (cupsFileClose(dst)); ++ return (cupsdCloseCreatedConfFile(dst, to)); + } + + +diff -up cups-1.6.3/scheduler/Makefile.str4461 cups-1.6.3/scheduler/Makefile +--- cups-1.6.3/scheduler/Makefile.str4461 2014-09-02 12:12:39.171354512 +0100 ++++ cups-1.6.3/scheduler/Makefile 2014-09-02 12:14:04.265787530 +0100 +@@ -174,7 +174,7 @@ install-data: + echo Creating $(REQUESTS)/tmp... + $(INSTALL_DIR) -m 1770 -g $(CUPS_GROUP) $(REQUESTS)/tmp + echo Creating $(CACHEDIR)... +- $(INSTALL_DIR) -m 775 -g $(CUPS_GROUP) $(CACHEDIR) ++ $(INSTALL_DIR) -m 770 -g $(CUPS_GROUP) $(CACHEDIR) + if test "x$(INITDIR)" != x; then \ + echo Installing init scripts...; \ + $(INSTALL_DIR) -m 755 $(BUILDROOT)$(INITDIR)/init.d; \ diff --git a/SOURCES/cups-str4475.patch b/SOURCES/cups-str4475.patch new file mode 100644 index 0000000..aa1da28 --- /dev/null +++ b/SOURCES/cups-str4475.patch @@ -0,0 +1,24 @@ +diff -up cups-1.6.3/cgi-bin/admin.c.str4475 cups-1.6.3/cgi-bin/admin.c +--- cups-1.6.3/cgi-bin/admin.c.str4475 2014-09-02 12:09:43.875462488 +0100 ++++ cups-1.6.3/cgi-bin/admin.c 2014-09-02 12:09:48.883487972 +0100 +@@ -1917,7 +1917,7 @@ do_config_server(http_t *http) /* I - H + } + else + { +- cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect"); ++ cgiSetVariable("refresh_page", "5;URL=/admin/"); + + cgiStartHTML(cgiText(_("Edit Configuration File"))); + cgiCopyTemplateLang("restart.tmpl"); +diff -up cups-1.6.3/templates/restart.tmpl.str4475 cups-1.6.3/templates/restart.tmpl +--- cups-1.6.3/templates/restart.tmpl.str4475 2008-10-08 23:50:16.000000000 +0100 ++++ cups-1.6.3/templates/restart.tmpl 2014-09-02 12:09:48.883487972 +0100 +@@ -2,7 +2,7 @@ + +

Change Settings

+ +-

Busy Indicator Please stand by while the server restarts...

+ + diff --git a/SOURCES/cups-str4500.patch b/SOURCES/cups-str4500.patch new file mode 100644 index 0000000..cabe572 --- /dev/null +++ b/SOURCES/cups-str4500.patch @@ -0,0 +1,16 @@ +diff -up cups-2.0.0/cups/util.c.str4500 cups-2.0.0/cups/util.c +--- cups-2.0.0/cups/util.c.str4500 2014-10-15 12:59:27.105942488 +0100 ++++ cups-2.0.0/cups/util.c 2014-10-15 13:03:38.618187112 +0100 +@@ -846,10 +846,10 @@ cupsGetPPD3(http_t *http, /* I - H + + snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", cg->cups_serverroot, + name); +- if (!stat(ppdname, &ppdinfo)) ++ if (!stat(ppdname, &ppdinfo) && !access(ppdname, R_OK)) + { + /* +- * OK, the file exists, use it! ++ * OK, the file exists and is readable, use it! + */ + + if (buffer[0]) diff --git a/SOURCES/cups-systemd-socket.patch b/SOURCES/cups-systemd-socket.patch index a57f462..ff03f7c 100644 --- a/SOURCES/cups-systemd-socket.patch +++ b/SOURCES/cups-systemd-socket.patch @@ -103,9 +103,10 @@ diff -up cups-1.6.2/data/cups.path.in.systemd-socket cups-1.6.2/data/cups.path.i diff -up cups-1.6.2/data/cups.service.in.systemd-socket cups-1.6.2/data/cups.service.in --- cups-1.6.2/data/cups.service.in.systemd-socket 2013-03-18 18:53:53.770961616 +0100 +++ cups-1.6.2/data/cups.service.in 2013-03-18 18:53:53.770961616 +0100 -@@ -0,0 +1,10 @@ +@@ -0,0 +1,11 @@ +[Unit] +Description=CUPS Printing Service ++After=network.target + +[Service] +ExecStart=@sbindir@/cupsd -f diff --git a/SPECS/cups.spec b/SPECS/cups.spec index 1d1f46b..f158364 100644 --- a/SPECS/cups.spec +++ b/SPECS/cups.spec @@ -11,7 +11,7 @@ Summary: CUPS printing system Name: cups Epoch: 1 Version: 1.6.3 -Release: 14%{?dist} +Release: 17%{?dist} License: GPLv2 Group: System Environment/Daemons Url: http://www.cups.org/ @@ -67,23 +67,30 @@ Patch36: cups-ipp-multifile.patch Patch37: cups-full-relro.patch Patch38: cups-web-devices-timeout.patch Patch39: cups-synconclose.patch -Patch40: cups-final-content-type.patch +Patch40: cups-str4500.patch Patch41: cups-dbus-notifier.patch Patch42: cups-usb-timeout.patch Patch43: cups-str4326.patch Patch44: cups-str4327.patch +Patch45: cups-CVE-2014-2856.patch +Patch46: cups-str4380.patch +Patch47: cups-colord-interface.patch +Patch48: cups-nodatadelay.patch +Patch49: cups-str4440.patch +Patch50: cups-error-policy-manpage.patch +Patch51: cups-CVE-2014-3537.patch +Patch52: cups-CVE-2014-5029-5030-5031.patch +Patch53: cups-str4461.patch +Patch54: cups-str4475.patch +Patch55: cups-failover-backend.patch Patch100: cups-lspp.patch -Requires: /sbin/chkconfig Requires: %{name}-filesystem = %{epoch}:%{version}-%{release} Requires: %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} -%if %use_alternatives -Provides: /usr/bin/lpq /usr/bin/lpr /usr/bin/lp /usr/bin/cancel /usr/bin/lprm /usr/bin/lpstat -Requires: /usr/sbin/alternatives -%endif +Requires: %{name}-client%{?_isa} = %{epoch}:%{version}-%{release} -Provides: lpd lpr cupsddk cupsddk-drivers +Provides: cupsddk cupsddk-drivers BuildRequires: pam-devel pkgconfig BuildRequires: openssl-devel libacl-devel @@ -120,6 +127,17 @@ Requires: acl # Make sure we have some filters for converting to raster format. Requires: ghostscript-cups +%package client +Summary: CUPS printing system - client programs +Group: System Environment/Daemons +License: GPLv2 +Requires: %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} +%if %use_alternatives +Provides: /usr/bin/lpq /usr/bin/lpr /usr/bin/lp /usr/bin/cancel /usr/bin/lprm /usr/bin/lpstat +Requires: /usr/sbin/alternatives +%endif +Provides: lpr + %package devel Summary: CUPS printing system - development environment Group: Development/Libraries @@ -144,8 +162,9 @@ Requires: cups-filters %package lpd Summary: CUPS printing system - lpd emulation Group: System Environment/Daemons -Requires: %{name} = %{epoch}:%{version}-%{release} +Requires: %{name}%{?_isa} = %{epoch}:%{version}-%{release} Requires: %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} +Provides: lpd %package ipptool Summary: CUPS printing system - tool for performing IPP requests @@ -158,6 +177,11 @@ UNIX® operating systems. It has been developed by Apple Inc. to promote a standard printing solution for all UNIX vendors and users. CUPS provides the System V and Berkeley command-line interfaces. +%description client +CUPS printing system provides a portable printing layer for +UNIX® operating systems. This package contains command-line client +programs. + %description devel CUPS printing system provides a portable printing layer for UNIX® operating systems. This is the development package for creating @@ -265,9 +289,9 @@ Sends IPP requests to the specified URI and tests and/or displays the results. %patch38 -p1 -b .web-devices-timeout # Add SyncOnClose option (bug #984883). %patch39 -p1 -b .synconclose -# Reverted upstream change to FINAL_CONTENT_TYPE in order to fix -# printing to remote CUPS servers (bug #1013040). -%patch40 -p1 -b .final-content-type +# Fix cupsGetPPD3() so it doesn't give the caller an unreadable file +# (part of fix for CVE-2014-5031, STR #4500). +%patch40 -p1 -b .str4500 # Avoid stale lockfile in dbus notifier (bug #1030666). %patch41 -p1 -b .dbus-notifier # Prevent USB timeouts causing incorrect print output (bug #1036057). @@ -276,6 +300,32 @@ Sends IPP requests to the specified URI and tests and/or displays the results. %patch43 -p1 -b .str4326 # Apply upstream patch to improve cupsUser() (bug #1046845). %patch44 -p1 -b .str4327 +# Apply upstream patch to fix cross-site scripting flaw (CVE-2014-2856, +# bug #1087122). +%patch45 -p1 -b .CVE-2014-2856 +# Fix for cupsEnumDest() 'removed' callbacks (bug #1072954, STR #4380). +%patch46 -p1 -b .str4380 +# Use colord interface correctly (bug #1087323). +%patch47 -p1 -b .colord-interface +# Apply upstream patch to avoid 10 second timeouts in cupsd caused by +# reading when no data ready (bug #1110259). +%patch48 -p1 -b .nodatadelay +# Avoid race condition in cupsdReadClient() (bug #1113045). +%patch49 -p1 -b .str4440 +# Describe ErrorPolicy in the cupsd.conf man page (bug #1120591). +%patch50 -p1 -b .error-policy-manpage +# Apply upstream patch to fix privilege escalation due to insufficient +# checking (CVE-2014-3537, bug #1115576). +%patch51 -p1 -b .CVE-2014-3537 +# Apply upstream patch to fix CVE-2014-5029 (bug #1122600), +# CVE-2014-5030 (bug #1128764), CVE-2014-5031 (bug #1128767). +%patch52 -p1 -b .CVE-2014-5029-5030-5031 +# Fix conf/log file reading for authenticated users (STR #4461). +%patch53 -p1 -b .str4461 +# Fix icon display in web interface during server restart (STR #4475). +%patch54 -p1 -b .str4475 +# Support for failover without load-balancing (bug #1115219). +%patch55 -p1 -b .failover-backend %if %lspp # LSPP support. @@ -407,23 +457,7 @@ s:.*\('%{_datadir}'/\)\([^/_]\+\)\(.*\.po$\):%lang(\2) \1\2\3: # Remove old-style certs directory; new-style is /var/run # (see bug #194581 for why this is necessary). -/bin/rm -rf %{_sysconfdir}/cups/certs -%if %use_alternatives -/usr/sbin/alternatives --install %{_bindir}/lpr print %{_bindir}/lpr.cups 40 \ - --slave %{_bindir}/lp print-lp %{_bindir}/lp.cups \ - --slave %{_bindir}/lpq print-lpq %{_bindir}/lpq.cups \ - --slave %{_bindir}/lprm print-lprm %{_bindir}/lprm.cups \ - --slave %{_bindir}/lpstat print-lpstat %{_bindir}/lpstat.cups \ - --slave %{_bindir}/cancel print-cancel %{_bindir}/cancel.cups \ - --slave %{_sbindir}/lpc print-lpc %{_sbindir}/lpc.cups \ - --slave %{_mandir}/man1/cancel.1.gz print-cancelman %{_mandir}/man1/cancel-cups.1.gz \ - --slave %{_mandir}/man1/lp.1.gz print-lpman %{_mandir}/man1/lp-cups.1.gz \ - --slave %{_mandir}/man8/lpc.8.gz print-lpcman %{_mandir}/man8/lpc-cups.8.gz \ - --slave %{_mandir}/man1/lpq.1.gz print-lpqman %{_mandir}/man1/lpq-cups.1.gz \ - --slave %{_mandir}/man1/lpr.1.gz print-lprman %{_mandir}/man1/lpr-cups.1.gz \ - --slave %{_mandir}/man1/lprm.1.gz print-lprmman %{_mandir}/man1/lprm-cups.1.gz \ - --slave %{_mandir}/man1/lpstat.1.gz print-lpstatman %{_mandir}/man1/lpstat-cups.1.gz -%endif +rm -rf %{_sysconfdir}/cups/certs rm -f %{_localstatedir}/cache/cups/*.ipp %{_localstatedir}/cache/cups/*.cache # Deal with config migration due to CVE-2012-5519 (STR #4223) @@ -465,6 +499,25 @@ done exit 0 +%post client +%if %use_alternatives +/usr/sbin/alternatives --install %{_bindir}/lpr print %{_bindir}/lpr.cups 40 \ + --slave %{_bindir}/lp print-lp %{_bindir}/lp.cups \ + --slave %{_bindir}/lpq print-lpq %{_bindir}/lpq.cups \ + --slave %{_bindir}/lprm print-lprm %{_bindir}/lprm.cups \ + --slave %{_bindir}/lpstat print-lpstat %{_bindir}/lpstat.cups \ + --slave %{_bindir}/cancel print-cancel %{_bindir}/cancel.cups \ + --slave %{_sbindir}/lpc print-lpc %{_sbindir}/lpc.cups \ + --slave %{_mandir}/man1/cancel.1.gz print-cancelman %{_mandir}/man1/cancel-cups.1.gz \ + --slave %{_mandir}/man1/lp.1.gz print-lpman %{_mandir}/man1/lp-cups.1.gz \ + --slave %{_mandir}/man8/lpc.8.gz print-lpcman %{_mandir}/man8/lpc-cups.8.gz \ + --slave %{_mandir}/man1/lpq.1.gz print-lpqman %{_mandir}/man1/lpq-cups.1.gz \ + --slave %{_mandir}/man1/lpr.1.gz print-lprman %{_mandir}/man1/lpr-cups.1.gz \ + --slave %{_mandir}/man1/lprm.1.gz print-lprmman %{_mandir}/man1/lprm-cups.1.gz \ + --slave %{_mandir}/man1/lpstat.1.gz print-lpstatman %{_mandir}/man1/lpstat-cups.1.gz +%endif +exit 0 + %post lpd %systemd_post cups-lpd.socket exit 0 @@ -475,13 +528,14 @@ exit 0 %preun %systemd_preun %{name}.path %{name}.socket %{name}.service +exit 0 +%preun client %if %use_alternatives if [ $1 -eq 0 ] ; then /usr/sbin/alternatives --remove print %{_bindir}/lpr.cups fi %endif - exit 0 %preun lpd @@ -575,8 +629,6 @@ rm -f %{cups_serverbin}/backend/smb %{_unitdir}/%{name}.path %{_bindir}/cupstestppd %{_bindir}/cupstestdsc -%{_bindir}/cancel* -%{_bindir}/lp* %{_bindir}/ppd* %{cups_serverbin}/backend/* %{cups_serverbin}/cgi-bin @@ -588,6 +640,10 @@ rm -f %{cups_serverbin}/backend/smb %{cups_serverbin}/filter/* %{cups_serverbin}/monitor %{_mandir}/man[1578]/* +# client subpackage +%exclude %{_mandir}/man1/lp*.1.gz +%exclude %{_mandir}/man1/cancel-cups.1.gz +%exclude %{_mandir}/man8/lpc-cups.8.gz # devel subpackage %exclude %{_mandir}/man1/cups-config.1.gz # ipptool subpackage @@ -596,6 +652,8 @@ rm -f %{cups_serverbin}/backend/smb # lpd subpackage %exclude %{_mandir}/man8/cups-lpd.8.gz %{_sbindir}/* +# client subpackage +%exclude %{_sbindir}/lpc.cups %dir %{_datadir}/cups/templates %dir %{_datadir}/cups/templates/ca %dir %{_datadir}/cups/templates/cs @@ -622,6 +680,14 @@ rm -f %{cups_serverbin}/backend/smb %{_datadir}/cups/ppdc/*.defs %{_datadir}/cups/ppdc/*.h +%files client +%{_sbindir}/lpc.cups +%{_bindir}/cancel* +%{_bindir}/lp* +%{_mandir}/man1/lp*.1.gz +%{_mandir}/man1/cancel-cups.1.gz +%{_mandir}/man8/lpc-cups.8.gz + %files libs %doc LICENSE.txt %{_libdir}/*.so.* @@ -664,6 +730,36 @@ rm -f %{cups_serverbin}/backend/smb %{_mandir}/man5/ipptoolfile.5.gz %changelog +* Tue Oct 21 2014 Tim Waugh - 1:1.6.3-17 +- Support for failover without load-balancing (bug #1115219). +- Fix cupsGetPPD3() so it doesn't give the caller an unreadable file + (part of fix for CVE-2014-5031, STR #4500). +- Can no longer reproduce bug #1010580 so removing final-content-type + patch as it causes issues for some backends (bug #1149245). +- Start cups.service after network.target (bug #1144780). + +* Tue Sep 2 2014 Tim Waugh - 1:1.6.3-16 +- Apply upstream patch to fix CVE-2014-5029 (bug #1122600), + CVE-2014-5030 (bug #1128764), CVE-2014-5031 (bug #1128767). Also: + - Fix conf/log file reading for authenticated users (STR #4461). + - Fix icon display in web interface during server restart (STR #4475). +- Apply upstream patch to fix privilege escalation due to insufficient + checking (CVE-2014-3537, bug #1115576). +- Describe ErrorPolicy in the cupsd.conf man page (bug #1120591). +- Reduce package dependencies (bug #1115057): + - New client subpackage containing command line client tools. + - Removed 'Requires: /sbin/chkconfig'. + - Moved 'Provides: lpd' to lpd subpackage. +- Avoid race condition in cupsdReadClient() (bug #1113045). +- Apply upstream patch to avoid 10 second timeouts in cupsd caused by + reading when no data ready (bug #1110259). +- Use colord interface correctly (bug #1087323). +- Fix for cupsEnumDest() 'removed' callbacks (bug #1072954, STR #4380). + +* Fri Jul 25 2014 Tim Waugh - 1:1.6.3-15 +- Apply upstream patch to fix cross-site scripting flaw (CVE-2014-2856, + bug #1087122). + * Fri Jan 24 2014 Daniel Mach - 1:1.6.3-14 - Mass rebuild 2014-01-24