diff --git a/backport-Retry-Validate-Job-once-if-needed-Issue-132.patch b/backport-Retry-Validate-Job-once-if-needed-Issue-132.patch deleted file mode 100644 index a677090..0000000 --- a/backport-Retry-Validate-Job-once-if-needed-Issue-132.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 6e6999b1f74457b7fd6057a31f1d3606de19a05b Mon Sep 17 00:00:00 2001 -From: Michael R Sweet -Date: Fri, 9 Apr 2021 10:20:04 -0400 -Subject: [PATCH] Retry Validate-Job once, if needed (Issue #132) - ---- - CHANGES.md | 1 + - backend/ipp.c | 14 +++++++++++++- - 2 files changed, 14 insertions(+), 1 deletion(-) - -diff --git a/backend/ipp.c b/backend/ipp.c -index 63353a66d..020ab7fd4 100644 ---- a/backend/ipp.c -+++ b/backend/ipp.c -@@ -256,6 +257,7 @@ main(int argc, /* I - Number of command-line args */ - get_job_attrs = 0, /* Does printer support Get-Job-Attributes? */ - send_document = 0, /* Does printer support Send-Document? */ - validate_job = 0, /* Does printer support Validate-Job? */ -+ validate_retried = 0, /* Was Validate-Job request retried? */ - copies, /* Number of copies for job */ - copies_remaining; /* Number of copies remaining */ - const char *content_type, /* CONTENT_TYPE environment variable */ -@@ -1559,7 +1561,17 @@ main(int argc, /* I - Number of command-line args */ - ipp_status == IPP_STATUS_ERROR_BAD_REQUEST) - break; - else if (job_auth == NULL && ipp_status > IPP_STATUS_ERROR_BAD_REQUEST) -+ { -+ if (!validate_retried) -+ { -+ // Retry Validate-Job operation once, to work around known printer bug... -+ validate_retried = 1; -+ sleep(10); -+ continue; -+ } -+ - goto cleanup; -+ } - } - - /* --- -2.26.3 - diff --git a/backport-backend-usb-libusb.c-Use-60s-timeout-for-reading-at-.patch b/backport-backend-usb-libusb.c-Use-60s-timeout-for-reading-at-.patch deleted file mode 100644 index 71ccba9..0000000 --- a/backport-backend-usb-libusb.c-Use-60s-timeout-for-reading-at-.patch +++ /dev/null @@ -1,28 +0,0 @@ -From c37d71b1a31d26a4790166e2508822b18934a5c0 Mon Sep 17 00:00:00 2001 -From: Zdenek Dohnal -Date: Tue, 13 Apr 2021 15:44:14 +0200 -Subject: [PATCH] backend/usb-libusb.c: Use 60s timeout for reading at - backchannel - -Some older models malfunction if timeout is too short. ---- - CHANGES.md | 1 + - backend/usb-libusb.c | 2 +- - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/backend/usb-libusb.c b/backend/usb-libusb.c -index d6b0eb423..fbb0d9d89 100644 ---- a/backend/usb-libusb.c -+++ b/backend/usb-libusb.c -@@ -1704,7 +1704,7 @@ static void *read_thread(void *reference) - readstatus = libusb_bulk_transfer(g.printer->handle, - g.printer->read_endp, - readbuffer, rbytes, -- &rbytes, 250); -+ &rbytes, 60000); - if (readstatus == LIBUSB_SUCCESS && rbytes > 0) - { - fprintf(stderr, "DEBUG: Read %d bytes of back-channel data...\n", (int)rbytes); --- -2.26.3 - diff --git a/backport-cgi-bin-ipp-var.c-Use-guest-user-for-Move-Job-when-n.patch b/backport-cgi-bin-ipp-var.c-Use-guest-user-for-Move-Job-when-n.patch deleted file mode 100644 index d2c0716..0000000 --- a/backport-cgi-bin-ipp-var.c-Use-guest-user-for-Move-Job-when-n.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/cgi-bin/ipp-var.c b/cgi-bin/ipp-var.c -index 92f1501..7edc058 100644 ---- a/cgi-bin/ipp-var.c -+++ b/cgi-bin/ipp-var.c -@@ -275,10 +275,7 @@ cgiMoveJobs(http_t *http, /* I - Connection to server */ - */ - - if ((user = getenv("REMOTE_USER")) == NULL) -- { -- puts("Status: 401\n"); -- exit(0); -- } -+ user = "guest"; - - /* - * See if the user has already selected a new destination... diff --git a/backport-cups-md5passwd.c-Stub-out-httpMD5-functions.patch b/backport-cups-md5passwd.c-Stub-out-httpMD5-functions.patch deleted file mode 100644 index 0acd3a5..0000000 --- a/backport-cups-md5passwd.c-Stub-out-httpMD5-functions.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 3e217bff90829cf7d53ceacb553a7abaad3cb4db Mon Sep 17 00:00:00 2001 -From: Zdenek Dohnal -Date: Thu, 26 Aug 2021 15:45:40 +0200 -Subject: [PATCH] cups/md5passwd.c: Stub out httpMD5* functions - ---- - CHANGES.md | 1 + - cups/md5passwd.c | 60 +++++++++++++++++++----------------------------- - 2 files changed, 25 insertions(+), 36 deletions(-) - -diff --git a/cups/md5passwd.c b/cups/md5passwd.c -index 9af5de23c..5c9a64e06 100644 ---- a/cups/md5passwd.c -+++ b/cups/md5passwd.c -@@ -19,6 +19,9 @@ - /* - * 'httpMD5()' - Compute the MD5 sum of the username:group:password. - * -+ * The function was used for HTTP Digest authentication. Since CUPS 2.4.0 -+ * it produces an empty string. Please use @link cupsDoAuthentication@ instead. -+ * - * @deprecated@ - */ - -@@ -28,22 +31,13 @@ httpMD5(const char *username, /* I - User name */ - const char *passwd, /* I - Password string */ - char md5[33]) /* O - MD5 string */ - { -- unsigned char sum[16]; /* Sum data */ -- char line[256]; /* Line to sum */ -- -- -- /* -- * Compute the MD5 sum of the user name, group name, and password. -- */ -+ (void)username; -+ (void)realm; -+ (void)passwd; - -- snprintf(line, sizeof(line), "%s:%s:%s", username, realm, passwd); -- cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); -+ md5[0] = '\0'; - -- /* -- * Return the sum... -- */ -- -- return ((char *)cupsHashString(sum, sizeof(sum), md5, 33)); -+ return (NULL); - } - - -@@ -52,6 +46,9 @@ httpMD5(const char *username, /* I - User name */ - * with the server-supplied nonce value, method, and - * request-uri. - * -+ * The function was used for HTTP Digest authentication. Since CUPS 2.4.0 -+ * it produces an empty string. Please use @link cupsDoAuthentication@ instead. -+ * - * @deprecated@ - */ - -@@ -61,35 +58,22 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ - const char *resource, /* I - Resource path */ - char md5[33]) /* IO - MD5 sum */ - { -- unsigned char sum[16]; /* Sum data */ -- char line[1024]; /* Line of data */ -- char a2[33]; /* Hash of method and resource */ -- -+ (void)nonce; -+ (void)method; -+ (void)resource; - -- /* -- * First compute the MD5 sum of the method and resource... -- */ -+ md5[0] = '\0'; - -- snprintf(line, sizeof(line), "%s:%s", method, resource); -- cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); -- cupsHashString(sum, sizeof(sum), a2, sizeof(a2)); -- -- /* -- * Then combine A1 (MD5 of username, realm, and password) with the nonce -- * and A2 (method + resource) values to get the final MD5 sum for the -- * request... -- */ -- -- snprintf(line, sizeof(line), "%s:%s:%s", md5, nonce, a2); -- cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); -- -- return ((char *)cupsHashString(sum, sizeof(sum), md5, 33)); -+ return (NULL); - } - - - /* - * 'httpMD5String()' - Convert an MD5 sum to a character string. - * -+ * The function was used for HTTP Digest authentication. Since CUPS 2.4.0 -+ * it produces an empty string. Please use @link cupsDoAuthentication@ instead. -+ * - * @deprecated@ - */ - -@@ -98,5 +82,9 @@ httpMD5String(const unsigned char *sum, /* I - MD5 sum data */ - char md5[33]) - /* O - MD5 sum in hex */ - { -- return ((char *)cupsHashString(sum, 16, md5, 33)); -+ (void)sum; -+ -+ md5[0] = '\0'; -+ -+ return (NULL); - } --- -2.31.1 - diff --git a/backport-cups.service.in-Add-SYSTEMD_WANTED_BY-variable.patch b/backport-cups.service.in-Add-SYSTEMD_WANTED_BY-variable.patch deleted file mode 100644 index 8282477..0000000 --- a/backport-cups.service.in-Add-SYSTEMD_WANTED_BY-variable.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/config-scripts/cups-defaults.m4 b/config-scripts/cups-defaults.m4 -index 9e05bd4..505d272 100644 ---- a/config-scripts/cups-defaults.m4 -+++ b/config-scripts/cups-defaults.m4 -@@ -8,6 +8,9 @@ dnl Licensed under Apache License v2.0. See the file "LICENSE" for more - dnl information. - dnl - -+dnl Set a default systemd WantedBy directive -+SYSTEMD_WANTED_BY="printers.target" -+ - dnl Default languages... - LANGUAGES="`ls -1 locale/cups_*.po 2>/dev/null | sed -e '1,$s/locale\/cups_//' -e '1,$s/\.po//' | tr '\n' ' '`" - -@@ -461,3 +464,8 @@ esac - - AC_SUBST(CUPS_WEBIF) - AC_DEFINE_UNQUOTED(CUPS_DEFAULT_WEBIF, $CUPS_DEFAULT_WEBIF) -+ -+AS_IF([test $CUPS_WEBIF = Yes || test $CUPS_BROWSING = Yes], [ -+ SYSTEMD_WANTED_BY="$SYSTEMD_WANTED_BY multi-user.target"], [ -+ ]) -+AC_SUBST([SYSTEMD_WANTED_BY]) -diff --git a/scheduler/cups.service.in b/scheduler/cups.service.in -index baff51b..f0d7e2f 100644 ---- a/scheduler/cups.service.in -+++ b/scheduler/cups.service.in -@@ -11,4 +11,4 @@ Restart=on-failure - - [Install] - Also=cups.socket cups.path --WantedBy=printer.target -+WantedBy=@SYSTEMD_WANTED_BY@ diff --git a/backport-scheduler-job.c-use-gziptoany-for-raw-files-not-just.patch b/backport-scheduler-job.c-use-gziptoany-for-raw-files-not-just.patch deleted file mode 100644 index 025361f..0000000 --- a/backport-scheduler-job.c-use-gziptoany-for-raw-files-not-just.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 08e9b6e1f8497a8159d6bd7cd6dc96ae79a2e704 Mon Sep 17 00:00:00 2001 -From: Bryan Mason -Date: Thu, 15 Jul 2021 16:26:27 -0700 -Subject: [PATCH] scheduler/job.c: use gziptoany for raw files (not just raw - printers) - ---- - scheduler/job.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/scheduler/job.c b/scheduler/job.c -index d8c2efcc6..b448acda5 100644 ---- a/scheduler/job.c -+++ b/scheduler/job.c -@@ -501,6 +501,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ - int backroot; /* Run backend as root? */ - int pid; /* Process ID of new filter process */ - int banner_page; /* 1 if banner page, 0 otherwise */ -+ int raw_file; /* 1 if file type is vnd.cups-raw */ - int filterfds[2][2] = { { -1, -1 }, { -1, -1 } }; - /* Pipes used between filters */ - int envc; /* Number of environment variables */ -@@ -746,8 +747,11 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ - * Add decompression/raw filter as needed... - */ - -+ raw_file = !strcmp(job->filetypes[job->current_file]->super, "application") && -+ !strcmp(job->filetypes[job->current_file]->type, "vnd.cups-raw"); -+ - if ((job->compressions[job->current_file] && (!job->printer->remote || job->num_files == 1)) || -- (!job->printer->remote && job->printer->raw && job->num_files > 1)) -+ (!job->printer->remote && (job->printer->raw || raw_file) && job->num_files > 1)) - { - /* - * Add gziptoany filter to the front of the list... --- -2.31.1 - diff --git a/cups-2.3.3op2-source.tar.gz b/cups-2.4.0-source.tar.gz similarity index 51% rename from cups-2.3.3op2-source.tar.gz rename to cups-2.4.0-source.tar.gz index 20c392c..aa8d49f 100644 Binary files a/cups-2.3.3op2-source.tar.gz and b/cups-2.4.0-source.tar.gz differ diff --git a/cups-cleanfiles.patch b/cups-cleanfiles.patch deleted file mode 100644 index 05437f3..0000000 --- a/cups-cleanfiles.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/scheduler/main.c b/scheduler/main.c -index e1fa357..53ca94a 100644 ---- a/scheduler/main.c -+++ b/scheduler/main.c -@@ -1760,6 +1760,11 @@ select_timeout(int fds) /* I - Number of descriptors returned */ - /* - * Check for any job activity... - */ -+ if (JobHistoryUpdate && timeout > JobHistoryUpdate) -+ { -+ timeout = JobHistoryUpdate; -+ why = "update job history"; -+ } - - for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); - job; diff --git a/cups-deprecate-drivers.patch b/cups-deprecate-drivers.patch deleted file mode 100644 index f0fb420..0000000 --- a/cups-deprecate-drivers.patch +++ /dev/null @@ -1,164 +0,0 @@ -diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c -index 02b9d9d..669cb65 100644 ---- a/cgi-bin/admin.c -+++ b/cgi-bin/admin.c -@@ -619,6 +619,7 @@ do_am_printer(http_t *http, /* I - HTTP connection */ - *oldinfo; /* Old printer information */ - const cgi_file_t *file; /* Uploaded file, if any */ - const char *var; /* CGI variable */ -+ char *ppd_name = NULL; /* Pointer to PPD name */ - char uri[HTTP_MAX_URI], /* Device or printer URI */ - *uriptr, /* Pointer into URI */ - evefile[1024] = ""; /* IPP Everywhere PPD file */ -@@ -1124,12 +1125,12 @@ do_am_printer(http_t *http, /* I - HTTP connection */ - - if (!file) - { -- var = cgiGetVariable("PPD_NAME"); -- if (!strcmp(var, "everywhere")) -+ ppd_name = cgiGetVariable("PPD_NAME"); -+ if (!strcmp(ppd_name, "everywhere")) - get_printer_ppd(cgiGetVariable("DEVICE_URI"), evefile, sizeof(evefile)); -- else if (strcmp(var, "__no_change__")) -+ else if (strcmp(ppd_name, "__no_change__")) - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name", -- NULL, var); -+ NULL, ppd_name); - } - - ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", -@@ -1219,7 +1220,7 @@ do_am_printer(http_t *http, /* I - HTTP connection */ - - cgiCopyTemplateLang("printer-modified.tmpl"); - } -- else -+ else if (ppd_name && (strcmp(ppd_name, "everywhere") == 0 || strstr(ppd_name, "driverless"))) - { - /* - * Set the printer options... -@@ -1229,6 +1230,16 @@ do_am_printer(http_t *http, /* I - HTTP connection */ - do_set_options(http, 0); - return; - } -+ else -+ { -+ /* -+ * If we don't have an everywhere model, show printer-added -+ * template with warning about drivers going away... -+ */ -+ -+ cgiStartHTML(title); -+ cgiCopyTemplateLang("printer-added.tmpl"); -+ } - - cgiEndHTML(); - } -diff --git a/scheduler/printers.c b/scheduler/printers.c -index 3bfe4a8..248bdba 100644 ---- a/scheduler/printers.c -+++ b/scheduler/printers.c -@@ -950,6 +950,8 @@ cupsdLoadAllPrinters(void) - *value, /* Pointer to value */ - *valueptr; /* Pointer into value */ - cupsd_printer_t *p; /* Current printer */ -+ int found_raw = 0; /* Flag whether raw queue is installed */ -+ int found_driver = 0; /* Flag whether queue with classic driver is installed */ - - - /* -@@ -1025,6 +1027,30 @@ cupsdLoadAllPrinters(void) - - cupsdSetPrinterAttrs(p); - -+ if ((p->device_uri && strncmp(p->device_uri, "ipp:", 4) && strncmp(p->device_uri, "ipps:", 5) && strncmp(p->device_uri, "implicitclass:", 14)) || -+ !p->make_model || -+ (p->make_model && strstr(p->make_model, "IPP Everywhere") == NULL && strstr(p->make_model, "driverless") == NULL)) -+ { -+ /* -+ * Warn users about printer drivers and raw queues will be deprecated. -+ * It will warn users in the following scenarios: -+ * - the queue doesn't use ipp, ipps or implicitclass backend, which means -+ * it doesn't communicate via IPP and is raw or uses a driver for sure -+ * - the queue doesn't have make_model - it is raw -+ * - the queue uses a correct backend, but the model is not IPP Everywhere/driverless -+ */ -+ if (!p->make_model) -+ { -+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Queue %s is a raw queue, which is deprecated.", p->name); -+ found_raw = 1; -+ } -+ else -+ { -+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Queue %s uses a printer driver, which is deprecated.", p->name); -+ found_driver = 1; -+ } -+ } -+ - if (strncmp(p->device_uri, "file:", 5) && p->state != IPP_PRINTER_STOPPED) - { - /* -@@ -1415,6 +1441,12 @@ cupsdLoadAllPrinters(void) - } - } - -+ if (found_raw) -+ cupsdLogMessage(CUPSD_LOG_WARN, "Raw queues are deprecated and will stop working in a future version of CUPS. See https://github.com/OpenPrinting/cups/issues/103"); -+ -+ if (found_driver) -+ cupsdLogMessage(CUPSD_LOG_WARN, "Printer drivers are deprecated and will stop working in a future version of CUPS. See https://github.com/OpenPrinting/cups/issues/103"); -+ - cupsFileClose(fp); - } - -diff --git a/templates/choose-model.tmpl b/templates/choose-model.tmpl -index e916cf8..9c9b71f 100644 ---- a/templates/choose-model.tmpl -+++ b/templates/choose-model.tmpl -@@ -39,7 +39,7 @@ - - - -diff --git a/templates/printer-added.tmpl b/templates/printer-added.tmpl -index 0ccf6d3..9ebc835 100644 ---- a/templates/printer-added.tmpl -+++ b/templates/printer-added.tmpl -@@ -1,4 +1,15 @@ --

Add Printer

-+

Add Printer {printer_name}

- -

Printer {printer_name} has been added - successfully. -+ -+

-+Note:Printer drivers and raw queues are deprecated and will stop working in a future version of CUPS. -+
-+ -+
-+ -+ -+ -+ -+
-diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh -index 4498a8c..8776874 100755 ---- a/test/run-stp-tests.sh -+++ b/test/run-stp-tests.sh -@@ -1049,10 +1049,10 @@ fi - - # Warning log messages - count=`$GREP '^W ' $BASE/log/error_log | $GREP -v CreateProfile | $GREP -v 'libusb error' | $GREP -v ColorManager | $GREP -v 'Avahi client failed' | wc -l | awk '{print $1}'` --if test $count != 8; then -- echo "FAIL: $count warning messages, expected 8." -+if test $count != 10; then -+ echo "FAIL: $count warning messages, expected 10." - $GREP '^W ' $BASE/log/error_log -- echo "

FAIL: $count warning messages, expected 8.

" >>$strfile -+ echo "

FAIL: $count warning messages, expected 10.

" >>$strfile - echo "
" >>$strfile
- 	$GREP '^W ' $BASE/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
- 	echo "    
" >>$strfile diff --git a/cups-dymo-deviceid.patch b/cups-dymo-deviceid.patch deleted file mode 100644 index 3ff1ffd..0000000 --- a/cups-dymo-deviceid.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -up cups-2.3.1/ppdc/sample.drv.dymo-deviceid cups-2.3.1/ppdc/sample.drv ---- cups-2.3.1/ppdc/sample.drv.dymo-deviceid 2019-12-16 09:22:34.476492212 +0100 -+++ cups-2.3.1/ppdc/sample.drv 2019-12-16 09:23:44.665003895 +0100 -@@ -129,6 +129,7 @@ Version "2.3" - { - Manufacturer "DYMO" - ModelName "Label Printer" -+ Attribute "1284DeviceID" "" "MFG:DYMO;MDL:LabelWriter 400;" - Attribute NickName "" "DYMO Label Printer" - PCFileName "dymo.ppd" - DriverType label diff --git a/cups-failover-backend.patch b/cups-failover-backend.patch deleted file mode 100644 index 1bcf627..0000000 --- a/cups-failover-backend.patch +++ /dev/null @@ -1,876 +0,0 @@ -diff -up cups-2.3.3/backend/failover.c.failover cups-2.3.3/backend/failover.c ---- cups-2.3.3/backend/failover.c.failover 2020-06-11 08:49:20.515264358 +0200 -+++ cups-2.3.3/backend/failover.c 2020-06-11 08:49:20.515264358 +0200 -@@ -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 -up cups-2.3.3/backend/Makefile.failover cups-2.3.3/backend/Makefile ---- cups-2.3.3/backend/Makefile.failover 2020-04-27 20:04:29.000000000 +0200 -+++ cups-2.3.3/backend/Makefile 2020-06-11 08:52:31.212642019 +0200 -@@ -22,6 +22,7 @@ include ../Makedefs - RBACKENDS = \ - ipp \ - lpd \ -+ failover \ - $(DNSSD_BACKEND) - UBACKENDS = \ - snmp \ -@@ -45,6 +46,7 @@ LIBOBJS = \ - OBJS = \ - ipp.o \ - lpd.o \ -+ failover.o \ - dnssd.o \ - snmp.o \ - socket.o \ -@@ -276,6 +278,15 @@ lpd: lpd.o ../cups/$(LIBCUPS) libbackend - - - # -+# failover -+# -+ -+failover: failover.o ../cups/$(LIBCUPS) libbackend.a -+ echo Linking $@... -+ $(LD_CC) $(ALL_LDFLAGS) -o failover failover.o libbackend.a $(LINKCUPS) -+ -+ -+# - # snmp - # - diff --git a/cups-fstack-strong.patch b/cups-fstack-strong.patch deleted file mode 100644 index 0cdbcd5..0000000 --- a/cups-fstack-strong.patch +++ /dev/null @@ -1,49 +0,0 @@ -diff --git a/config-scripts/cups-compiler.m4 b/config-scripts/cups-compiler.m4 -index 733b06c..bb770f0 100644 ---- a/config-scripts/cups-compiler.m4 -+++ b/config-scripts/cups-compiler.m4 -@@ -123,21 +123,35 @@ if test -n "$GCC"; then - OPTIM="-fPIC $OPTIM" - fi - -- # The -fstack-protector option is available with some versions of -- # GCC and adds "stack canaries" which detect when the return address -- # has been overwritten, preventing many types of exploit attacks. -- AC_MSG_CHECKING(whether compiler supports -fstack-protector) -+ # The -fstack-protector-strong and -fstack-protector options are available -+ # with some versions of# GCC and adds "stack canaries" which detect -+ # when the return address has been overwritten, preventing many types of exploit attacks. -+ # First check for -fstack-protector-strong, then for -fstack-protector... -+ AC_MSG_CHECKING([whether compiler supports -fstack-protector-strong]) - OLDCFLAGS="$CFLAGS" -- CFLAGS="$CFLAGS -fstack-protector" -- AC_TRY_LINK(,, -+ CFLAGS="$CFLAGS -fstack-protector-strong" -+ AC_TRY_LINK(,,[ - if test "x$LSB_BUILD" = xy; then - # Can't use stack-protector with LSB binaries... - OPTIM="$OPTIM -fno-stack-protector" - else -- OPTIM="$OPTIM -fstack-protector" -+ OPTIM="$OPTIM -fstack-protector-strong" - fi -- AC_MSG_RESULT(yes), -- AC_MSG_RESULT(no)) -+ AC_MSG_RESULT(yes) -+ ], [ -+ AC_MSG_CHECKING([whether compiler supports -fstack-protector]) -+ CFLAGS="$OLDCFLAGS -fstack-protector" -+ AC_LINK_IFELSE([AC_LANG_PROGRAM()], [ -+ AS_IF([test "x$LSB_BUILD" = xy], [ -+ # Can't use stack-protector with LSB binaries... -+ OPTIM="$OPTIM -fno-stack-protector" -+ ], [ -+ OPTIM="$OPTIM -fstack-protector" -+ ]) -+ ], [ -+ AC_MSG_RESULT([no]) -+ ]) -+ ]) - CFLAGS="$OLDCFLAGS" - - if test "x$LSB_BUILD" != xy; then diff --git a/cups-logs.patch b/cups-logs.patch deleted file mode 100644 index 75b3e26..0000000 --- a/cups-logs.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/scheduler/log.c b/scheduler/log.c -index 17331ff02..41ddb4cb9 100644 ---- a/scheduler/log.c -+++ b/scheduler/log.c -@@ -569,11 +569,7 @@ cupsdLogJob(cupsd_job_t *job, /* I - Job */ - * Format and write the log message... - */ - --#ifdef HAVE_SYSTEMD_SD_JOURNAL_H -- if (job && strcmp(ErrorLog, "syslog")) --#else - if (job) --#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ - snprintf(jobmsg, sizeof(jobmsg), "[Job %d] %s", job->id, message); - else - strlcpy(jobmsg, message, sizeof(jobmsg)); diff --git a/cups-lspp.patch b/cups-lspp.patch deleted file mode 100644 index 7c094d2..0000000 --- a/cups-lspp.patch +++ /dev/null @@ -1,1990 +0,0 @@ -diff -up cups-2.3.0/config.h.in.lspp cups-2.3.0/config.h.in ---- cups-2.3.0/config.h.in.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/config.h.in 2019-10-07 12:24:43.058597468 +0200 -@@ -684,4 +684,11 @@ static __inline int _cups_abs(int i) { r - # endif /* __GNUC__ || __STDC_VERSION__ */ - #endif /* !HAVE_ABS && !abs */ - -+/* -+ * Are we trying to meet LSPP requirements? -+ */ -+ -+#undef WITH_LSPP -+ -+ - #endif /* !_CUPS_CONFIG_H_ */ -diff -up cups-2.3.0/config-scripts/cups-lspp.m4.lspp cups-2.3.0/config-scripts/cups-lspp.m4 ---- cups-2.3.0/config-scripts/cups-lspp.m4.lspp 2019-10-07 12:24:43.058597468 +0200 -+++ cups-2.3.0/config-scripts/cups-lspp.m4 2019-10-07 12:24:43.058597468 +0200 -@@ -0,0 +1,36 @@ -+dnl -+dnl LSPP code for the Common UNIX Printing System (CUPS). -+dnl -+dnl Copyright 2005-2006 by Hewlett-Packard Development Company, L.P. -+dnl -+dnl This program is free software; you can redistribute it and/or modify -+dnl it under the terms of the GNU General Public License as published by -+dnl the Free Software Foundation; version 2. -+dnl -+dnl This program is distributed in the hope that it will be useful, but -+dnl WITHOUT ANY WARRANTY; without even the implied warranty of -+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+dnl General Public License for more details. -+dnl -+dnl You should have received a copy of the GNU General Public License -+dnl along with this program; if not, write to the Free Software Foundation, -+dnl Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301 USA -+dnl -+ -+dnl Are we trying to meet LSPP requirements -+AC_ARG_ENABLE(lspp, [ --enable-lspp turn on auditing and label support, default=no]) -+ -+if test x"$enable_lspp" != xno; then -+ case "$uname" in -+ Linux) -+ AC_CHECK_LIB(audit,audit_log_user_message, [LIBAUDIT="-laudit" AC_SUBST(LIBAUDIT)]) -+ AC_CHECK_HEADER(libaudit.h) -+ AC_CHECK_LIB(selinux,getpeercon, [LIBSELINUX="-lselinux" AC_SUBST(LIBSELINUX)]) -+ AC_CHECK_HEADER(selinux/selinux.h) -+ AC_DEFINE(WITH_LSPP) -+ ;; -+ *) -+ # All others -+ ;; -+ esac -+fi -diff -up cups-2.3.0/configure.ac.lspp cups-2.3.0/configure.ac ---- cups-2.3.0/configure.ac.lspp 2019-10-07 12:24:43.058597468 +0200 -+++ cups-2.3.0/configure.ac 2019-10-07 12:39:20.122546282 +0200 -@@ -34,6 +34,8 @@ sinclude(config-scripts/cups-dnssd.m4) - sinclude(config-scripts/cups-startup.m4) - sinclude(config-scripts/cups-defaults.m4) - -+sinclude(config-scripts/cups-lspp.m4) -+ - INSTALL_LANGUAGES="" - UNINSTALL_LANGUAGES="" - LANGFILES="" -diff -up cups-2.3.0/filter/common.c.lspp cups-2.3.0/filter/common.c ---- cups-2.3.0/filter/common.c.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/filter/common.c 2019-10-07 12:24:43.059597461 +0200 -@@ -11,6 +11,12 @@ - * Include necessary headers... - */ - -+#include "config.h" -+#ifdef WITH_LSPP -+#define _GNU_SOURCE -+#include -+#endif /* WITH_LSPP */ -+ - #include "common.h" - #include - -@@ -293,6 +299,18 @@ WriteLabelProlog(const char *label, /* I - { - const char *classification; /* CLASSIFICATION environment variable */ - const char *ptr; /* Temporary string pointer */ -+#ifdef WITH_LSPP -+ int i, /* counter */ -+ n, /* counter */ -+ lines, /* number of lines needed */ -+ line_len, /* index into tmp_label */ -+ label_len, /* length of the label in characters */ -+ label_index, /* index into the label */ -+ longest, /* length of the longest line */ -+ longest_line, /* index to the longest line */ -+ max_width; /* maximum width in characters */ -+ char **wrapped_label; /* label with line breaks */ -+#endif /* WITH_LSPP */ - - - /* -@@ -315,6 +333,124 @@ WriteLabelProlog(const char *label, /* I - return; - } - -+#ifdef WITH_LSPP -+ if (strncmp(classification, "LSPP:", 5) == 0 && label == NULL) -+ { -+ /* -+ * Based on the 12pt fixed width font below determine the max_width -+ */ -+ max_width = width / 8; -+ longest_line = 0; -+ longest = 0; -+ classification += 5; // Skip the "LSPP:" -+ label_len = strlen(classification); -+ -+ if (label_len > max_width) -+ { -+ lines = 1 + (int)(label_len / max_width); -+ line_len = (int)(label_len / lines); -+ wrapped_label = malloc(sizeof(*wrapped_label) * lines); -+ label_index = i = n = 0; -+ while (classification[label_index]) -+ { -+ if ((label_index + line_len) > label_len) -+ break; -+ switch (classification[label_index + line_len + i]) -+ { -+ case ':': -+ case ',': -+ case '-': -+ i++; -+ wrapped_label[n++] = strndup(&classification[label_index], (line_len + i)); -+ label_index += line_len + i; -+ i = 0; -+ break; -+ default: -+ i++; -+ break; -+ } -+ if ((i + line_len) == max_width) -+ { -+ wrapped_label[n++] = strndup(&(classification[label_index]), (line_len + i)); -+ label_index = label_index + line_len + i; -+ i = 0; -+ } -+ } -+ wrapped_label[n] = strndup(&classification[label_index], label_len - label_index); -+ } -+ else -+ { -+ lines = 1; -+ wrapped_label = malloc(sizeof(*wrapped_label)); -+ wrapped_label[0] = (char*)classification; -+ } -+ -+ for (n = 0; n < lines; n++ ) -+ { -+ printf("userdict/ESPp%c(", ('a' + n)); -+ for (ptr = wrapped_label[n], i = 0; *ptr; ptr ++, i++) -+ if (*ptr < 32 || *ptr > 126) -+ printf("\\%03o", *ptr); -+ else -+ { -+ if (*ptr == '(' || *ptr == ')' || *ptr == '\\') -+ putchar('\\'); -+ -+ printf("%c", *ptr); -+ } -+ if (i > longest) -+ { -+ longest = i; -+ longest_line = n; -+ } -+ printf(")put\n"); -+ } -+ -+ /* -+ * For LSPP use a fixed width font so that line wrapping can be calculated -+ */ -+ -+ puts("userdict/ESPlf /Nimbus-Mono findfont 12 scalefont put"); -+ -+ /* -+ * Finally, the procedure to write the labels on the page... -+ */ -+ -+ printf("userdict/ESPwl{\n" -+ " ESPlf setfont\n"); -+ printf(" ESPp%c stringwidth pop dup 12 add exch -0.5 mul %.0f add\n ", -+ 'a' + longest_line, width * 0.5f); -+ for (n = 1; n < lines; n++) -+ printf(" dup"); -+ printf("\n 1 setgray\n"); -+ printf(" dup 6 sub %.0f %d index %.0f ESPrf\n", -+ (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines)); -+ printf(" dup 6 sub %.0f %d index %.0f ESPrf\n", -+ (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines)); -+ printf(" 0 setgray\n"); -+ printf(" dup 6 sub %.0f %d index %.0f ESPrs\n", -+ (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines)); -+ printf(" dup 6 sub %.0f %d index %.0f ESPrs\n", -+ (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines)); -+ for (n = 0; n < lines; n ++) -+ { -+ printf(" dup %.0f moveto ESPp%c show\n", -+ bottom + 6.0 + ((lines - (n+1)) * 16.0), 'a' + n); -+ printf(" %.0f moveto ESPp%c show\n", top + 2.0 - ((n + 1) * 16.0), 'a' + n); -+ } -+ printf(" pop\n" -+ "}bind put\n"); -+ -+ /* -+ * Do some clean up at the end of the LSPP special case -+ */ -+ free(wrapped_label); -+ -+ } -+ else -+ { -+#endif /* !WITH_LSPP */ -+ - /* - * Set the classification + page label string... - */ -@@ -395,7 +531,10 @@ WriteLabelProlog(const char *label, /* I - printf(" %.0f moveto ESPpl show\n", top - 14.0); - puts("pop"); - puts("}bind put"); -+ } -+#ifdef WITH_LSPP - } -+#endif /* WITH_LSPP */ - - - /* -diff -up cups-2.3.0/filter/pstops.c.lspp cups-2.3.0/filter/pstops.c ---- cups-2.3.0/filter/pstops.c.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/filter/pstops.c 2019-10-07 12:24:43.059597461 +0200 -@@ -3170,6 +3170,18 @@ write_label_prolog(pstops_doc_t *doc, /* - { - const char *classification; /* CLASSIFICATION environment variable */ - const char *ptr; /* Temporary string pointer */ -+#ifdef WITH_LSPP -+ int i, /* counter */ -+ n, /* counter */ -+ lines, /* number of lines needed */ -+ line_len, /* index into tmp_label */ -+ label_len, /* length of the label in characters */ -+ label_index, /* index into the label */ -+ longest, /* length of the longest line */ -+ longest_line, /* index to the longest line */ -+ max_width; /* maximum width in characters */ -+ char **wrapped_label; /* label with line breaks */ -+#endif /* WITH_LSPP */ - - - /* -@@ -3192,6 +3204,124 @@ write_label_prolog(pstops_doc_t *doc, /* - return; - } - -+#ifdef WITH_LSPP -+ if (strncmp(classification, "LSPP:", 5) == 0 && label == NULL) -+ { -+ /* -+ * Based on the 12pt fixed width font below determine the max_width -+ */ -+ max_width = width / 8; -+ longest_line = 0; -+ longest = 0; -+ classification += 5; // Skip the "LSPP:" -+ label_len = strlen(classification); -+ -+ if (label_len > max_width) -+ { -+ lines = 1 + (int)(label_len / max_width); -+ line_len = (int)(label_len / lines); -+ wrapped_label = malloc(sizeof(*wrapped_label) * lines); -+ label_index = i = n = 0; -+ while (classification[label_index]) -+ { -+ if ((label_index + line_len) > label_len) -+ break; -+ switch (classification[label_index + line_len + i]) -+ { -+ case ':': -+ case ',': -+ case '-': -+ i++; -+ wrapped_label[n++] = strndup(&classification[label_index], (line_len + i)); -+ label_index += line_len + i; -+ i = 0; -+ break; -+ default: -+ i++; -+ break; -+ } -+ if ((i + line_len) == max_width) -+ { -+ wrapped_label[n++] = strndup(&(classification[label_index]), (line_len + i)); -+ label_index = label_index + line_len + i; -+ i = 0; -+ } -+ } -+ wrapped_label[n] = strndup(&classification[label_index], label_len - label_index); -+ } -+ else -+ { -+ lines = 1; -+ wrapped_label = malloc(sizeof(*wrapped_label)); -+ wrapped_label[0] = (char*)classification; -+ } -+ -+ for (n = 0; n < lines; n++ ) -+ { -+ printf("userdict/ESPp%c(", ('a' + n)); -+ for (ptr = wrapped_label[n], i = 0; *ptr; ptr ++, i++) -+ if (*ptr < 32 || *ptr > 126) -+ printf("\\%03o", *ptr); -+ else -+ { -+ if (*ptr == '(' || *ptr == ')' || *ptr == '\\') -+ putchar('\\'); -+ -+ printf("%c", *ptr); -+ } -+ if (i > longest) -+ { -+ longest = i; -+ longest_line = n; -+ } -+ printf(")put\n"); -+ } -+ -+ /* -+ * For LSPP use a fixed width font so that line wrapping can be calculated -+ */ -+ -+ puts("userdict/ESPlf /Nimbus-Mono findfont 12 scalefont put"); -+ -+ /* -+ * Finally, the procedure to write the labels on the page... -+ */ -+ -+ printf("userdict/ESPwl{\n" -+ " ESPlf setfont\n"); -+ printf(" ESPp%c stringwidth pop dup 12 add exch -0.5 mul %.0f add\n ", -+ 'a' + longest_line, width * 0.5f); -+ for (n = 1; n < lines; n++) -+ printf(" dup"); -+ printf("\n 1 setgray\n"); -+ printf(" dup 6 sub %.0f %d index %.0f ESPrf\n", -+ (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines)); -+ printf(" dup 6 sub %.0f %d index %.0f ESPrf\n", -+ (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines)); -+ printf(" 0 setgray\n"); -+ printf(" dup 6 sub %.0f %d index %.0f ESPrs\n", -+ (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines)); -+ printf(" dup 6 sub %.0f %d index %.0f ESPrs\n", -+ (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines)); -+ for (n = 0; n < lines; n ++) -+ { -+ printf(" dup %.0f moveto ESPp%c show\n", -+ bottom + 6.0 + ((lines - (n+1)) * 16.0), 'a' + n); -+ printf(" %.0f moveto ESPp%c show\n", top + 2.0 - ((n + 1) * 16.0), 'a' + n); -+ } -+ printf(" pop\n" -+ "}bind put\n"); -+ -+ /* -+ * Do some clean up at the end of the LSPP special case -+ */ -+ free(wrapped_label); -+ -+ } -+ else -+ { -+#endif /* !WITH_LSPP */ -+ - /* - * Set the classification + page label string... - */ -@@ -3270,7 +3400,10 @@ write_label_prolog(pstops_doc_t *doc, /* - doc_printf(doc, " %.0f moveto ESPpl show\n", top - 14.0); - doc_puts(doc, "pop\n"); - doc_puts(doc, "}bind put\n"); -+ } -+#ifdef WITH_LSPP - } -+#endif /* WITH_LSPP */ - - - /* -diff -up cups-2.3.0/Makedefs.in.lspp cups-2.3.0/Makedefs.in ---- cups-2.3.0/Makedefs.in.lspp 2019-10-07 12:24:43.059597461 +0200 -+++ cups-2.3.0/Makedefs.in 2019-10-07 12:37:19.200565805 +0200 -@@ -174,7 +174,7 @@ IPPFIND_MAN = @IPPFIND_MAN@ - LDFLAGS = @LDFLAGS@ - LINKCUPS = @LINKCUPS@ - LINKCUPSSTATIC = ../cups/$(LIBCUPSSTATIC) $(LIBS) --LIBS = $(LIBGSSAPI) $(DNSSDLIBS) $(SSLLIBS) $(LIBZ) $(COMMONLIBS) -+LIBS = $(LIBGSSAPI) $(DNSSDLIBS) $(SSLLIBS) $(LIBZ) $(COMMONLIBS) @LIBAUDIT@ @LIBSELINUX@ - ONDEMANDFLAGS = @ONDEMANDFLAGS@ - ONDEMANDLIBS = @ONDEMANDLIBS@ - OPTIM = @OPTIM@ -diff -up cups-2.3.0/scheduler/client.c.lspp cups-2.3.0/scheduler/client.c ---- cups-2.3.0/scheduler/client.c.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/scheduler/client.c 2019-10-07 12:33:10.459693580 +0200 -@@ -19,12 +19,20 @@ - #define _HTTP_NO_PRIVATE - #include "cupsd.h" - -+#ifndef _GNU_SOURCE -+#define _GNU_SOURCE -+#endif /* !defined(_GNU_SOURCE) */ - #ifdef __APPLE__ - # include - #endif /* __APPLE__ */ - #ifdef HAVE_TCPD_H - # include - #endif /* HAVE_TCPD_H */ -+#ifdef WITH_LSPP -+# include -+# include -+# include -+#endif /* WITH_LSPP */ - - - /* -@@ -265,6 +273,59 @@ cupsdAcceptClient(cupsd_listener_t *lis) - } - #endif /* HAVE_TCPD_H */ - -+#ifdef WITH_LSPP -+ if (is_lspp_config()) -+ { -+ struct ucred cr; -+ unsigned int cl=sizeof(cr); -+ -+ if (getsockopt(httpGetFd(con->http), SOL_SOCKET, SO_PEERCRED, &cr, &cl) == 0) -+ { -+ /* -+ * client_pid_to_auid() can be racey -+ * In this case the pid is based on a socket connected to the client -+ */ -+ if ((con->auid = client_pid_to_auid(cr.pid)) == -1) -+ { -+ httpClose(con->http); -+ cupsdLogClient(con, CUPSD_LOG_ERROR, -+ "Unable to determine client auid for client pid=%d", -+ cr.pid); -+ free(con); -+ return; -+ } -+ cupsdLogClient(con, CUPSD_LOG_INFO, -+ "peer's pid=%d, uid=%d, gid=%d, auid=%d", -+ cr.pid, cr.uid, cr.gid, con->auid); -+ } -+ else -+ { -+ httpClose(con->http); -+ cupsdLogClient(con, CUPSD_LOG_ERROR, "getsockopt() failed"); -+ free(con); -+ return; -+ } -+ -+ /* -+ * get the context of the peer connection -+ */ -+ if (getpeercon(httpGetFd(con->http), &con->scon)) -+ { -+ httpClose(con->http); -+ cupsdLogClient(con, CUPSD_LOG_ERROR, "getpeercon() failed"); -+ free(con); -+ return; -+ } -+ -+ cupsdLogClient(con, CUPSD_LOG_INFO, "client context=%s", con->scon); -+ } -+ else -+ { -+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "skipping getpeercon()"); -+ cupsdSetString(&con->scon, UNKNOWN_SL); -+ } -+#endif /* WITH_LSPP */ -+ - #ifdef AF_LOCAL - if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL) - { -@@ -558,6 +619,13 @@ cupsdReadClient(cupsd_client_t *con) /* - struct stat filestats; /* File information */ - mime_type_t *type; /* MIME type of file */ - static unsigned request_id = 0; /* Request ID for temp files */ -+#ifdef WITH_LSPP -+ security_context_t spoolcon; /* context of the job file */ -+ context_t clicon; /* contex_t container for con->scon */ -+ context_t tmpcon; /* temp context to swap the level */ -+ char *clirange; /* SELinux sensitivity range */ -+ char *cliclearance; /* SELinux low end clearance */ -+#endif /* WITH_LSPP */ - - - status = HTTP_STATUS_CONTINUE; -@@ -1679,6 +1747,73 @@ cupsdReadClient(cupsd_client_t *con) /* - fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC); - } - -+#ifdef WITH_LSPP -+ if (strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0) -+ { -+ if (getfilecon(con->filename, &spoolcon) == -1) -+ { -+ cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE); -+ cupsdCloseClient(con); -+ return; -+ } -+ clicon = context_new(con->scon); -+ tmpcon = context_new(spoolcon); -+ freecon(spoolcon); -+ if (!clicon || !tmpcon) -+ { -+ cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE); -+ if (clicon) -+ context_free(clicon); -+ if (tmpcon) -+ context_free(tmpcon); -+ cupsdCloseClient(con); -+ return; -+ } -+ clirange = (char *) context_range_get(clicon); -+ if (clirange) -+ { -+ clirange = strdup(clirange); -+ if ((cliclearance = strtok(clirange, "-")) != NULL) -+ { -+ if (context_range_set(tmpcon, cliclearance) == -1) -+ { -+ cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE); -+ free(clirange); -+ context_free(tmpcon); -+ context_free(clicon); -+ cupsdCloseClient(con); -+ return; -+ } -+ } -+ else -+ { -+ if (context_range_set(tmpcon, (context_range_get(clicon))) == -1) -+ { -+ cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE); -+ free(clirange); -+ context_free(tmpcon); -+ context_free(clicon); -+ cupsdCloseClient(con); -+ return; -+ } -+ } -+ free(clirange); -+ } -+ if (setfilecon(con->filename, context_str(tmpcon)) == -1) -+ { -+ cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE); -+ context_free(tmpcon); -+ context_free(clicon); -+ cupsdCloseClient(con); -+ return; -+ } -+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "%s set to %s", -+ con->filename, context_str(tmpcon)); -+ context_free(tmpcon); -+ context_free(clicon); -+ } -+#endif /* WITH_LSPP */ -+ - if (httpGetState(con->http) != HTTP_STATE_POST_SEND) - { - if (!httpWait(con->http, 0)) -@@ -3174,6 +3309,49 @@ is_path_absolute(const char *path) /* I - return (1); - } - -+#ifdef WITH_LSPP -+/* -+ * 'client_pid_to_auid()' - Using the client's pid, read /proc and determine the loginuid. -+ */ -+ -+uid_t client_pid_to_auid(pid_t clipid) -+{ -+ uid_t uid; -+ int len, in; -+ char buf[16] = {0}; -+ char fname[32] = {0}; -+ -+ -+ /* -+ * Hopefully this pid is still the one we are interested in. -+ */ -+ snprintf(fname, 32, "/proc/%d/loginuid", clipid); -+ in = open(fname, O_NOFOLLOW|O_RDONLY); -+ -+ if (in < 0) -+ return (uid_t) -1; -+ -+ errno = 0; -+ -+ do { -+ len = read(in, buf, sizeof(buf)); -+ } while (len < 0 && errno == EINTR); -+ -+ close(in); -+ -+ if (len < 0 || len >= sizeof(buf)) -+ return (uid_t) -1; -+ -+ errno = 0; -+ buf[len] = 0; -+ uid = strtol(buf, 0, 10); -+ -+ if (errno != 0) -+ return (uid_t) -1; -+ else -+ return uid; -+} -+#endif /* WITH_LSPP */ - - /* - * 'pipe_command()' - Pipe the output of a command to the remote client. -diff -up cups-2.3.0/scheduler/client.h.lspp cups-2.3.0/scheduler/client.h ---- cups-2.3.0/scheduler/client.h.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/scheduler/client.h 2019-10-07 12:24:43.113597079 +0200 -@@ -13,6 +13,13 @@ - #endif /* HAVE_AUTHORIZATION_H */ - - -+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ -+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ -+ -+#ifdef WITH_LSPP -+#include -+#endif /* WITH_LSPP */ -+ - /* - * HTTP client structure... - */ -@@ -63,6 +70,10 @@ struct cupsd_client_s - #ifdef HAVE_AUTHORIZATION_H - AuthorizationRef authref; /* Authorization ref */ - #endif /* HAVE_AUTHORIZATION_H */ -+#ifdef WITH_LSPP -+ security_context_t scon; /* Security context of connection */ -+ uid_t auid; /* Audit loginuid of the client */ -+#endif /* WITH_LSPP */ - }; - - #define HTTP(con) ((con)->http) -@@ -136,6 +147,9 @@ extern void cupsdStartListening(void); - extern void cupsdStopListening(void); - extern void cupsdUpdateCGI(void); - extern void cupsdWriteClient(cupsd_client_t *con); -+#ifdef WITH_LSPP -+extern uid_t client_pid_to_auid(pid_t clipid); -+#endif /* WITH_LSPP */ - - #ifdef HAVE_SSL - extern int cupsdEndTLS(cupsd_client_t *con); -diff -up cups-2.3.0/scheduler/conf.c.lspp cups-2.3.0/scheduler/conf.c ---- cups-2.3.0/scheduler/conf.c.lspp 2019-10-07 12:24:43.049597531 +0200 -+++ cups-2.3.0/scheduler/conf.c 2019-10-07 12:24:43.113597079 +0200 -@@ -37,6 +37,9 @@ - # define INADDR_NONE 0xffffffff - #endif /* !INADDR_NONE */ - -+#ifdef WITH_LSPP -+# include -+#endif /* WITH_LSPP */ - - /* - * Configuration variable structure... -@@ -131,6 +134,10 @@ static const cupsd_var_t cupsd_vars[] = - { "ServerName", &ServerName, CUPSD_VARTYPE_STRING }, - { "StrictConformance", &StrictConformance, CUPSD_VARTYPE_BOOLEAN }, - { "Timeout", &Timeout, CUPSD_VARTYPE_TIME }, -+#ifdef WITH_LSPP -+ { "AuditLog", &AuditLog, CUPSD_VARTYPE_INTEGER }, -+ { "PerPageLabels", &PerPageLabels, CUPSD_VARTYPE_BOOLEAN }, -+#endif /* WITH_LSPP */ - { "WebInterface", &WebInterface, CUPSD_VARTYPE_BOOLEAN } - }; - static const cupsd_var_t cupsfiles_vars[] = -@@ -544,6 +551,9 @@ cupsdReadConfiguration(void) - const char *tmpdir; /* TMPDIR environment variable */ - struct stat tmpinfo; /* Temporary directory info */ - cupsd_policy_t *p; /* Policy */ -+#ifdef WITH_LSPP -+ char *audit_message; /* Audit message string */ -+#endif /* WITH_LSPP */ - - - /* -@@ -864,6 +874,25 @@ cupsdReadConfiguration(void) - - RunUser = getuid(); - -+#ifdef WITH_LSPP -+ if (AuditLog != -1) -+ { -+ /* -+ * ClassifyOverride is set during read_configuration, if its ON, report it now -+ */ -+ if (ClassifyOverride) -+ audit_log_user_message(AuditLog, AUDIT_USYS_CONFIG, -+ "[Config] ClassifyOverride=enabled Users can override print banners", -+ ServerName, NULL, NULL, 1); -+ /* -+ * PerPageLabel is set during read_configuration, if its OFF, report it now -+ */ -+ if (!PerPageLabels) -+ audit_log_user_message(AuditLog, AUDIT_USYS_CONFIG, -+ "[Config] PerPageLabels=disabled", ServerName, NULL, NULL, 1); -+ } -+#endif /* WITH_LSPP */ -+ - cupsdLogMessage(CUPSD_LOG_INFO, "Remote access is %s.", - RemotePort ? "enabled" : "disabled"); - -@@ -1275,7 +1304,19 @@ cupsdReadConfiguration(void) - cupsdClearString(&Classification); - - if (Classification) -+ { - cupsdLogMessage(CUPSD_LOG_INFO, "Security set to \"%s\"", Classification); -+#ifdef WITH_LSPP -+ if (AuditLog != -1) -+ { -+ audit_message = NULL; -+ cupsdSetStringf(&audit_message, "[Config] Classification=%s", Classification); -+ audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message, -+ ServerName, NULL, NULL, 1); -+ cupsdClearString(&audit_message); -+ } -+#endif /* WITH_LSPP */ -+ } - - /* - * Check the MaxClients setting, and then allocate memory for it... -@@ -3830,6 +3871,18 @@ read_location(cups_file_t *fp, /* I - C - return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum); - } - -+#ifdef WITH_LSPP -+int is_lspp_config() -+{ -+ if (Classification != NULL) -+ return ((_cups_strcasecmp(Classification, MLS_CONFIG) == 0) -+ || (_cups_strcasecmp(Classification, TE_CONFIG) == 0) -+ || (_cups_strcasecmp(Classification, SELINUX_CONFIG) == 0)); -+ else -+ return 0; -+} -+#endif /* WITH_LSPP */ -+ - - /* - * 'read_policy()' - Read a definition. -diff -up cups-2.3.0/scheduler/conf.h.lspp cups-2.3.0/scheduler/conf.h ---- cups-2.3.0/scheduler/conf.h.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/scheduler/conf.h 2019-10-07 12:24:43.113597079 +0200 -@@ -243,6 +243,13 @@ VAR char *ServerKeychain VALUE(NULL); - /* Keychain holding cert + key */ - #endif /* HAVE_SSL */ - -+#ifdef WITH_LSPP -+VAR int AuditLog VALUE(-1), -+ /* File descriptor for audit */ -+ PerPageLabels VALUE(TRUE); -+ /* Put the label on each page */ -+#endif /* WITH_LSPP */ -+ - #ifdef HAVE_ONDEMAND - VAR int IdleExitTimeout VALUE(60); - /* Time after which an idle cupsd will exit */ -@@ -261,6 +268,9 @@ VAR int HaveServerCreds VALUE(0); - VAR gss_cred_id_t ServerCreds; /* Server's GSS credentials */ - #endif /* HAVE_GSSAPI */ - -+#ifdef WITH_LSPP -+extern int is_lspp_config(void); -+#endif /* WITH_LSPP */ - - /* - * Prototypes... -diff -up cups-2.3.0/scheduler/cupsd.h.lspp cups-2.3.0/scheduler/cupsd.h ---- cups-2.3.0/scheduler/cupsd.h.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/scheduler/cupsd.h 2019-10-07 12:31:38.458480578 +0200 -@@ -8,6 +8,8 @@ - * information. - */ - -+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ -+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ - - /* - * Include necessary headers. -@@ -33,6 +35,14 @@ - # include - #endif /* _WIN32 */ - -+#include "config.h" -+#ifdef WITH_LSPP -+# define MLS_CONFIG "mls" -+# define TE_CONFIG "te" -+# define SELINUX_CONFIG "SELinux" -+# define UNKNOWN_SL "UNKNOWN SL" -+#endif /* WITH_LSPP */ -+ - #include "mime.h" - - #if defined(HAVE_CDSASSL) -diff -up cups-2.3.0/scheduler/ipp.c.lspp cups-2.3.0/scheduler/ipp.c ---- cups-2.3.0/scheduler/ipp.c.lspp 2019-10-07 12:24:43.016597764 +0200 -+++ cups-2.3.0/scheduler/ipp.c 2019-10-07 12:31:01.243798920 +0200 -@@ -11,6 +11,9 @@ - * information. - */ - -+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ -+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ -+ - /* - * Include necessary headers... - */ -@@ -27,6 +30,14 @@ extern int mbr_group_name_to_uuid(const - extern int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember); - #endif /* __APPLE__ */ - -+#ifdef WITH_LSPP -+#include -+#include -+#include -+#include -+#include -+#include -+#endif /* WITH_LSPP */ - - /* - * Local functions... -@@ -51,6 +62,9 @@ static void cancel_all_jobs(cupsd_client - static void cancel_job(cupsd_client_t *con, ipp_attribute_t *uri); - static void cancel_subscription(cupsd_client_t *con, int id); - static int check_rss_recipient(const char *recipient); -+#ifdef WITH_LSPP -+static int check_context(cupsd_client_t *con, cupsd_job_t *job); -+#endif /* WITH_LSPP */ - static int check_quotas(cupsd_client_t *con, cupsd_printer_t *p); - static void close_job(cupsd_client_t *con, ipp_attribute_t *uri); - static void copy_attrs(ipp_t *to, ipp_t *from, cups_array_t *ra, -@@ -1240,6 +1254,21 @@ add_job(cupsd_client_t *con, /* I - Cl - "time-at-creation", - "time-at-processing" - }; -+#ifdef WITH_LSPP -+ char *audit_message; /* Audit message string */ -+ char *printerfile; /* device file pointed to by the printer */ -+ char *userheader = NULL; /* User supplied job-sheets[0] */ -+ char *userfooter = NULL; /* User supplied job-sheets[1] */ -+ int override = 0; /* Was a banner overrode on a job */ -+ security_id_t clisid; /* SELinux SID for the client */ -+ security_id_t psid; /* SELinux SID for the printer */ -+ context_t printercon; /* Printer's context string */ -+ struct stat printerstat; /* Printer's stat buffer */ -+ security_context_t devcon; /* Printer's SELinux context */ -+ struct avc_entry_ref avcref; /* Pointer to the access vector cache */ -+ security_class_t tclass; /* Object class for the SELinux check */ -+ access_vector_t avr; /* Access method being requested */ -+#endif /* WITH_LSPP */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))", -@@ -1568,6 +1597,106 @@ add_job(cupsd_client_t *con, /* I - Cl - - attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME); - -+#ifdef WITH_LSPP -+ if (is_lspp_config()) -+ { -+ if (!con->scon || strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0) -+ { -+ cupsdLogMessage(CUPSD_LOG_ERROR, "add_job: missing classification for connection \'%s\'!", printer->name); -+ send_ipp_status(con, IPP_INTERNAL_ERROR, _("Missing required security attributes.")); -+ return (NULL); -+ } -+ -+ /* -+ * Perform an access check so that if the user gets feedback at enqueue time -+ */ -+ -+ printerfile = strstr(printer->device_uri, "/dev/"); -+ if (printerfile == NULL && (strncmp(printer->device_uri, "file:/", 6) == 0)) -+ printerfile = printer->device_uri + strlen("file:"); -+ -+ if (printerfile != NULL) -+ { -+ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: Attempting an access check on printer device %s", -+ printerfile); -+ -+ if (lstat(printerfile, &printerstat) < 0) -+ { -+ if (errno != ENOENT) -+ { -+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to stat the printer")); -+ return (NULL); -+ } -+ /* -+ * The printer does not exist, so for now assume it's a FileDevice -+ */ -+ tclass = SECCLASS_FILE; -+ avr = FILE__WRITE; -+ } -+ else if (S_ISCHR(printerstat.st_mode)) -+ { -+ tclass = SECCLASS_CHR_FILE; -+ avr = CHR_FILE__WRITE; -+ } -+ else if (S_ISREG(printerstat.st_mode)) -+ { -+ tclass = SECCLASS_FILE; -+ avr = FILE__WRITE; -+ } -+ else -+ { -+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Printer is not a character device or regular file")); -+ return (NULL); -+ } -+ static int avc_initialized = 0; -+ if (!avc_initialized++) -+ avc_init("cupsd_enqueue_", NULL, NULL, NULL, NULL); -+ avc_entry_ref_init(&avcref); -+ if (avc_context_to_sid(con->scon, &clisid) != 0) -+ { -+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux sid of the client")); -+ return (NULL); -+ } -+ if (getfilecon(printerfile, &devcon) == -1) -+ { -+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux context of the printer")); -+ return (NULL); -+ } -+ printercon = context_new(devcon); -+ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: printer context %s client context %s", -+ context_str(printercon), con->scon); -+ context_free(printercon); -+ -+ if (avc_context_to_sid(devcon, &psid) != 0) -+ { -+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux sid of the printer")); -+ freecon(devcon); -+ return (NULL); -+ } -+ freecon(devcon); -+ if (avc_has_perm(clisid, psid, tclass, avr, &avcref, NULL) != 0) -+ { -+ /* -+ * The access check failed, so cancel the job and send an audit message -+ */ -+ if (AuditLog != -1) -+ { -+ audit_message = NULL; -+ cupsdSetStringf(&audit_message, "job=? auid=%u acct=%s obj=%s refused" -+ " unable to access printer=%s", con->auid, -+ con->username, con->scon, printer->name); -+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message, -+ ServerName, NULL, NULL, 0); -+ cupsdClearString(&audit_message); -+ } -+ -+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("SELinux prohibits access to the printer")); -+ return (NULL); -+ } -+ } -+ } -+#endif /* WITH_LSPP */ -+ - if ((job = cupsdAddJob(priority, printer->name)) == NULL) - { - send_ipp_status(con, IPP_INTERNAL_ERROR, -@@ -1576,6 +1705,32 @@ add_job(cupsd_client_t *con, /* I - Cl - return (NULL); - } - -+#ifdef WITH_LSPP -+ if (is_lspp_config()) -+ { -+ /* -+ * duplicate the security context and auid of the connection into the job structure -+ */ -+ job->scon = strdup(con->scon); -+ job->auid = con->auid; -+ -+ /* -+ * add the security context to the request so that on a restart the security -+ * attributes will be able to be restored -+ */ -+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "security-context", -+ NULL, job->scon); -+ } -+ else -+ { -+ /* -+ * Fill in the security context of the job as unlabeled -+ */ -+ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: setting context of job to %s", UNKNOWN_SL); -+ cupsdSetString(&job->scon, UNKNOWN_SL); -+ } -+#endif /* WITH_LSPP */ -+ - job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); - job->attrs = con->request; - job->dirty = 1; -@@ -1763,6 +1918,29 @@ add_job(cupsd_client_t *con, /* I - Cl - ippSetString(job->attrs, &attr, 0, printer->job_sheets[0]); - ippSetString(job->attrs, &attr, 1, printer->job_sheets[1]); - } -+#ifdef WITH_LSPP -+ else -+ { -+ /* -+ * The option was present, so capture the user supplied strings -+ */ -+ userheader = strdup(attr->values[0].string.text); -+ -+ if (attr->num_values > 1) -+ userfooter = strdup(attr->values[1].string.text); -+ -+ if (Classification != NULL && (strcmp(userheader, Classification) == 0) -+ && userfooter &&(strcmp(userfooter, Classification) == 0)) -+ { -+ /* -+ * Since both values are Classification, the user is not trying to Override -+ */ -+ free(userheader); -+ if (userfooter) free(userfooter); -+ userheader = userfooter = NULL; -+ } -+ } -+#endif /* WITH_LSPP */ - - job->job_sheets = attr; - -@@ -1793,6 +1971,9 @@ add_job(cupsd_client_t *con, /* I - Cl - "job-sheets=\"%s,none\", " - "job-originating-user-name=\"%s\"", - Classification, job->username); -+#ifdef WITH_LSPP -+ override = 1; -+#endif /* WITH_LSPP */ - } - else if (attr->num_values == 2 && - strcmp(attr->values[0].string.text, -@@ -1811,6 +1992,9 @@ add_job(cupsd_client_t *con, /* I - Cl - "job-originating-user-name=\"%s\"", - attr->values[0].string.text, - attr->values[1].string.text, job->username); -+#ifdef WITH_LSPP -+ override = 1; -+#endif /* WITH_LSPP */ - } - else if (strcmp(attr->values[0].string.text, Classification) && - strcmp(attr->values[0].string.text, "none") && -@@ -1831,6 +2015,9 @@ add_job(cupsd_client_t *con, /* I - Cl - "job-originating-user-name=\"%s\"", - attr->values[0].string.text, - attr->values[1].string.text, job->username); -+#ifdef WITH_LSPP -+ override = 1; -+#endif /* WITH_LSPP */ - } - } - else if (strcmp(attr->values[0].string.text, Classification) && -@@ -1871,8 +2058,52 @@ add_job(cupsd_client_t *con, /* I - Cl - "job-sheets=\"%s\", " - "job-originating-user-name=\"%s\"", - Classification, job->username); -+#ifdef WITH_LSPP -+ override = 1; -+#endif /* WITH_LSPP */ -+ } -+#ifdef WITH_LSPP -+ if (is_lspp_config() && AuditLog != -1) -+ { -+ audit_message = NULL; -+ -+ if (userheader || userfooter) -+ { -+ if (!override) -+ { -+ /* -+ * The user overrode the banner, so audit it -+ */ -+ cupsdSetStringf(&audit_message, "job=%d user supplied job-sheets=%s,%s" -+ " using banners=%s,%s", job->id, userheader, -+ userfooter, attr->values[0].string.text, -+ (attr->num_values > 1) ? attr->values[1].string.text : "(null)"); -+ audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message, -+ ServerName, NULL, NULL, 1); -+ } -+ else -+ { -+ /* -+ * The user tried to override the banner, audit the failure -+ */ -+ cupsdSetStringf(&audit_message, "job=%d user supplied job-sheets=%s,%s" -+ " ignored banners=%s,%s", job->id, userheader, -+ userfooter, attr->values[0].string.text, -+ (attr->num_values > 1) ? attr->values[1].string.text : "(null)"); -+ audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message, -+ ServerName, NULL, NULL, 0); -+ } -+ cupsdClearString(&audit_message); -+ } - } -+ -+ if (userheader) -+ free(userheader); -+ if (userfooter) -+ free(userfooter); -+#endif /* WITH_LSPP */ - } -+ - - /* - * See if we need to add the starting sheet... -@@ -3648,6 +3879,128 @@ check_rss_recipient( - } - - -+#ifdef WITH_LSPP -+/* -+ * 'check_context()' - Check SELinux security context of a user and job -+ */ -+ -+static int /* O - 1 if OK, 0 if not, -1 on error */ -+check_context(cupsd_client_t *con, /* I - Client connection */ -+ cupsd_job_t *job) /* I - Job */ -+{ -+ int enforcing; /* is SELinux in enforcing mode */ -+ char filename[1024]; /* Filename of the spool file */ -+ security_id_t clisid; /* SELinux SID of the client */ -+ security_id_t jobsid; /* SELinux SID of the job */ -+ security_id_t filesid; /* SELinux SID of the spool file */ -+ struct avc_entry_ref avcref; /* AVC entry cache pointer */ -+ security_class_t tclass; /* SELinux security class */ -+ access_vector_t avr; /* SELinux access being queried */ -+ security_context_t spoolfilecon; /* SELinux context of the spool file */ -+ -+ -+ /* -+ * Validate the input to be sure there are contexts to work with... -+ */ -+ -+ if (con->scon == NULL || job->scon == NULL -+ || strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0 -+ || strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0) -+ return -1; -+ -+ if ((enforcing = security_getenforce()) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Error while determining SELinux enforcement"); -+ return -1; -+ } -+ cupsdLogJob(job, CUPSD_LOG_DEBUG, -+ "check_context: client context %s job context %s", -+ con->scon, job->scon); -+ -+ -+ /* -+ * Initialize the avc engine... -+ */ -+ -+ static int avc_initialized = 0; -+ if (! avc_initialized++) -+ { -+ if (avc_init("cupsd", NULL, NULL, NULL, NULL) < 0) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, "check_context: unable avc_init"); -+ return -1; -+ } -+ } -+ if (avc_context_to_sid(con->scon, &clisid) != 0) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "check_context: unable to convert %s to SELinux sid", -+ con->scon); -+ return -1; -+ } -+ if (avc_context_to_sid(job->scon, &jobsid) != 0) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "check_context: unable to convert %s to SELinux sid", -+ job->scon); -+ return -1; -+ } -+ avc_entry_ref_init(&avcref); -+ tclass = SECCLASS_FILE; -+ avr = FILE__READ; -+ -+ /* -+ * Perform the check with the client as the subject, first with the job as the object -+ * if that fails then with the spool file as the object... -+ */ -+ -+ if (avc_has_perm_noaudit(clisid, jobsid, tclass, avr, &avcref, NULL) != 0) -+ { -+ cupsdLogJob(job, CUPSD_LOG_INFO, -+ "check_context: SELinux denied access " -+ "based on the client context"); -+ -+ snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, job->id); -+ if (getfilecon(filename, &spoolfilecon) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "check_context: Unable to get spoolfile context"); -+ return -1; -+ } -+ if (avc_context_to_sid(spoolfilecon, &filesid) != 0) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "check_context: Unable to determine the " -+ "SELinux sid for the spool file"); -+ freecon(spoolfilecon); -+ return -1; -+ } -+ freecon(spoolfilecon); -+ if (avc_has_perm_noaudit(clisid, filesid, tclass, avr, &avcref, NULL) != 0) -+ { -+ cupsdLogJob(job, CUPSD_LOG_INFO, -+ "check_context: SELinux denied access to the spool file"); -+ return 0; -+ } -+ cupsdLogJob(job, CUPSD_LOG_INFO, -+ "check_context: SELinux allowed access to the spool file"); -+ return 1; -+ } -+ else -+ if (enforcing == 0) -+ cupsdLogJob(job, CUPSD_LOG_INFO, -+ "check_context: allowing operation due to permissive mode"); -+ else -+ cupsdLogJob(job, CUPSD_LOG_INFO, -+ "check_context: SELinux allowed access based on the " -+ "client context"); -+ -+ return 1; -+} -+#endif /* WITH_LSPP */ -+ -+ - /* - * 'check_quotas()' - Check quotas for a printer and user. - */ -@@ -4103,6 +4456,15 @@ copy_banner(cupsd_client_t *con, /* I - - char attrname[255], /* Name of attribute */ - *s; /* Pointer into name */ - ipp_attribute_t *attr; /* Attribute */ -+#ifdef WITH_LSPP -+ const char *mls_label; /* SL of print job */ -+ char *jobrange; /* SELinux sensitivity range */ -+ char *jobclearance; /* SELinux low end clearance */ -+ context_t jobcon; /* SELinux context of the job */ -+ context_t tmpcon; /* Temp context to set the level */ -+ security_context_t spoolcon; /* Context of the file in the spool */ -+#endif /* WITH_LSPP */ -+ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, -@@ -4138,6 +4500,85 @@ copy_banner(cupsd_client_t *con, /* I - - - fchmod(cupsFileNumber(out), 0640); - fchown(cupsFileNumber(out), RunUser, Group); -+#ifdef WITH_LSPP -+ if (job->scon != NULL && -+ strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0) -+ { -+ if (getfilecon(filename, &spoolcon) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to get the context of the banner file %s - %s", -+ filename, strerror(errno)); -+ job->num_files --; -+ return (0); -+ } -+ tmpcon = context_new(spoolcon); -+ jobcon = context_new(job->scon); -+ freecon(spoolcon); -+ if (!tmpcon || !jobcon) -+ { -+ if (tmpcon) -+ context_free(tmpcon); -+ if (jobcon) -+ context_free(jobcon); -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "copy_banner: Unable to get the SELinux contexts"); -+ job->num_files --; -+ return (0); -+ } -+ jobrange = (char *) context_range_get(jobcon); -+ if (jobrange) -+ { -+ jobrange = strdup(jobrange); -+ if ((jobclearance = strtok(jobrange, "-")) != NULL) -+ { -+ if (context_range_set(tmpcon, jobclearance) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "copy_banner: Unable to set the " -+ "level of the context for file %s - %s", -+ filename, strerror(errno)); -+ free(jobrange); -+ context_free(jobcon); -+ context_free(tmpcon); -+ job->num_files --; -+ return (0); -+ } -+ } -+ else -+ { -+ if (context_range_set(tmpcon, (context_range_get(jobcon))) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "copy_banner: Unable to set the " -+ "level of the context for file %s - %s", -+ filename, strerror(errno)); -+ free(jobrange); -+ context_free(jobcon); -+ context_free(tmpcon); -+ job->num_files --; -+ return (0); -+ } -+ } -+ free(jobrange); -+ } -+ if (setfilecon(filename, context_str(tmpcon)) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "copy_banner: Unable to set the " -+ "context of the banner file %s - %s", -+ filename, strerror(errno)); -+ context_free(jobcon); -+ context_free(tmpcon); -+ job->num_files --; -+ return (0); -+ } -+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "copy_banner: %s set to %s", -+ filename, context_str(tmpcon)); -+ context_free(jobcon); -+ context_free(tmpcon); -+ } -+#endif /* WITH_LSPP */ - - /* - * Try the localized banner file under the subdirectory... -@@ -4232,6 +4673,24 @@ copy_banner(cupsd_client_t *con, /* I - - else - s = attrname; - -+#ifdef WITH_LSPP -+ if (strcmp(s, "mls-label") == 0) -+ { -+ if (job->scon != NULL && strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0) -+ { -+ jobcon = context_new(job->scon); -+ if (_cups_strcasecmp(name, MLS_CONFIG) == 0) -+ mls_label = context_range_get(jobcon); -+ else if (_cups_strcasecmp(name, TE_CONFIG) == 0) -+ mls_label = context_type_get(jobcon); -+ else // default to using the whole context string -+ mls_label = context_str(jobcon); -+ cupsFilePuts(out, mls_label); -+ context_free(jobcon); -+ } -+ continue; -+ } -+#endif /* WITH_LSPP */ - if (!strcmp(s, "printer-name")) - { - cupsFilePuts(out, job->dest); -@@ -6439,6 +6898,22 @@ get_job_attrs(cupsd_client_t *con, /* I - - exclude = cupsdGetPrivateAttrs(policy, con, printer, job->username); - -+ -+#ifdef WITH_LSPP -+ /* -+ * Check SELinux... -+ */ -+ if (is_lspp_config() && check_context(con, job) != 1) -+ { -+ /* -+ * Unfortunately we have to lie to the user... -+ */ -+ send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid); -+ return; -+ } -+#endif /* WITH_LSPP */ -+ -+ - /* - * Copy attributes... - */ -@@ -6836,6 +7311,11 @@ get_jobs(cupsd_client_t *con, /* I - C - if (username[0] && _cups_strcasecmp(username, job->username)) - continue; - -+#ifdef WITH_LSPP -+ if (is_lspp_config() && check_context(con, job) != 1) -+ continue; -+#endif /* WITH_LSPP */ -+ - if (count > 0) - ippAddSeparator(con->response); - -@@ -11445,6 +11925,11 @@ validate_user(cupsd_job_t *job, /* I - - strlcpy(username, get_username(con), userlen); - -+#ifdef WITH_LSPP -+ if (is_lspp_config() && check_context(con, job) != 1) -+ return 0; -+#endif /* WITH_LSPP */ -+ - /* - * Check the username against the owner... - */ -diff -up cups-2.3.0/scheduler/job.c.lspp cups-2.3.0/scheduler/job.c ---- cups-2.3.0/scheduler/job.c.lspp 2019-10-07 12:24:43.024597707 +0200 -+++ cups-2.3.0/scheduler/job.c 2019-10-07 12:30:13.092210820 +0200 -@@ -8,6 +8,9 @@ - * information. - */ - -+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ -+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ -+ - /* - * Include necessary headers... - */ -@@ -23,6 +26,14 @@ - # endif /* HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */ - #endif /* __APPLE__ */ - -+#ifdef WITH_LSPP -+#include -+#include -+#include -+#include -+#include -+#include -+#endif /* WITH_LSPP */ - - /* - * Design Notes for Job Management -@@ -544,6 +555,14 @@ cupsdContinueJob(cupsd_job_t *job) /* I - /* PRINTER_STATE_REASONS env var */ - rip_max_cache[255]; - /* RIP_MAX_CACHE env variable */ -+#ifdef WITH_LSPP -+ char *audit_message = NULL; /* Audit message string */ -+ context_t jobcon; /* SELinux context of the job */ -+ char *label_template = NULL; /* SL to put in classification -+ env var */ -+ const char *mls_label = NULL; /* SL to put in classification -+ env var */ -+#endif /* WITH_LSPP */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, -@@ -1080,6 +1099,67 @@ cupsdContinueJob(cupsd_job_t *job) /* I - if (final_content_type[0]) - envp[envc ++] = final_content_type; - -+#ifdef WITH_LSPP -+ if (is_lspp_config()) -+ { -+ if (!job->scon || strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0) -+ { -+ if (AuditLog != -1) -+ { -+ audit_message = NULL; -+ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s title=%s", -+ job->id, job->auid, job->username, job->printer->name, title); -+ audit_log_user_message(AuditLog, AUDIT_USER_UNLABELED_EXPORT, audit_message, -+ ServerName, NULL, NULL, 1); -+ cupsdClearString(&audit_message); -+ } -+ } -+ else -+ { -+ jobcon = context_new(job->scon); -+ -+ if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME)) == NULL) -+ label_template = strdup(Classification); -+ else if (attr->num_values > 1 && -+ strcmp(attr->values[1].string.text, "none") != 0) -+ label_template = strdup(attr->values[1].string.text); -+ else -+ label_template = strdup(attr->values[0].string.text); -+ -+ if (_cups_strcasecmp(label_template, MLS_CONFIG) == 0) -+ mls_label = context_range_get(jobcon); -+ else if (_cups_strcasecmp(label_template, TE_CONFIG) == 0) -+ mls_label = context_type_get(jobcon); -+ else if (_cups_strcasecmp(label_template, SELINUX_CONFIG) == 0) -+ mls_label = context_str(jobcon); -+ else -+ mls_label = label_template; -+ -+ if (mls_label && (PerPageLabels || banner_page)) -+ { -+ snprintf(classification, sizeof(classification), "CLASSIFICATION=LSPP:%s", mls_label); -+ envp[envc ++] = classification; -+ } -+ -+ if ((AuditLog != -1) && !banner_page) -+ { -+ audit_message = NULL; -+ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s title=%s" -+ " obj=%s label=%s", job->id, job->auid, job->username, -+ job->printer->name, title, job->scon, mls_label?mls_label:"none"); -+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message, -+ ServerName, NULL, NULL, 1); -+ cupsdClearString(&audit_message); -+ } -+ context_free(jobcon); -+ free(label_template); -+ } -+ } -+ else -+ /* -+ * Fall through to the non-LSPP behavior -+ */ -+#endif /* WITH_LSPP */ - if (Classification && !banner_page) - { - if ((attr = ippFindAttribute(job->attrs, "job-sheets", -@@ -1858,6 +1938,22 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J - ippSetString(job->attrs, &job->reasons, 0, "none"); - } - -+#ifdef WITH_LSPP -+ if ((attr = ippFindAttribute(job->attrs, "security-context", IPP_TAG_NAME)) != NULL) -+ cupsdSetString(&job->scon, attr->values[0].string.text); -+ else if (is_lspp_config()) -+ { -+ /* -+ * There was no security context so delete the job -+ */ -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Missing or bad security-context attribute " -+ "in control file \"%s\"!", -+ jobfile); -+ goto error; -+ } -+#endif /* WITH_LSPP */ -+ - job->impressions = ippFindAttribute(job->attrs, "job-impressions-completed", IPP_TAG_INTEGER); - job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed", IPP_TAG_INTEGER); - job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME); -@@ -2273,6 +2369,14 @@ cupsdSaveJob(cupsd_job_t *job) /* I - J - { - char filename[1024]; /* Job control filename */ - cups_file_t *fp; /* Job file */ -+#ifdef WITH_LSPP -+ security_context_t spoolcon; /* context of the job control file */ -+ context_t jobcon; /* contex_t container for job->scon */ -+ context_t tmpcon; /* Temp context to swap the level */ -+ char *jobclearance; /* SELinux low end clearance */ -+ const char *jobrange; /* SELinux sensitivity range */ -+ char *jobrange_copy; /* SELinux sensitivity range */ -+#endif /* WITH_LSPP */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSaveJob(job=%p(%d)): job->attrs=%p", -@@ -2295,6 +2399,78 @@ cupsdSaveJob(cupsd_job_t *job) /* I - J - - fchown(cupsFileNumber(fp), RunUser, Group); - -+#ifdef WITH_LSPP -+ if (job->scon && strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0) -+ { -+ if (getfilecon(filename, &spoolcon) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to get context of job control file \"%s\" - %s.", -+ filename, strerror(errno)); -+ return; -+ } -+ jobcon = context_new(job->scon); -+ tmpcon = context_new(spoolcon); -+ freecon(spoolcon); -+ if (!jobcon || !tmpcon) -+ { -+ if (jobcon) -+ context_free(jobcon); -+ if (tmpcon) -+ context_free(tmpcon); -+ cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to get SELinux contexts"); -+ return; -+ } -+ jobrange = context_range_get(jobcon); -+ if (jobrange) -+ { -+ jobrange_copy = strdup(jobrange); -+ if ((jobclearance = strtok(jobrange_copy, "-")) != NULL) -+ { -+ if (context_range_set(tmpcon, jobclearance) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to set the range for " -+ "job control file \"%s\" - %s.", -+ filename, strerror(errno)); -+ free(jobrange_copy); -+ context_free(tmpcon); -+ context_free(jobcon); -+ return; -+ } -+ } -+ else -+ { -+ if (context_range_set(tmpcon, (context_range_get(jobcon))) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to set the range for " -+ "job control file \"%s\" - %s.", -+ filename, strerror(errno)); -+ free(jobrange_copy); -+ context_free(tmpcon); -+ context_free(jobcon); -+ return; -+ } -+ } -+ free(jobrange_copy); -+ } -+ if (setfilecon(filename, context_str(tmpcon)) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to set context of job control file \"%s\" - %s.", -+ filename, strerror(errno)); -+ context_free(tmpcon); -+ context_free(jobcon); -+ return; -+ } -+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "New spool file context=%s", -+ context_str(tmpcon)); -+ context_free(tmpcon); -+ context_free(jobcon); -+ } -+#endif /* WITH_LSPP */ -+ - job->attrs->state = IPP_IDLE; - - if (ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL, -@@ -3995,6 +4171,19 @@ get_options(cupsd_job_t *job, /* I - Jo - banner_page) - continue; - -+#ifdef WITH_LSPP -+ /* -+ * In LSPP mode refuse to honor the page-label -+ */ -+ if (is_lspp_config() && -+ !strcmp(attr->name, "page-label")) -+ { -+ cupsdLogJob(job, CUPSD_LOG_DEBUG, -+ "Ignoring page-label option due to LSPP mode"); -+ continue; -+ } -+#endif /* WITH_LSPP */ -+ - /* - * Otherwise add them to the list... - */ -@@ -4805,6 +4994,18 @@ start_job(cupsd_job_t *job, /* I - - cupsd_printer_t *printer) /* I - Printer to print job */ - { - const char *filename; /* Support filename */ -+#ifdef WITH_LSPP -+ char *audit_message = NULL; /* Audit message string */ -+ char *printerfile = NULL; /* Device file pointed to by the printer */ -+ security_id_t clisid; /* SELinux SID for the client */ -+ security_id_t psid; /* SELinux SID for the printer */ -+ context_t printercon; /* Printer's context string */ -+ struct stat printerstat; /* Printer's stat buffer */ -+ security_context_t devcon; /* Printer's SELinux context */ -+ struct avc_entry_ref avcref; /* Pointer to the access vector cache */ -+ security_class_t tclass; /* Object class for the SELinux check */ -+ access_vector_t avr; /* Access method being requested */ -+#endif /* WITH_LSPP */ - ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs, - "job-cancel-after", - IPP_TAG_INTEGER); -@@ -4993,6 +5194,113 @@ start_job(cupsd_job_t *job, /* I - - fcntl(job->side_pipes[1], F_SETFD, - fcntl(job->side_pipes[1], F_GETFD) | FD_CLOEXEC); - -+#ifdef WITH_LSPP -+ if (is_lspp_config()) -+ { -+ /* -+ * Perform an access check before printing, but only if the printer starts with /dev/ -+ */ -+ printerfile = strstr(printer->device_uri, "/dev/"); -+ if (printerfile == NULL && (strncmp(printer->device_uri, "file:/", 6) == 0)) -+ printerfile = printer->device_uri + strlen("file:"); -+ -+ if (printerfile != NULL) -+ { -+ cupsdLogJob(job, CUPSD_LOG_DEBUG, -+ "Attempting to check access on printer device %s", -+ printerfile); -+ if (lstat(printerfile, &printerstat) < 0) -+ { -+ if (errno != ENOENT) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to stat the printer"); -+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); -+ return ; -+ } -+ /* -+ * The printer does not exist, so for now assume it's a FileDevice -+ */ -+ tclass = SECCLASS_FILE; -+ avr = FILE__WRITE; -+ } -+ else if (S_ISCHR(printerstat.st_mode)) -+ { -+ tclass = SECCLASS_CHR_FILE; -+ avr = CHR_FILE__WRITE; -+ } -+ else if (S_ISREG(printerstat.st_mode)) -+ { -+ tclass = SECCLASS_FILE; -+ avr = FILE__WRITE; -+ } -+ else -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "StartJob: Printer is not a character device or " -+ "regular file"); -+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); -+ return ; -+ } -+ static int avc_initialized = 0; -+ if (!avc_initialized++) -+ avc_init("cupsd_dequeue_", NULL, NULL, NULL, NULL); -+ avc_entry_ref_init(&avcref); -+ if (avc_context_to_sid(job->scon, &clisid) != 0) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to determine the SELinux sid for the job"); -+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); -+ return ; -+ } -+ if (getfilecon(printerfile, &devcon) == -1) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to get the SELinux context of %s", -+ printerfile); -+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); -+ return ; -+ } -+ printercon = context_new(devcon); -+ cupsdLogJob(job, CUPSD_LOG_DEBUG, -+ "Printer context %s client context %s", -+ context_str(printercon), job->scon); -+ context_free(printercon); -+ -+ if (avc_context_to_sid(devcon, &psid) != 0) -+ { -+ cupsdLogJob(job, CUPSD_LOG_ERROR, -+ "Unable to determine the SELinux sid for the printer"); -+ freecon(devcon); -+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); -+ return ; -+ } -+ freecon(devcon); -+ -+ if (avc_has_perm(clisid, psid, tclass, avr, &avcref, NULL) != 0) -+ { -+ /* -+ * The access check failed, so cancel the job and send an audit message -+ */ -+ if (AuditLog != -1) -+ { -+ audit_message = NULL; -+ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s obj=%s canceled" -+ " unable to access printer=%s", job->id, -+ job->auid, (job->username)?job->username:"?", job->scon, printer->name); -+ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message, -+ ServerName, NULL, NULL, 0); -+ cupsdClearString(&audit_message); -+ } -+ -+ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); -+ -+ return ; -+ } -+ } -+ } -+#endif /* WITH_LSPP */ -+ - /* - * Now start the first file in the job... - */ -diff -up cups-2.3.0/scheduler/job.h.lspp cups-2.3.0/scheduler/job.h ---- cups-2.3.0/scheduler/job.h.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/scheduler/job.h 2019-10-07 12:29:54.364371023 +0200 -@@ -7,6 +7,13 @@ - * Licensed under Apache License v2.0. See the file "LICENSE" for more information. - */ - -+/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ -+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ -+ -+#ifdef WITH_LSPP -+#include -+#endif /* WITH_LSPP */ -+ - /* - * Constants... - */ -@@ -84,6 +91,10 @@ struct cupsd_job_s /**** Job request * - int progress; /* Printing progress */ - int num_keywords; /* Number of PPD keywords */ - cups_option_t *keywords; /* PPD keywords */ -+#ifdef WITH_LSPP -+ security_context_t scon; /* Security context of job */ -+ uid_t auid; /* Audit loginuid for this job */ -+#endif /* WITH_LSPP */ - }; - - typedef struct cupsd_joblog_s /**** Job log message ****/ -diff -up cups-2.3.0/scheduler/main.c.lspp cups-2.3.0/scheduler/main.c ---- cups-2.3.0/scheduler/main.c.lspp 2019-10-07 12:24:43.037597616 +0200 -+++ cups-2.3.0/scheduler/main.c 2019-10-07 12:24:43.119597037 +0200 -@@ -57,6 +57,9 @@ - # include - #endif /* HAVE_SYS_PARAM_H */ - -+#ifdef WITH_LSPP -+# include -+#endif /* WITH_LSPP */ - - /* - * Local functions... -@@ -123,6 +126,9 @@ main(int argc, /* I - Number of comm - #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Actions for POSIX signals */ - #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ -+#if WITH_LSPP -+ auditfail_t failmode; /* Action for audit_open failure */ -+#endif /* WITH_LSPP */ - #ifdef __APPLE__ - int use_sysman = 1; /* Use system management functions? */ - #else -@@ -495,6 +501,25 @@ main(int argc, /* I - Number of comm - exit(errno); - } - -+#ifdef WITH_LSPP -+ if ((AuditLog = audit_open()) < 0 ) -+ { -+ if (get_auditfail_action(&failmode) == 0) -+ { -+ if (failmode == FAIL_LOG) -+ { -+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to connect to audit subsystem."); -+ AuditLog = -1; -+ } -+ else if (failmode == FAIL_TERMINATE) -+ { -+ fprintf(stderr, "cupsd: unable to start auditing, terminating"); -+ return -1; -+ } -+ } -+ } -+#endif /* WITH_LSPP */ -+ - /* - * Let the system know we are busy while we bring up cupsd... - */ -@@ -1201,6 +1226,11 @@ main(int argc, /* I - Number of comm - - cupsdStopSelect(); - -+#ifdef WITH_LSPP -+ if (AuditLog != -1) -+ audit_close(AuditLog); -+#endif /* WITH_LSPP */ -+ - return (!stop_scheduler); - } - -diff -up cups-2.3.0/scheduler/printers.c.lspp cups-2.3.0/scheduler/printers.c ---- cups-2.3.0/scheduler/printers.c.lspp 2019-08-23 17:19:38.000000000 +0200 -+++ cups-2.3.0/scheduler/printers.c 2019-10-07 12:29:17.956658129 +0200 -@@ -8,6 +8,8 @@ - * information. - */ - -+/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ -+ - /* - * Include necessary headers... - */ -@@ -32,6 +34,10 @@ - # include - #endif /* __APPLE__ */ - -+#ifdef WITH_LSPP -+# include -+# include -+#endif /* WITH_LSPP */ - - /* - * Local functions... -@@ -2252,6 +2258,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) - ipp_attribute_t *attr; /* Attribute data */ - char *name, /* Current user/group name */ - *filter; /* Current filter */ -+#ifdef WITH_LSPP -+ char *audit_message; /* Audit message string */ -+ char *printerfile; /* Path to a local printer dev */ -+ char *rangestr; /* Printer's range if its available */ -+ security_context_t devcon; /* Printer SELinux context */ -+ context_t printercon; /* context_t for the printer */ -+#endif /* WITH_LSPP */ - - - /* -@@ -2378,6 +2391,45 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) - attr->values[1].string.text = _cupsStrAlloc(Classification ? - Classification : p->job_sheets[1]); - } -+#ifdef WITH_LSPP -+ if (AuditLog != -1) -+ { -+ audit_message = NULL; -+ rangestr = NULL; -+ printercon = 0; -+ printerfile = strstr(p->device_uri, "/dev/"); -+ if (printerfile == NULL && (strncmp(p->device_uri, "file:/", 6) == 0)) -+ printerfile = p->device_uri + strlen("file:"); -+ -+ if (printerfile != NULL) -+ { -+ if (getfilecon(printerfile, &devcon) == -1) -+ { -+ if(is_selinux_enabled()) -+ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdSetPrinterAttrs: Unable to get printer context"); -+ } -+ else -+ { -+ printercon = context_new(devcon); -+ freecon(devcon); -+ } -+ } -+ -+ if (printercon && context_range_get(printercon)) -+ rangestr = strdup(context_range_get(printercon)); -+ else -+ rangestr = strdup("unknown"); -+ -+ cupsdSetStringf(&audit_message, "printer=%s uri=%s banners=%s,%s range=%s", -+ p->name, p->sanitized_device_uri, p->job_sheets[0], p->job_sheets[1], rangestr); -+ audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message, -+ ServerName, NULL, NULL, 1); -+ if (printercon) -+ context_free(printercon); -+ free(rangestr); -+ cupsdClearString(&audit_message); -+ } -+#endif /* WITH_LSPP */ - } - - p->raw = 0; diff --git a/cups-no-export-ssllibs.patch b/cups-no-export-ssllibs.patch deleted file mode 100644 index 14b4426..0000000 --- a/cups-no-export-ssllibs.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff -up cups-2.2b2/config-scripts/cups-ssl.m4.no-export-ssllibs cups-2.2b2/config-scripts/cups-ssl.m4 ---- cups-2.2b2/config-scripts/cups-ssl.m4.no-export-ssllibs 2016-06-27 15:06:22.299980753 +0200 -+++ cups-2.2b2/config-scripts/cups-ssl.m4 2016-06-27 15:08:00.953154042 +0200 -@@ -102,5 +102,5 @@ AC_SUBST(IPPALIASES) - AC_SUBST(SSLFLAGS) - AC_SUBST(SSLLIBS) - --EXPORT_SSLLIBS="$SSLLIBS" -+EXPORT_SSLLIBS="" - AC_SUBST(EXPORT_SSLLIBS) diff --git a/cups-nssuserlookup-target.patch b/cups-nssuserlookup-target.patch deleted file mode 100644 index 35eff69..0000000 --- a/cups-nssuserlookup-target.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/scheduler/cups.service.in b/scheduler/cups.service.in -index a3fa0e8..baff51b 100644 ---- a/scheduler/cups.service.in -+++ b/scheduler/cups.service.in -@@ -1,7 +1,7 @@ - [Unit] - Description=CUPS Scheduler - Documentation=man:cupsd(8) --After=network.target sssd.service ypbind.service nslcd.service -+After=network.target nss-user-lookup.target nslcd.service - Requires=cups.socket - - [Service] diff --git a/cups-restart-job-hold-until.patch b/cups-restart-job-hold-until.patch deleted file mode 100644 index d235518..0000000 --- a/cups-restart-job-hold-until.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/scheduler/ipp.c b/scheduler/ipp.c -index e0dbc4a..5e9a985 100644 ---- a/scheduler/ipp.c -+++ b/scheduler/ipp.c -@@ -9891,11 +9891,10 @@ restart_job(cupsd_client_t *con, /* I - Client connection */ - cupsdLogJob(job, CUPSD_LOG_DEBUG, - "Restarted by \"%s\" with job-hold-until=%s.", - username, attr->values[0].string.text); -- cupsdSetJobHoldUntil(job, attr->values[0].string.text, 0); -- -- cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_STATE, -- NULL, job, "Job restarted by user with job-hold-until=%s", -- attr->values[0].string.text); -+ cupsdSetJobHoldUntil(job, attr->values[0].string.text, 1); -+ cupsdSetJobState(job, IPP_JOB_HELD, CUPSD_JOB_DEFAULT, -+ "Job restarted by user with job-hold-until=%s", -+ attr->values[0].string.text); - } - else - { diff --git a/cups.spec b/cups.spec index e54467b..6177bda 100644 --- a/cups.spec +++ b/cups.spec @@ -1,9 +1,8 @@ %global cups_serverbin %{_exec_prefix}/lib/cups -%global OP_VER op2 Name: cups Epoch: 1 -Version: 2.3.3%{OP_VER} +Version: 2.4.0 Release: 1 Summary: CUPS is the standards-based, open source printing system for linux operating systems. License: GPLv2+ and LGPLv2+ with exceptions and AML @@ -17,29 +16,13 @@ Source2: macros.cups Patch1: cups-system-auth.patch Patch2: cups-multilib.patch Patch3: cups-banners.patch -Patch4: cups-no-export-ssllibs.patch -Patch5: cups-direct-usb.patch -Patch6: cups-driverd-timeout.patch -Patch7: cups-usb-paperout.patch -Patch8: cups-uri-compat.patch -Patch9: cups-freebind.patch -Patch10: cups-ipp-multifile.patch -Patch11: cups-web-devices-timeout.patch -Patch12: cups-failover-backend.patch -Patch13: cups-dymo-deviceid.patch -Patch14: cups-logs.patch -Patch15: backport-backend-usb-libusb.c-Use-60s-timeout-for-reading-at-.patch -Patch16: cups-nssuserlookup-target.patch -Patch17: backport-Retry-Validate-Job-once-if-needed-Issue-132.patch -Patch18: backport-cups.service.in-Add-SYSTEMD_WANTED_BY-variable.patch -Patch19: cups-cleanfiles.patch -Patch20: backport-cgi-bin-ipp-var.c-Use-guest-user-for-Move-Job-when-n.patch -Patch21: backport-scheduler-job.c-use-gziptoany-for-raw-files-not-just.patch -Patch22: cups-restart-job-hold-until.patch -Patch23: backport-cups-md5passwd.c-Stub-out-httpMD5-functions.patch -Patch24: cups-deprecate-drivers.patch -Patch25: cups-fstack-strong.patch -Patch26: cups-lspp.patch +Patch4: cups-direct-usb.patch +Patch5: cups-driverd-timeout.patch +Patch6: cups-usb-paperout.patch +Patch7: cups-uri-compat.patch +Patch8: cups-freebind.patch +Patch9: cups-ipp-multifile.patch +Patch10: cups-web-devices-timeout.patch BuildRequires: pam-devel pkgconf-pkg-config pkgconfig(gnutls) libacl-devel openldap-devel pkgconfig(libusb-1.0) BuildRequires: krb5-devel pkgconfig(avahi-client) systemd pkgconfig(libsystemd) pkgconfig(dbus-1) python3-cups @@ -320,6 +303,8 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %{_datadir}/cups/templates/*.tmpl %dir %{_datadir}/cups/templates/de %{_datadir}/cups/templates/de/*.tmpl +%dir %{_datadir}/cups/templates/da +%{_datadir}/cups/templates/da/*.tmpl %dir %{_datadir}/cups/templates/es %{_datadir}/cups/templates/es/*.tmpl %dir %{_datadir}/cups/templates/fr @@ -335,11 +320,10 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %dir %{_datadir}/%{name}/www %{_datadir}/%{name}/www/images %{_datadir}/%{name}/www/*.css -# 1658673 - html files cannot be docs, because CUPS web ui will not have -# introduction page on Fedora Docker image (because rpms are installed -# without docs there because of space reasons) %dir %{_datadir}/%{name}/www/de +%dir %{_datadir}/%{name}/www/da %dir %{_datadir}/%{name}/www/es +%dir %{_datadir}/%{name}/www/fr %dir %{_datadir}/%{name}/www/ja %dir %{_datadir}/%{name}/www/pt_BR %dir %{_datadir}/%{name}/www/ru @@ -419,6 +403,7 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %{_libdir}/*.so %{_mandir}/man1/cups-config.1.gz %{_rpmconfigdir}/macros.d/macros.cups +%{_prefix}/lib/pkgconfig/cups.pc %files lpd %{cups_serverbin}/daemon/cups-lpd @@ -450,13 +435,18 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %doc %{_datadir}/%{name}/www/help %doc %{_datadir}/%{name}/www/robots.txt %doc %{_datadir}/%{name}/www/de/index.html +%doc %{_datadir}/%{name}/www/da/index.html %doc %{_datadir}/%{name}/www/es/index.html +%doc %{_datadir}/%{name}/www/fr/index.html %doc %{_datadir}/%{name}/www/ja/index.html %doc %{_datadir}/%{name}/www/ru/index.html %doc %{_datadir}/%{name}/www/pt_BR/index.html %doc %{_datadir}/%{name}/www/apple-touch-icon.png %changelog +* Thu Sep 9 2021 hanhui - 2.4.0-1 +- DESC:update to cups-2.4.0 + * Mon Nov 29 2021 hanhui - 2.3.3op2-1 - DESC:update to cups-2.3.3op2 @@ -531,4 +521,3 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb * Wed Sep 18 2019 Guan Yanjie - 2.2.8-6 - Package init -