diff --git a/backport-0001-CVE-2024-47175.patch b/backport-0001-CVE-2024-47175.patch deleted file mode 100644 index 61a4e04577c3ab29473c971876c217985bb3a4c0..0000000000000000000000000000000000000000 --- a/backport-0001-CVE-2024-47175.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 9939a70b750edd9d05270060cc5cf62ca98cfbe5 Mon Sep 17 00:00:00 2001 -From: Michael R Sweet -Date: Mon, 9 Sep 2024 10:03:10 -0400 -Subject: [PATCH] Mirror IPP Everywhere printer changes from master. - ---- - cups/ppd-cache.c | 10 +++++----- - scheduler/ipp.c | 9 ++++++++- - 2 files changed, 13 insertions(+), 6 deletions(-) - ---- a/cups/ppd-cache.c -+++ b/cups/ppd-cache.c -@@ -4350,10 +4350,10 @@ _ppdCreateFromIPP2( - } - cupsFilePuts(fp, "\"\n"); - -- if ((attr = ippFindAttribute(supported, "printer-more-info", IPP_TAG_URI)) != NULL) -+ if ((attr = ippFindAttribute(supported, "printer-more-info", IPP_TAG_URI)) != NULL && ippValidateAttribute(attr)) - cupsFilePrintf(fp, "*APSupplies: \"%s\"\n", ippGetString(attr, 0, NULL)); - -- if ((attr = ippFindAttribute(supported, "printer-charge-info-uri", IPP_TAG_URI)) != NULL) -+ if ((attr = ippFindAttribute(supported, "printer-charge-info-uri", IPP_TAG_URI)) != NULL && ippValidateAttribute(attr)) - cupsFilePrintf(fp, "*cupsChargeInfoURI: \"%s\"\n", ippGetString(attr, 0, NULL)); - - if ((attr = ippFindAttribute(supported, "printer-strings-uri", IPP_TAG_URI)) != NULL) -@@ -4422,10 +4422,10 @@ _ppdCreateFromIPP2( - if (ippGetBoolean(ippFindAttribute(supported, "job-accounting-user-id-supported", IPP_TAG_BOOLEAN), 0)) - cupsFilePuts(fp, "*cupsJobAccountingUserId: True\n"); - -- if ((attr = ippFindAttribute(supported, "printer-privacy-policy-uri", IPP_TAG_URI)) != NULL) -+ if ((attr = ippFindAttribute(supported, "printer-privacy-policy-uri", IPP_TAG_URI)) != NULL && ippValidateAttribute(attr)) - cupsFilePrintf(fp, "*cupsPrivacyURI: \"%s\"\n", ippGetString(attr, 0, NULL)); - -- if ((attr = ippFindAttribute(supported, "printer-mandatory-job-attributes", IPP_TAG_KEYWORD)) != NULL) -+ if ((attr = ippFindAttribute(supported, "printer-mandatory-job-attributes", IPP_TAG_KEYWORD)) != NULL && ippValidateAttribute(attr)) - { - char prefix = '\"'; // Prefix for string - -@@ -4443,7 +4443,7 @@ _ppdCreateFromIPP2( - cupsFilePuts(fp, "\"\n"); - } - -- if ((attr = ippFindAttribute(supported, "printer-requested-job-attributes", IPP_TAG_KEYWORD)) != NULL) -+ if ((attr = ippFindAttribute(supported, "printer-requested-job-attributes", IPP_TAG_KEYWORD)) != NULL && ippValidateAttribute(attr)) - { - char prefix = '\"'; // Prefix for string - ---- a/scheduler/ipp.c -+++ b/scheduler/ipp.c -@@ -1,7 +1,7 @@ - /* - * IPP routines for the CUPS scheduler. - * -- * Copyright © 2020-2023 by OpenPrinting -+ * Copyright © 2020-2024 by OpenPrinting - * Copyright © 2007-2021 by Apple Inc. - * Copyright © 1997-2007 by Easy Software Products, all rights reserved. - * -@@ -5413,6 +5413,13 @@ create_local_bg_thread( - } - } - -+ // Validate response from printer... -+ if (!ippValidateAttributes(response)) -+ { -+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Printer returned invalid data: %s"), cupsLastErrorString()); -+ goto finish_response; -+ } -+ - // TODO: Grab printer icon file... - httpClose(http); - diff --git a/backport-0002-CVE-2024-47175.patch b/backport-0002-CVE-2024-47175.patch deleted file mode 100644 index 592bb08678672a5d651ad0feb4bac1f4fdd8944f..0000000000000000000000000000000000000000 --- a/backport-0002-CVE-2024-47175.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 04bb2af4521b56c1699a2c2431c56c05a7102e69 Mon Sep 17 00:00:00 2001 -From: Michael R Sweet -Date: Mon, 9 Sep 2024 14:05:42 -0400 -Subject: [PATCH] Refactor make-and-model code. - ---- - cups/ppd-cache.c | 103 +++++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 87 insertions(+), 16 deletions(-) - ---- a/cups/ppd-cache.c -+++ b/cups/ppd-cache.c -@@ -4230,9 +4230,10 @@ _ppdCreateFromIPP2( - ipp_t *media_col, /* Media collection */ - *media_size; /* Media size collection */ - char make[256], /* Make and model */ -- *model, /* Model name */ -+ *mptr, /* Pointer into make and model */ - ppdname[PPD_MAX_NAME]; - /* PPD keyword */ -+ const char *model; /* Model name */ - int i, j, /* Looping vars */ - count, /* Number of values */ - bottom, /* Largest bottom margin */ -@@ -4293,34 +4294,104 @@ _ppdCreateFromIPP2( - } - - /* -- * Standard stuff for PPD file... -+ * Get a sanitized make and model... - */ - -- cupsFilePuts(fp, "*PPD-Adobe: \"4.3\"\n"); -- cupsFilePuts(fp, "*FormatVersion: \"4.3\"\n"); -- cupsFilePrintf(fp, "*FileVersion: \"%d.%d\"\n", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR); -- cupsFilePuts(fp, "*LanguageVersion: English\n"); -- cupsFilePuts(fp, "*LanguageEncoding: ISOLatin1\n"); -- cupsFilePuts(fp, "*PSVersion: \"(3010.000) 0\"\n"); -- cupsFilePuts(fp, "*LanguageLevel: \"3\"\n"); -- cupsFilePuts(fp, "*FileSystem: False\n"); -- cupsFilePuts(fp, "*PCFileName: \"ippeve.ppd\"\n"); -+ if ((attr = ippFindAttribute(supported, "printer-make-and-model", IPP_TAG_TEXT)) != NULL && ippValidateAttribute(attr)) -+ { -+ /* -+ * Sanitize the model name to only contain PPD-safe characters. -+ */ - -- if ((attr = ippFindAttribute(supported, "printer-make-and-model", IPP_TAG_TEXT)) != NULL) - strlcpy(make, ippGetString(attr, 0, NULL), sizeof(make)); -+ -+ for (mptr = make; *mptr; mptr ++) -+ { -+ if (*mptr < ' ' || *mptr >= 127 || *mptr == '\"') -+ { -+ /* -+ * Truncate the make and model on the first bad character... -+ */ -+ -+ *mptr = '\0'; -+ break; -+ } -+ } -+ -+ while (mptr > make) -+ { -+ /* -+ * Strip trailing whitespace... -+ */ -+ -+ mptr --; -+ if (*mptr == ' ') -+ *mptr = '\0'; -+ } -+ -+ if (!make[0]) -+ { -+ /* -+ * Use a default make and model if nothing remains... -+ */ -+ -+ strlcpy(make, "Unknown", sizeof(make)); -+ } -+ } - else -- strlcpy(make, "Unknown Printer", sizeof(make)); -+ { -+ /* -+ * Use a default make and model... -+ */ -+ -+ strlcpy(make, "Unknown", sizeof(make)); -+ } - - if (!_cups_strncasecmp(make, "Hewlett Packard ", 16) || !_cups_strncasecmp(make, "Hewlett-Packard ", 16)) - { -+ /* -+ * Normalize HP printer make and model... -+ */ -+ - model = make + 16; - strlcpy(make, "HP", sizeof(make)); -+ -+ if (!_cups_strncasecmp(model, "HP ", 3)) -+ model += 3; -+ } -+ else if ((mptr = strchr(make, ' ')) != NULL) -+ { -+ /* -+ * Separate "MAKE MODEL"... -+ */ -+ -+ while (*mptr && *mptr == ' ') -+ *mptr++ = '\0'; -+ -+ model = mptr; - } -- else if ((model = strchr(make, ' ')) != NULL) -- *model++ = '\0'; - else -- model = make; -+ { -+ /* -+ * No separate model name... -+ */ -+ -+ model = "Printer"; -+ } -+ -+ /* -+ * Standard stuff for PPD file... -+ */ - -+ cupsFilePuts(fp, "*PPD-Adobe: \"4.3\"\n"); -+ cupsFilePuts(fp, "*FormatVersion: \"4.3\"\n"); -+ cupsFilePrintf(fp, "*FileVersion: \"%d.%d\"\n", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR); -+ cupsFilePuts(fp, "*LanguageVersion: English\n"); -+ cupsFilePuts(fp, "*LanguageEncoding: ISOLatin1\n"); -+ cupsFilePuts(fp, "*PSVersion: \"(3010.000) 0\"\n"); -+ cupsFilePuts(fp, "*LanguageLevel: \"3\"\n"); -+ cupsFilePuts(fp, "*FileSystem: False\n"); -+ cupsFilePuts(fp, "*PCFileName: \"ippeve.ppd\"\n"); - cupsFilePrintf(fp, "*Manufacturer: \"%s\"\n", make); - cupsFilePrintf(fp, "*ModelName: \"%s\"\n", model); - cupsFilePrintf(fp, "*Product: \"(%s)\"\n", model); diff --git a/backport-0003-CVE-2024-47175.patch b/backport-0003-CVE-2024-47175.patch deleted file mode 100644 index 0580c149e4d262d56a4e25d361ce47be658c0008..0000000000000000000000000000000000000000 --- a/backport-0003-CVE-2024-47175.patch +++ /dev/null @@ -1,111 +0,0 @@ -From e0630cd18f76340d302000f2bf6516e99602b844 Mon Sep 17 00:00:00 2001 -From: Michael R Sweet -Date: Mon, 9 Sep 2024 15:59:57 -0400 -Subject: [PATCH] PPDize preset and template names. - ---- - cups/ppd-cache.c | 33 ++++++++++++++++++++++++--------- - 1 file changed, 24 insertions(+), 9 deletions(-) - ---- a/cups/ppd-cache.c -+++ b/cups/ppd-cache.c -@@ -5993,12 +5993,14 @@ _ppdCreateFromIPP2( - - cupsArrayAdd(templates, (void *)keyword); - -+ pwg_ppdize_name(keyword, ppdname, sizeof(ppdname)); -+ - snprintf(msgid, sizeof(msgid), "finishing-template.%s", keyword); - if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) - if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) - msgstr = keyword; - -- cupsFilePrintf(fp, "*cupsFinishingTemplate %s: \"\n", keyword); -+ cupsFilePrintf(fp, "*cupsFinishingTemplate %s: \"\n", ppdname); - for (finishing_attr = ippFirstAttribute(finishing_col); finishing_attr; finishing_attr = ippNextAttribute(finishing_col)) - { - if (ippGetValueTag(finishing_attr) == IPP_TAG_BEGIN_COLLECTION) -@@ -6011,7 +6013,7 @@ _ppdCreateFromIPP2( - } - } - cupsFilePuts(fp, "\"\n"); -- cupsFilePrintf(fp, "*%s.cupsFinishingTemplate %s/%s: \"\"\n", lang->language, keyword, msgstr); -+ cupsFilePrintf(fp, "*%s.cupsFinishingTemplate %s/%s: \"\"\n", lang->language, ppdname, msgstr); - cupsFilePuts(fp, "*End\n"); - } - -@@ -6057,7 +6059,8 @@ _ppdCreateFromIPP2( - if (!preset || !preset_name) - continue; - -- cupsFilePrintf(fp, "*APPrinterPreset %s: \"\n", preset_name); -+ pwg_ppdize_name(preset_name, ppdname, sizeof(ppdname)); -+ cupsFilePrintf(fp, "*APPrinterPreset %s: \"\n", ppdname); - for (member = ippFirstAttribute(preset); member; member = ippNextAttribute(preset)) - { - member_name = ippGetName(member); -@@ -6098,7 +6101,10 @@ _ppdCreateFromIPP2( - fin_col = ippGetCollection(member, i); - - if ((keyword = ippGetString(ippFindAttribute(fin_col, "finishing-template", IPP_TAG_ZERO), 0, NULL)) != NULL) -- cupsFilePrintf(fp, "*cupsFinishingTemplate %s\n", keyword); -+ { -+ pwg_ppdize_name(keyword, ppdname, sizeof(ppdname)); -+ cupsFilePrintf(fp, "*cupsFinishingTemplate %s\n", ppdname); -+ } - } - } - else if (!strcmp(member_name, "media")) -@@ -6125,13 +6131,13 @@ _ppdCreateFromIPP2( - if ((keyword = ippGetString(ippFindAttribute(media_col, "media-source", IPP_TAG_ZERO), 0, NULL)) != NULL) - { - pwg_ppdize_name(keyword, ppdname, sizeof(ppdname)); -- cupsFilePrintf(fp, "*InputSlot %s\n", keyword); -+ cupsFilePrintf(fp, "*InputSlot %s\n", ppdname); - } - - if ((keyword = ippGetString(ippFindAttribute(media_col, "media-type", IPP_TAG_ZERO), 0, NULL)) != NULL) - { - pwg_ppdize_name(keyword, ppdname, sizeof(ppdname)); -- cupsFilePrintf(fp, "*MediaType %s\n", keyword); -+ cupsFilePrintf(fp, "*MediaType %s\n", ppdname); - } - } - else if (!strcmp(member_name, "print-quality")) -@@ -6177,7 +6183,10 @@ _ppdCreateFromIPP2( - cupsFilePuts(fp, "\"\n*End\n"); - - if ((localized_name = _cupsMessageLookup(strings, preset_name)) != preset_name) -- cupsFilePrintf(fp, "*%s.APPrinterPreset %s/%s: \"\"\n", lang->language, preset_name, localized_name); -+ { -+ pwg_ppdize_name(preset_name, ppdname, sizeof(ppdname)); -+ cupsFilePrintf(fp, "*%s.APPrinterPreset %s/%s: \"\"\n", lang->language, ppdname, localized_name); -+ } - } - } - -@@ -6561,7 +6570,7 @@ pwg_ppdize_name(const char *ipp, /* I - - *end; /* End of name buffer */ - - -- if (!ipp) -+ if (!ipp || !_cups_isalnum(*ipp)) - { - *name = '\0'; - return; -@@ -6576,8 +6585,14 @@ pwg_ppdize_name(const char *ipp, /* I - - ipp ++; - *ptr++ = (char)toupper(*ipp++ & 255); - } -- else -+ else if (*ipp == '_' || *ipp == '.' || *ipp == '-' || _cups_isalnum(*ipp)) -+ { - *ptr++ = *ipp++; -+ } -+ else -+ { -+ ipp ++; -+ } - } - - *ptr = '\0'; diff --git a/backport-0004-CVE-2024-47175.patch b/backport-0004-CVE-2024-47175.patch deleted file mode 100644 index e516be761bbbad3579ad2564281db273ba2add4e..0000000000000000000000000000000000000000 --- a/backport-0004-CVE-2024-47175.patch +++ /dev/null @@ -1,241 +0,0 @@ -From 1e6ca5913eceee906038bc04cc7ccfbe2923bdfd Mon Sep 17 00:00:00 2001 -From: Michael R Sweet -Date: Mon, 23 Sep 2024 09:36:39 -0400 -Subject: [PATCH] Quote PPD localized strings. - ---- - cups/ppd-cache.c | 93 +++++++++++++++++++++++++++--------------------- - 1 file changed, 53 insertions(+), 40 deletions(-) - ---- a/cups/ppd-cache.c -+++ b/cups/ppd-cache.c -@@ -32,6 +32,7 @@ - static int cups_connect(http_t **http, const char *url, char *resource, size_t ressize); - static int cups_get_url(http_t **http, const char *url, char *name, size_t namesize); - static const char *ppd_inputslot_for_keyword(_ppd_cache_t *pc, const char *keyword); -+static void ppd_put_string(cups_file_t *fp, cups_lang_t *lang, cups_array_t *strings, const char *ppd_option, const char *ppd_choice, const char *pwg_msgid); - static void pwg_add_finishing(cups_array_t *finishings, ipp_finishings_t template, const char *name, const char *value); - static void pwg_add_message(cups_array_t *a, const char *msg, const char *str); - static int pwg_compare_finishings(_pwg_finishings_t *a, _pwg_finishings_t *b); -@@ -4427,7 +4428,7 @@ _ppdCreateFromIPP2( - if ((attr = ippFindAttribute(supported, "printer-charge-info-uri", IPP_TAG_URI)) != NULL && ippValidateAttribute(attr)) - cupsFilePrintf(fp, "*cupsChargeInfoURI: \"%s\"\n", ippGetString(attr, 0, NULL)); - -- if ((attr = ippFindAttribute(supported, "printer-strings-uri", IPP_TAG_URI)) != NULL) -+ if ((attr = ippFindAttribute(supported, "printer-strings-uri", IPP_TAG_URI)) != NULL && ippValidateAttribute(attr)) - { - http_t *http = NULL; /* Connection to printer */ - char stringsfile[1024]; /* Temporary strings file */ -@@ -4471,7 +4472,7 @@ _ppdCreateFromIPP2( - - response = cupsDoRequest(http, request, resource); - -- if ((attr = ippFindAttribute(response, "printer-strings-uri", IPP_TAG_URI)) != NULL) -+ if ((attr = ippFindAttribute(response, "printer-strings-uri", IPP_TAG_URI)) != NULL && ippValidateAttribute(attr)) - cupsFilePrintf(fp, "*cupsStringsURI %s: \"%s\"\n", keyword, ippGetString(attr, 0, NULL)); - - ippDelete(response); -@@ -5061,18 +5062,16 @@ _ppdCreateFromIPP2( - cupsFilePrintf(fp, "*DefaultInputSlot: %s\n", ppdname); - - for (j = 0; j < (int)(sizeof(sources) / sizeof(sources[0])); j ++) -+ { - if (!strcmp(sources[j], keyword)) - { - snprintf(msgid, sizeof(msgid), "media-source.%s", keyword); - -- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) -- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) -- msgstr = keyword; -- - cupsFilePrintf(fp, "*InputSlot %s: \"<>setpagedevice\"\n", ppdname, j); -- cupsFilePrintf(fp, "*%s.InputSlot %s/%s: \"\"\n", lang->language, ppdname, msgstr); -+ ppd_put_string(fp, lang, strings, "InputSlot", ppdname, msgid); - break; - } -+ } - } - cupsFilePuts(fp, "*CloseUI: *InputSlot\n"); - } -@@ -5098,12 +5097,9 @@ _ppdCreateFromIPP2( - pwg_ppdize_name(keyword, ppdname, sizeof(ppdname)); - - snprintf(msgid, sizeof(msgid), "media-type.%s", keyword); -- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) -- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) -- msgstr = keyword; - - cupsFilePrintf(fp, "*MediaType %s: \"<>setpagedevice\"\n", ppdname, ppdname); -- cupsFilePrintf(fp, "*%s.MediaType %s/%s: \"\"\n", lang->language, ppdname, msgstr); -+ ppd_put_string(fp, lang, strings, "MediaType", ppdname, msgid); - } - cupsFilePuts(fp, "*CloseUI: *MediaType\n"); - } -@@ -5564,12 +5560,9 @@ _ppdCreateFromIPP2( - pwg_ppdize_name(keyword, ppdname, sizeof(ppdname)); - - snprintf(msgid, sizeof(msgid), "output-bin.%s", keyword); -- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) -- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) -- msgstr = keyword; - - cupsFilePrintf(fp, "*OutputBin %s: \"\"\n", ppdname); -- cupsFilePrintf(fp, "*%s.OutputBin %s/%s: \"\"\n", lang->language, ppdname, msgstr); -+ ppd_put_string(fp, lang, strings, "OutputBin", ppdname, msgid); - - if ((tray_ptr = ippGetOctetString(trays, i, &tray_len)) != NULL) - { -@@ -5688,9 +5681,6 @@ _ppdCreateFromIPP2( - cupsArrayAdd(names, (char *)keyword); - - snprintf(msgid, sizeof(msgid), "finishings.%d", value); -- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) -- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) -- msgstr = keyword; - - if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE) - ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE]; -@@ -5705,7 +5695,7 @@ _ppdCreateFromIPP2( - continue; - - cupsFilePrintf(fp, "*StapleLocation %s: \"\"\n", ppd_keyword); -- cupsFilePrintf(fp, "*%s.StapleLocation %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr); -+ ppd_put_string(fp, lang, strings, "StapleLocation", ppd_keyword, msgid); - cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*StapleLocation %s\"\n", value, keyword, ppd_keyword); - } - -@@ -5768,9 +5758,6 @@ _ppdCreateFromIPP2( - cupsArrayAdd(names, (char *)keyword); - - snprintf(msgid, sizeof(msgid), "finishings.%d", value); -- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) -- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) -- msgstr = keyword; - - if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE) - ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE]; -@@ -5785,7 +5772,7 @@ _ppdCreateFromIPP2( - continue; - - cupsFilePrintf(fp, "*FoldType %s: \"\"\n", ppd_keyword); -- cupsFilePrintf(fp, "*%s.FoldType %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr); -+ ppd_put_string(fp, lang, strings, "FoldType", ppd_keyword, msgid); - cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*FoldType %s\"\n", value, keyword, ppd_keyword); - } - -@@ -5856,9 +5843,6 @@ _ppdCreateFromIPP2( - cupsArrayAdd(names, (char *)keyword); - - snprintf(msgid, sizeof(msgid), "finishings.%d", value); -- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) -- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) -- msgstr = keyword; - - if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE) - ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE]; -@@ -5873,7 +5857,7 @@ _ppdCreateFromIPP2( - continue; - - cupsFilePrintf(fp, "*PunchMedia %s: \"\"\n", ppd_keyword); -- cupsFilePrintf(fp, "*%s.PunchMedia %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr); -+ ppd_put_string(fp, lang, strings, "PunchMedia", ppd_keyword, msgid); - cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*PunchMedia %s\"\n", value, keyword, ppd_keyword); - } - -@@ -5944,9 +5928,6 @@ _ppdCreateFromIPP2( - cupsArrayAdd(names, (char *)keyword); - - snprintf(msgid, sizeof(msgid), "finishings.%d", value); -- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) -- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) -- msgstr = keyword; - - if (value == IPP_FINISHINGS_TRIM) - ppd_keyword = "Auto"; -@@ -5954,7 +5935,7 @@ _ppdCreateFromIPP2( - ppd_keyword = trim_keywords[value - IPP_FINISHINGS_TRIM_AFTER_PAGES]; - - cupsFilePrintf(fp, "*CutMedia %s: \"\"\n", ppd_keyword); -- cupsFilePrintf(fp, "*%s.CutMedia %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr); -+ ppd_put_string(fp, lang, strings, "CutMedia", ppd_keyword, msgid); - cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*CutMedia %s\"\n", value, keyword, ppd_keyword); - } - -@@ -5996,9 +5977,6 @@ _ppdCreateFromIPP2( - pwg_ppdize_name(keyword, ppdname, sizeof(ppdname)); - - snprintf(msgid, sizeof(msgid), "finishing-template.%s", keyword); -- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr)) -- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid) -- msgstr = keyword; - - cupsFilePrintf(fp, "*cupsFinishingTemplate %s: \"\n", ppdname); - for (finishing_attr = ippFirstAttribute(finishing_col); finishing_attr; finishing_attr = ippNextAttribute(finishing_col)) -@@ -6013,7 +5991,7 @@ _ppdCreateFromIPP2( - } - } - cupsFilePuts(fp, "\"\n"); -- cupsFilePrintf(fp, "*%s.cupsFinishingTemplate %s/%s: \"\"\n", lang->language, ppdname, msgstr); -+ ppd_put_string(fp, lang, strings, "cupsFinishingTemplate", ppdname, msgid); - cupsFilePuts(fp, "*End\n"); - } - -@@ -6182,11 +6160,9 @@ _ppdCreateFromIPP2( - - cupsFilePuts(fp, "\"\n*End\n"); - -- if ((localized_name = _cupsMessageLookup(strings, preset_name)) != preset_name) -- { -- pwg_ppdize_name(preset_name, ppdname, sizeof(ppdname)); -- cupsFilePrintf(fp, "*%s.APPrinterPreset %s/%s: \"\"\n", lang->language, ppdname, localized_name); -- } -+ snprintf(msgid, sizeof(msgid), "preset-name.%s", preset_name); -+ pwg_ppdize_name(preset_name, ppdname, sizeof(ppdname)); -+ ppd_put_string(fp, lang, strings, "APPrinterPreset", ppdname, msgid); - } - } - -@@ -6457,6 +6433,43 @@ cups_get_url(http_t **http, /* IO - - } - - -+/* -+ * 'ppd_put_strings()' - Write localization attributes to a PPD file. -+ */ -+ -+static void -+ppd_put_string(cups_file_t *fp, /* I - PPD file */ -+ cups_lang_t *lang, /* I - Language */ -+ cups_array_t *strings, /* I - Strings */ -+ const char *ppd_option,/* I - PPD option */ -+ const char *ppd_choice,/* I - PPD choice */ -+ const char *pwg_msgid) /* I - PWG message ID */ -+{ -+ const char *text; /* Localized text */ -+ -+ -+ if ((text = _cupsLangString(lang, pwg_msgid)) == pwg_msgid || !strcmp(pwg_msgid, text)) -+ { -+ if ((text = _cupsMessageLookup(strings, pwg_msgid)) == pwg_msgid) -+ return; -+ } -+ -+ // Add the first line of localized text... -+ cupsFilePrintf(fp, "*%s.%s %s/", lang->language, ppd_option, ppd_choice); -+ while (*text && *text != '\n') -+ { -+ // Escape ":" and "<"... -+ if (*text == ':' || *text == '<') -+ cupsFilePrintf(fp, "<%02X>", *text); -+ else -+ cupsFilePutChar(fp, *text); -+ -+ text ++; -+ } -+ cupsFilePuts(fp, ": \"\"\n"); -+} -+ -+ - /* - * 'pwg_add_finishing()' - Add a finishings value. - */ diff --git a/backport-0005-CVE-2024-47175.patch b/backport-0005-CVE-2024-47175.patch deleted file mode 100644 index aae3f561713b50ecf20f03189b2f0623703651ac..0000000000000000000000000000000000000000 --- a/backport-0005-CVE-2024-47175.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 2abe1ba8a66864aa82cd9836b37e57103b8e1a3b Mon Sep 17 00:00:00 2001 -From: Michael R Sweet -Date: Mon, 23 Sep 2024 10:11:31 -0400 -Subject: [PATCH] Fix warnings for unused vars. - ---- - cups/ppd-cache.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - ---- a/cups/ppd-cache.c -+++ b/cups/ppd-cache.c -@@ -4256,8 +4256,7 @@ _ppdCreateFromIPP2( - int have_qdraft = 0,/* Have draft quality? */ - have_qhigh = 0; /* Have high quality? */ - char msgid[256]; /* Message identifier (attr.value) */ -- const char *keyword, /* Keyword value */ -- *msgstr; /* Localized string */ -+ const char *keyword; /* Keyword value */ - cups_array_t *strings = NULL;/* Printer strings file */ - struct lconv *loc = localeconv(); - /* Locale data */ -@@ -6027,9 +6026,8 @@ _ppdCreateFromIPP2( - { - ipp_t *preset = ippGetCollection(attr, i); - /* Preset collection */ -- const char *preset_name = ippGetString(ippFindAttribute(preset, "preset-name", IPP_TAG_ZERO), 0, NULL), -+ const char *preset_name = ippGetString(ippFindAttribute(preset, "preset-name", IPP_TAG_ZERO), 0, NULL); - /* Preset name */ -- *localized_name; /* Localized preset name */ - ipp_attribute_t *member; /* Member attribute in preset */ - const char *member_name; /* Member attribute name */ - char member_value[256]; /* Member attribute value */ diff --git a/backport-Fix-CVE-2024-35235-regression.patch b/backport-Fix-CVE-2024-35235-regression.patch deleted file mode 100644 index 9482e7ef7a28a2495f124fc662f45fcbf0626f40..0000000000000000000000000000000000000000 --- a/backport-Fix-CVE-2024-35235-regression.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 6131f6a73c188f3db0ec94ae488991ce80cfd7ea Mon Sep 17 00:00:00 2001 -From: Michael R Sweet -Date: Fri, 14 Jun 2024 15:10:21 -0400 -Subject: [PATCH] Don't abort early if there are no listen sockets after - loading cupsd.conf (Issue #985) - ---- - scheduler/conf.c | 2 +- - scheduler/main.c | 17 +++++++++++++++++ - 2 files changed, 18 insertions(+), 1 deletion(-) - -diff --git a/scheduler/conf.c b/scheduler/conf.c -index ebf8ca8ccd..34b30e56d1 100644 ---- a/scheduler/conf.c -+++ b/scheduler/conf.c -@@ -1048,7 +1048,7 @@ cupsdReadConfiguration(void) - * as an error and exit! - */ - -- if (cupsArrayCount(Listeners) == 0) -+ if (cupsArrayCount(Listeners) == 0 && !OnDemand) - { - /* - * No listeners! -diff --git a/scheduler/main.c b/scheduler/main.c -index 4472863081..70f3159df6 100644 ---- a/scheduler/main.c -+++ b/scheduler/main.c -@@ -2036,6 +2036,23 @@ service_checkin(void) - service_add_listener(fd, 0); - } - #endif /* HAVE_LAUNCHD */ -+ -+ if (cupsArrayCount(Listeners) == 0) -+ { -+ /* -+ * No listeners! -+ */ -+ -+ cupsdLogMessage(CUPSD_LOG_EMERG, -+ "No valid Listen or Port lines were found in the " -+ "configuration file."); -+ -+ /* -+ * Commit suicide... -+ */ -+ -+ cupsdEndProcess(getpid(), 0); -+ } - } - - diff --git a/backport-Fix-CVE-2024-35235.patch b/backport-Fix-CVE-2024-35235.patch deleted file mode 100644 index 9a41790f9ecd9cc68d0c73f765a32ab962fe2e12..0000000000000000000000000000000000000000 --- a/backport-Fix-CVE-2024-35235.patch +++ /dev/null @@ -1,95 +0,0 @@ -From a436956f374b0fd7f5da9df482e4f5840fa1c0d2 Mon Sep 17 00:00:00 2001 -From: Zdenek Dohnal -Date: Mon, 3 Jun 2024 18:53:58 +020 -Subject: [PATCH] Fix domain socket handling -Reference: https://github.com/OpenPrinting/cups/commit/a436956f374b0fd7f5da9df482e4f5840fa1c0d2 - ---- - cups/http-addr.c | 37 +++++++++++++++++++------------------ - scheduler/conf.c | 19 +++++++++++++++++++ - 2 files changed, 38 insertions(+), 18 deletions(-) - -diff --git a/cups/http-addr.c b/cups/http-addr.c -index 254857c..29a821f 100644 ---- a/cups/http-addr.c -+++ b/cups/http-addr.c -@@ -210,27 +210,28 @@ httpAddrListen(http_addr_t *addr, /* I - Address to bind to */ - * Remove any existing domain socket file... - */ - -- unlink(addr->un.sun_path); -- -- /* -- * Save the current umask and set it to 0 so that all users can access -- * the domain socket... -- */ -- -- mask = umask(0); -- -- /* -- * Bind the domain socket... -- */ -+ if ((status = unlink(addr->un.sun_path)) < 0) -+ { -+ DEBUG_printf(("1httpAddrListen: Unable to unlink \"%s\": %s", addr->un.sun_path, strerror(errno))); - -- status = bind(fd, (struct sockaddr *)addr, (socklen_t)httpAddrLength(addr)); -+ if (errno == ENOENT) -+ status = 0; -+ } - -- /* -- * Restore the umask and fix permissions... -- */ -+ if (!status) -+ { -+ // Save the current umask and set it to 0 so that all users can access -+ // the domain socket... -+ mask = umask(0); -+ // Bind the domain socket... -+ if ((status = bind(fd, (struct sockaddr *)addr, (socklen_t)httpAddrLength(addr))) < 0) -+ { -+ DEBUG_printf(("1httpAddrListen: Unable to bind domain socket \"%s\": %s", addr->un.sun_path, strerror(errno))); -+ } - -- umask(mask); -- chmod(addr->un.sun_path, 0140777); -+ // Restore the umask... -+ umask(mask); -+ } - } - else - #endif /* AF_LOCAL */ -diff --git a/scheduler/conf.c b/scheduler/conf.c -index 4fa7eb1..8e54c47 100644 ---- a/scheduler/conf.c -+++ b/scheduler/conf.c -@@ -3082,6 +3082,25 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ - - cupsd_listener_t *lis; /* New listeners array */ - -+ /* -+ * If we are launched on-demand, do not use domain sockets from the config -+ * file. Also check that the domain socket path is not too long... -+ */ -+ -+#ifdef HAVE_ONDEMAND -+ if (*value == '/' && OnDemand) -+ { -+ if (strcmp(value, CUPS_DEFAULT_DOMAINSOCKET)) -+ cupsdLogMessage(CUPSD_LOG_INFO, "Ignoring %s address %s at line %d - only using domain socket from launchd/systemd.", line, value, linenum); -+ continue; -+ } -+#endif // HAVE_ONDEMAND -+ -+ if (*value == '/' && strlen(value) > (sizeof(addr->addr.un.sun_path) - 1)) -+ { -+ cupsdLogMessage(CUPSD_LOG_INFO, "Ignoring %s address %s at line %d - too long.", line, value, linenum); -+ continue; -+ } - - /* - * Get the address list... --- -2.27.0 - diff --git a/backport-delay-creating-driverless-printer-until-ppd-generated.patch b/backport-delay-creating-driverless-printer-until-ppd-generated.patch deleted file mode 100644 index 4c3ce864ca06606d1fe3869733d2a4ec06f6ef33..0000000000000000000000000000000000000000 --- a/backport-delay-creating-driverless-printer-until-ppd-generated.patch +++ /dev/null @@ -1,1121 +0,0 @@ -From df3718b09f395d59b454e0aa233490ba7f2aa857 Mon Sep 17 00:00:00 2001 -From: Michael R Sweet -Date: Thu, 4 Apr 2024 16:25:25 -0400 -Subject: [PATCH] Update CUPS-Add-Modify-Printer and CUPS-Create-Local-Printer - code to delay responding until the PPD is successfully generated (Issue #347) - ---- - scheduler/auth.c | 15 +- - scheduler/auth.h | 2 - - scheduler/client.h | 2 + - scheduler/cupsd.h | 9 + - scheduler/ipp.c | 383 ++++++++++++++++++++++++++++--------------- - scheduler/policy.h | 2 - - scheduler/printers.c | 6 +- - scheduler/printers.h | 2 - - 8 files changed, 271 insertions(+), 150 deletions(-) - ---- a/scheduler/auth.c -+++ b/scheduler/auth.c -@@ -105,7 +105,7 @@ - cupsd_authmask_t temp; /* New host/domain mask */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddIPMask(masks=%p(%p), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)", masks, *masks, address[0], address[1], address[2], address[3], netmask[0], netmask[1], netmask[2], netmask[3]); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddIPMask(masks=%p(%p), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)", (void *)masks, (void *)*masks, address[0], address[1], address[2], address[3], netmask[0], netmask[1], netmask[2], netmask[3]); - - temp.type = CUPSD_AUTH_IP; - memcpy(temp.mask.ip.address, address, sizeof(temp.mask.ip.address)); -@@ -158,7 +158,7 @@ - cupsdAddName(cupsd_location_t *loc, /* I - Location to add to */ - char *name) /* I - Name to add */ - { -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddName(loc=%p, name=\"%s\")", loc, name); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddName(loc=%p, name=\"%s\")", (void *)loc, name); - - if (!loc->names) - loc->names = cupsArrayNew3(NULL, NULL, NULL, 0, -@@ -188,7 +188,7 @@ - *ifptr; /* Pointer to end of name */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddNameMask(masks=%p(%p), name=\"%s\")", masks, *masks, name); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddNameMask(masks=%p(%p), name=\"%s\")", (void *)masks, (void *)*masks, name); - - if (!_cups_strcasecmp(name, "@LOCAL")) - { -@@ -274,7 +274,7 @@ - con->best = cupsdFindBest(con->uri, httpGetState(con->http)); - con->type = CUPSD_AUTH_NONE; - -- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "con->uri=\"%s\", con->best=%p(%s)", con->uri, con->best, con->best ? con->best->location : ""); -+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "con->uri=\"%s\", con->best=%p(%s)", con->uri, (void *)con->best, con->best ? con->best->location : ""); - - if (con->best && con->best->type != CUPSD_AUTH_NONE) - { -@@ -1143,7 +1143,7 @@ - #endif /* HAVE_MBR_UID_TO_UUID */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckGroup(username=\"%s\", user=%p, groupname=\"%s\")", username, user, groupname); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckGroup(username=\"%s\", user=%p, groupname=\"%s\")", username, (void *)user, groupname); - - /* - * Validate input... -@@ -1558,7 +1558,7 @@ - }; - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: con->uri=\"%s\", con->best=%p(%s)", con->uri, con->best, con->best ? con->best->location ? con->best->location : "(null)" : ""); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: con->uri=\"%s\", con->best=%p(%s)", con->uri, (void *)con->best, con->best ? con->best->location ? con->best->location : "(null)" : ""); - if (owner) - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: owner=\"%s\"", owner); - -@@ -2129,7 +2129,6 @@ - - free(snap_name); - g_clear_object(&snap); -- - # endif // CUPS_SNAP - - done: -@@ -2140,6 +2139,8 @@ - return (ret); - - #else -+ (void)con; -+ - // No AppArmor/snapd to deal with... - return (1); - #endif // HAVE_LIBAPPARMOR && HAVE_LIBSNAPDGLIB ---- a/scheduler/auth.h -+++ b/scheduler/auth.h -@@ -98,8 +98,6 @@ - http_encryption_t encryption; /* To encrypt or not to encrypt... */ - } cupsd_location_t; - --typedef struct cupsd_client_s cupsd_client_t; -- - - /* - * Globals... ---- a/scheduler/client.h -+++ b/scheduler/client.h -@@ -42,6 +42,8 @@ - *query_string; /* QUERY_STRING environment variable */ - int file; /* Input/output file */ - int file_ready; /* Input ready on file/pipe? */ -+ int bg_pending; /* Background response pending? */ -+ cupsd_printer_t *bg_printer; /* Background printer */ - int pipe_pid; /* Pipe process ID (or 0 if not a pipe) */ - http_status_t pipe_status; /* HTTP status from pipe process */ - int sent_header, /* Non-zero if sent HTTP header */ ---- a/scheduler/cupsd.h -+++ b/scheduler/cupsd.h -@@ -100,6 +100,15 @@ - - - /* -+ * Base types... -+ */ -+ -+typedef struct cupsd_client_s cupsd_client_t; -+typedef struct cupsd_job_s cupsd_job_t; -+typedef struct cupsd_printer_s cupsd_printer_t; -+ -+ -+/* - * Other stuff for the scheduler... - */ - ---- a/scheduler/ipp.c -+++ b/scheduler/ipp.c -@@ -73,7 +73,7 @@ - cups_array_t *ra, - cups_array_t *exclude); - static void create_job(cupsd_client_t *con, ipp_attribute_t *uri); --static void *create_local_bg_thread(cupsd_printer_t *printer); -+static void *create_local_bg_thread(cupsd_client_t *con); - static void create_local_printer(cupsd_client_t *con); - static cups_array_t *create_requested_array(ipp_t *request); - static void create_subscriptions(cupsd_client_t *con, ipp_attribute_t *uri); -@@ -111,6 +111,7 @@ - static void send_http_error(cupsd_client_t *con, http_status_t status, - cupsd_printer_t *printer); - static void send_ipp_status(cupsd_client_t *con, ipp_status_t status, const char *message, ...) _CUPS_FORMAT(3, 4); -+static int send_response(cupsd_client_t *con); - static void set_default(cupsd_client_t *con, ipp_attribute_t *uri); - static void set_job_attrs(cupsd_client_t *con, ipp_attribute_t *uri); - static void set_printer_attrs(cupsd_client_t *con, ipp_attribute_t *uri); -@@ -143,7 +144,7 @@ - int valid = 1; /* Valid request? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdProcessIPPRequest(%p[%d]): operation_id=%04x(%s)", con, con->number, con->request->request.op.operation_id, ippOpString(con->request->request.op.operation_id)); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdProcessIPPRequest(%p[%d]): operation_id=%04x(%s)", (void *)con, con->number, con->request->request.op.operation_id, ippOpString(con->request->request.op.operation_id)); - - if (LogLevel >= CUPSD_LOG_DEBUG2) - { -@@ -615,68 +616,13 @@ - } - } - -- if (con->response) -+ if (!con->bg_pending && con->response) - { - /* - * Sending data from the scheduler... - */ - -- cupsdLogClient(con, con->response->request.status.status_code >= IPP_STATUS_ERROR_BAD_REQUEST && con->response->request.status.status_code != IPP_STATUS_ERROR_NOT_FOUND ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, "Returning IPP %s for %s (%s) from %s.", ippErrorString(con->response->request.status.status_code), ippOpString(con->request->request.op.operation_id), uri ? uri->values[0].string.text : "no URI", con->http->hostname); -- -- httpClearFields(con->http); -- --#ifdef CUPSD_USE_CHUNKING -- /* -- * Because older versions of CUPS (1.1.17 and older) and some IPP -- * clients do not implement chunking properly, we cannot use -- * chunking by default. This may become the default in future -- * CUPS releases, or we might add a configuration directive for -- * it. -- */ -- -- if (con->http->version == HTTP_1_1) -- { -- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Transfer-Encoding: chunked"); -- cupsdSetLength(con->http, 0); -- } -- else --#endif /* CUPSD_USE_CHUNKING */ -- { -- size_t length; /* Length of response */ -- -- -- length = ippLength(con->response); -- -- if (con->file >= 0 && !con->pipe_pid) -- { -- struct stat fileinfo; /* File information */ -- -- if (!fstat(con->file, &fileinfo)) -- length += (size_t)fileinfo.st_size; -- } -- -- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Content-Length: " CUPS_LLFMT, CUPS_LLCAST length); -- httpSetLength(con->http, length); -- } -- -- if (cupsdSendHeader(con, HTTP_OK, "application/ipp", CUPSD_AUTH_NONE)) -- { -- /* -- * Tell the caller the response header was sent successfully... -- */ -- -- cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, (cupsd_selfunc_t)cupsdWriteClient, con); -- -- return (1); -- } -- else -- { -- /* -- * Tell the caller the response header could not be sent... -- */ -- -- return (0); -- } -+ return (send_response(con)); - } - else - { -@@ -747,7 +693,7 @@ - cupsd_printer_t *printer; /* Printer data */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "accept_jobs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "accept_jobs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -832,7 +778,7 @@ - int need_restart_job; /* Need to restart job? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_class(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_class(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -1142,7 +1088,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "add_file(con=%p[%d], job=%d, filetype=%s/%s, " -- "compression=%d)", con, con ? con->number : -1, job->id, -+ "compression=%d)", (void *)con, con ? con->number : -1, job->id, - filetype->super, filetype->type, compression); - - /* -@@ -1245,8 +1191,8 @@ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))", -- con, con->number, printer, printer->name, -- filetype, filetype ? filetype->super : "none", -+ (void *)con, con->number, (void *)printer, printer->name, -+ (void *)filetype, filetype ? filetype->super : "none", - filetype ? filetype->type : "none"); - - /* -@@ -2226,7 +2172,7 @@ - set_port_monitor; /* Did we set the port monitor? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -2717,8 +2663,21 @@ - return; - } - -- // Run a background thread to create the PPD... -- _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, printer); -+ if (!printer->printer_id) -+ printer->printer_id = NextPrinterId ++; -+ -+ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); -+ -+ cupsdSetPrinterAttrs(printer); -+ -+ /* Run a background thread to create the PPD... */ -+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Creating PPD in background thread."); -+ -+ con->bg_pending = 1; -+ con->bg_printer = printer; -+ -+ _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, con); -+ return; - } - else if (!strcmp(ppd_name, "raw")) - { -@@ -2883,7 +2842,7 @@ - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "add_printer_state_reasons(%p[%d], %p[%s])", -- con, con->number, p, p->name); -+ (void *)con, con->number, (void *)p, p->name); - - if (p->num_reasons == 0) - ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, -@@ -2909,7 +2868,7 @@ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_queued_job_count(%p[%d], %p[%s])", -- con, con->number, p, p->name); -+ (void *)con, con->number, (void *)p, p->name); - - count = cupsdGetPrinterJobCount(p->name); - -@@ -2999,7 +2958,7 @@ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "authenticate_job(%p[%d], %s)", -- con, con->number, uri->values[0].string.text); -+ (void *)con, con->number, uri->values[0].string.text); - - /* - * Start with "everything is OK" status... -@@ -3177,7 +3136,7 @@ - cupsd_job_t *job; /* Job */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_all_jobs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_all_jobs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -3414,7 +3373,7 @@ - cupsd_jobaction_t purge; /* Purge the job? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_job(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_job(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -3615,7 +3574,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cancel_subscription(con=%p[%d], sub_id=%d)", -- con, con->number, sub_id); -+ (void *)con, con->number, sub_id); - - /* - * Is the subscription ID valid? -@@ -3721,7 +3680,7 @@ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "check_quotas(%p[%d], %p[%s])", -- con, con->number, p, p->name); -+ (void *)con, con->number, (void *)p, p->name); - - /* - * Figure out who is printing... -@@ -3943,7 +3902,7 @@ - username[256]; /* User name */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "close_job(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "close_job(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -4063,7 +4022,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "copy_attrs(to=%p, from=%p, ra=%p, group=%x, quickcopy=%d)", -- to, from, ra, group, quickcopy); -+ (void *)to, (void *)from, (void *)ra, group, quickcopy); - - if (!to || !from) - return; -@@ -4147,7 +4106,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "copy_banner(con=%p[%d], job=%p[%d], name=\"%s\")", -- con, con ? con->number : -1, job, job->id, -+ (void *)con, con ? con->number : -1, (void *)job, job->id, - name ? name : "(null)"); - - /* -@@ -4492,7 +4451,7 @@ - /* cupsProtocol attribute */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_model(con=%p, from=\"%s\", to=\"%s\")", con, from, to); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_model(con=%p, from=\"%s\", to=\"%s\")", (void *)con, from, to); - - /* - * Run cups-driverd to get the PPD file... -@@ -5106,7 +5065,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "copy_subscription_attrs(con=%p, sub=%p, ra=%p, exclude=%p)", -- con, sub, ra, exclude); -+ (void *)con, (void *)sub, (void *)ra, (void *)exclude); - - /* - * Copy the subscription attributes to the response using the -@@ -5220,7 +5179,7 @@ - }; - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "create_job(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "create_job(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -5285,11 +5244,14 @@ - - static void * /* O - Exit status */ - create_local_bg_thread( -- cupsd_printer_t *printer) /* I - Printer */ -+ cupsd_client_t *con) /* I - Client */ - { -+ cupsd_printer_t *printer = con->bg_printer; -+ /* Printer */ - cups_file_t *from, /* Source file */ - *to; /* Destination file */ -- char fromppd[1024], /* Source PPD */ -+ char device_uri[1024], /* Device URI */ -+ fromppd[1024], /* Source PPD */ - toppd[1024], /* Destination PPD */ - scheme[32], /* URI scheme */ - userpass[256], /* User:pass */ -@@ -5301,7 +5263,7 @@ - http_encryption_t encryption; /* Type of encryption to use */ - http_t *http; /* Connection to printer */ - ipp_t *request, /* Request to printer */ -- *response; /* Response from printer */ -+ *response = NULL; /* Response from printer */ - ipp_attribute_t *attr; /* Attribute in response */ - ipp_status_t status; /* Status code */ - static const char * const pattrs[] = /* Printer attributes we need */ -@@ -5315,26 +5277,47 @@ - * Try connecting to the printer... - */ - -- cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Generating PPD file from \"%s\"...", printer->name, printer->device_uri); -+ _cupsRWLockRead(&printer->lock); -+ strlcpy(device_uri, printer->device_uri, sizeof(device_uri)); -+ _cupsRWUnlock(&printer->lock); - -+ cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Generating PPD file from \"%s\"...", printer->name, device_uri); - -- if (strstr(printer->device_uri, "._tcp")) -+ if (strstr(device_uri, "._tcp")) - { -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "%s: Resolving mDNS URI \"%s\".", printer->name, printer->device_uri); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "%s: Resolving mDNS URI \"%s\".", printer->name, device_uri); - -- if (!_httpResolveURI(printer->device_uri, uri, sizeof(uri), _HTTP_RESOLVE_DEFAULT, NULL, NULL)) -+ if (!_httpResolveURI(device_uri, uri, sizeof(uri), _HTTP_RESOLVE_DEFAULT, NULL, NULL)) - { -- cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Couldn't resolve mDNS URI \"%s\".", printer->name, printer->device_uri); -- return (NULL); -+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Couldn't resolve mDNS URI \"%s\".", printer->name, device_uri); -+ -+ /* Force printer to timeout and be deleted */ -+ _cupsRWLockWrite(&printer->lock); -+ printer->state_time = 0; -+ _cupsRWUnlock(&printer->lock); -+ -+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Couldn't resolve mDNS URI \"%s\"."), printer->device_uri); -+ goto finish_response; - } - -+ _cupsRWLockWrite(&printer->lock); - cupsdSetString(&printer->device_uri, uri); -+ _cupsRWUnlock(&printer->lock); -+ -+ strlcpy(device_uri, uri, sizeof(device_uri)); - } - -- if (httpSeparateURI(HTTP_URI_CODING_ALL, printer->device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) -+ if (httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) - { -- cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Bad device URI \"%s\".", printer->name, printer->device_uri); -- return (NULL); -+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Bad device URI \"%s\".", printer->name, device_uri); -+ -+ /* Force printer to timeout and be deleted */ -+ _cupsRWLockWrite(&printer->lock); -+ printer->state_time = 0; -+ _cupsRWUnlock(&printer->lock); -+ -+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Bad device URI \"%s\"."), device_uri); -+ goto finish_response; - } - - if (!strcmp(scheme, "ipps") || port == 443) -@@ -5345,7 +5328,14 @@ - if ((http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to connect to %s:%d: %s", printer->name, host, port, cupsLastErrorString()); -- return (NULL); -+ -+ /* Force printer to timeout and be deleted */ -+ _cupsRWLockWrite(&printer->lock); -+ printer->state_time = 0; -+ _cupsRWUnlock(&printer->lock); -+ -+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Unable to connect to %s:%d: %s"), host, port, cupsLastErrorString()); -+ goto finish_response; - } - - /* -@@ -5389,6 +5379,7 @@ - * If we did not succeed to obtain the "media-col-database" attribute - * try to get it separately - */ -+ - if (ippFindAttribute(response, "media-col-database", IPP_TAG_ZERO) == - NULL) - { -@@ -5447,17 +5438,29 @@ - if ((from = cupsFileOpen(fromppd, "r")) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to read generated PPD: %s", printer->name, strerror(errno)); -- ippDelete(response); -- return (NULL); -+ -+ /* Force printer to timeout and be deleted */ -+ _cupsRWLockWrite(&printer->lock); -+ printer->state_time = 0; -+ _cupsRWUnlock(&printer->lock); -+ -+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Unable to read generated PPD: %s"), strerror(errno)); -+ goto finish_response; - } - - snprintf(toppd, sizeof(toppd), "%s/ppd/%s.ppd", ServerRoot, printer->name); - if ((to = cupsdCreateConfFile(toppd, ConfigFilePerm)) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to create PPD for printer: %s", printer->name, strerror(errno)); -- ippDelete(response); - cupsFileClose(from); -- return (NULL); -+ -+ /* Force printer to timeout and be deleted */ -+ _cupsRWLockWrite(&printer->lock); -+ printer->state_time = 0; -+ _cupsRWUnlock(&printer->lock); -+ -+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Unable to create PPD for printer: %s"), strerror(errno)); -+ goto finish_response; - } - - while (cupsFileGets(from, line, sizeof(line))) -@@ -5466,10 +5469,14 @@ - cupsFileClose(from); - if (!cupsdCloseCreatedConfFile(to, toppd)) - { -+ _cupsRWLockWrite(&printer->lock); -+ - printer->config_time = time(NULL); - printer->state = IPP_PSTATE_IDLE; - printer->accepting = 1; - -+ _cupsRWUnlock(&printer->lock); -+ - cupsdSetPrinterAttrs(printer); - - cupsdAddEvent(CUPSD_EVENT_PRINTER_CONFIG, printer, NULL, "Printer \"%s\" is now available.", printer->name); -@@ -5477,10 +5484,39 @@ - } - } - else -+ { - cupsdLogMessage(CUPSD_LOG_ERROR, "%s: PPD creation failed: %s", printer->name, cupsLastErrorString()); - -+ /* Force printer to timeout and be deleted */ -+ _cupsRWLockWrite(&printer->lock); -+ printer->state_time = 0; -+ _cupsRWUnlock(&printer->lock); -+ -+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Unable to create PPD: %s"), cupsLastErrorString()); -+ goto finish_response; -+ } -+ -+ /* -+ * Respond to the client... -+ */ -+ -+ send_ipp_status(con, IPP_STATUS_OK, _("Local printer created.")); -+ -+ ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting); -+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", (int)printer->state); -+ add_printer_state_reasons(con, printer); -+ -+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), httpIsEncrypted(con->http) ? "ipps" : "ipp", NULL, con->clientname, con->clientport, "/printers/%s", printer->name); -+ ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", NULL, uri); -+ -+ finish_response: -+ - ippDelete(response); - -+ send_response(con); -+ -+ con->bg_pending = 0; -+ - return (NULL); - } - -@@ -5592,10 +5628,21 @@ - - if ((printer = cupsdFindDest(name)) != NULL) - { -- send_ipp_status(con, IPP_STATUS_ERROR_NOT_POSSIBLE, _("Printer \"%s\" already exists."), name); -+ printer->state_time = time(NULL); -+ send_ipp_status(con, IPP_STATUS_OK, _("Printer \"%s\" already exists."), name); - goto add_printer_attributes; - } - -+ for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers); printer; printer = (cupsd_printer_t *)cupsArrayNext(Printers)) -+ { -+ if (printer->device_uri && !strcmp(ptr, printer->device_uri)) -+ { -+ printer->state_time = time(NULL); -+ send_ipp_status(con, IPP_STATUS_OK, _("Printer \"%s\" already exists."), printer->name); -+ goto add_printer_attributes; -+ } -+ } -+ - /* - * Create the printer... - */ -@@ -5682,14 +5729,17 @@ - * Run a background thread to create the PPD... - */ - -- _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, printer); -+ con->bg_pending = 1; -+ con->bg_printer = printer; -+ -+ _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, con); -+ -+ return; - - /* - * Return printer attributes... - */ - -- send_ipp_status(con, IPP_STATUS_OK, _("Local printer created.")); -- - add_printer_attributes: - - ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting); -@@ -5795,7 +5845,7 @@ - * Is the destination valid? - */ - -- cupsdLogMessage(CUPSD_LOG_DEBUG, "create_subscriptions(con=%p(%d), uri=\"%s\")", con, con->number, uri->values[0].string.text); -+ cupsdLogMessage(CUPSD_LOG_DEBUG, "create_subscriptions(con=%p(%d), uri=\"%s\")", (void *)con, con->number, uri->values[0].string.text); - - httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme, - sizeof(scheme), userpass, sizeof(userpass), host, -@@ -6143,7 +6193,7 @@ - int temporary; /* Temporary queue? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "delete_printer(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "delete_printer(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -6256,7 +6306,7 @@ - cups_array_t *ra; /* Requested attributes array */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_default(%p[%d])", con, con->number); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_default(%p[%d])", (void *)con, con->number); - - /* - * Check policy... -@@ -6306,7 +6356,7 @@ - /* String for included schemes */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", con, con->number); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", (void *)con, con->number); - - /* - * Check policy... -@@ -6399,7 +6449,7 @@ - format[1024]; /* Format for document */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_document(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_document(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -6546,7 +6596,7 @@ - *exclude; /* Private attributes array */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_job_attrs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_job_attrs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -6677,7 +6727,7 @@ - cupsd_policy_t *policy; /* Current policy */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs(%p[%d], %s)", con, con->number, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs(%p[%d], %s)", (void *)con, con->number, - uri->values[0].string.text); - - /* -@@ -6988,7 +7038,7 @@ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "get_jobs: job->id=%d, dest=\"%s\", username=\"%s\", " - "state_value=%d, attrs=%p", job->id, job->dest, -- job->username, job->state_value, job->attrs); -+ job->username, job->state_value, (void *)job->attrs); - - if (!job->dest || !job->username) - cupsdLoadJob(job); -@@ -7067,7 +7117,7 @@ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_notifications(con=%p[%d])", -- con, con->number); -+ (void *)con, con->number); - - /* - * Get subscription attributes... -@@ -7200,8 +7250,8 @@ - cups_ptype_t dtype; /* Destination type */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", con, -- con->number, uri, uri->name, uri->values[0].string.text); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", (void *)con, -+ con->number, (void *)uri, uri->name, uri->values[0].string.text); - - if (!strcmp(ippGetName(uri), "ppd-name")) - { -@@ -7373,7 +7423,7 @@ - /* String for included schemes */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->number); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", (void *)con, con->number); - - /* - * Check policy... -@@ -7517,7 +7567,7 @@ - cups_array_t *ra; /* Requested attributes array */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_attrs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_attrs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -7573,7 +7623,7 @@ - cupsd_printer_t *printer; /* Printer/class */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_supported(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_supported(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -7643,7 +7693,7 @@ - int local; /* Local connection? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printers(%p[%d], %x)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printers(%p[%d], %x)", (void *)con, - con->number, type); - - /* -@@ -7804,7 +7854,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "get_subscription_attrs(con=%p[%d], sub_id=%d)", -- con, con->number, sub_id); -+ (void *)con, con->number, sub_id); - - /* - * Expire subscriptions as needed... -@@ -7891,7 +7941,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "get_subscriptions(con=%p[%d], uri=%s)", -- con, con->number, uri->values[0].string.text); -+ (void *)con, con->number, uri->values[0].string.text); - - /* - * Is the destination valid? -@@ -8059,7 +8109,7 @@ - cupsd_job_t *job; /* Job information */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_job(%p[%d], %s)", con, con->number, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_job(%p[%d], %s)", (void *)con, con->number, - uri->values[0].string.text); - - /* -@@ -8190,7 +8240,7 @@ - cupsd_printer_t *printer; /* Printer data */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_new_jobs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_new_jobs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -8267,7 +8317,7 @@ - *dprinter; /* Destination printer */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "move_job(%p[%d], %s)", con, con->number, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "move_job(%p[%d], %s)", (void *)con, con->number, - uri->values[0].string.text); - - /* -@@ -8596,7 +8646,7 @@ - int compression; /* Document compression */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "print_job(%p[%d], %s)", con, con->number, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "print_job(%p[%d], %s)", (void *)con, con->number, - uri->values[0].string.text); - - /* -@@ -9047,7 +9097,7 @@ - ipp_attribute_t *attr; /* printer-state-message text */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "reject_jobs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "reject_jobs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -9129,7 +9179,7 @@ - cupsd_printer_t *printer; /* Printer data */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_held_new_jobs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_held_new_jobs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -9202,7 +9252,7 @@ - cupsd_job_t *job; /* Job information */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_job(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_job(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -9339,7 +9389,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "renew_subscription(con=%p[%d], sub_id=%d)", -- con, con->number, sub_id); -+ (void *)con, con->number, sub_id); - - /* - * Is the subscription ID valid? -@@ -9426,7 +9476,7 @@ - int port; /* Port portion of URI */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "restart_job(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "restart_job(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -9777,7 +9827,7 @@ - int start_job; /* Start the job? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_document(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_document(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -10289,6 +10339,82 @@ - - - /* -+ * 'send_response()' - Send the IPP response. -+ */ -+ -+static int /* O - 1 on success, 0 on failure */ -+send_response(cupsd_client_t *con) /* I - Client */ -+{ -+ ipp_attribute_t *uri; /* Target URI */ -+ int ret = 0; /* Return value */ -+ static _cups_mutex_t mutex = _CUPS_MUTEX_INITIALIZER; -+ /* Mutex for logging/access */ -+ -+ -+ _cupsMutexLock(&mutex); -+ -+ if ((uri = ippFindAttribute(con->request, "printer-uri", IPP_TAG_URI)) == NULL) -+ { -+ if ((uri = ippFindAttribute(con->request, "job-uri", IPP_TAG_URI)) == NULL) -+ uri = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME); -+ } -+ -+ cupsdLogClient(con, con->response->request.status.status_code >= IPP_STATUS_ERROR_BAD_REQUEST && con->response->request.status.status_code != IPP_STATUS_ERROR_NOT_FOUND ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, "Returning IPP %s for %s (%s) from %s.", ippErrorString(con->response->request.status.status_code), ippOpString(con->request->request.op.operation_id), uri ? uri->values[0].string.text : "no URI", con->http->hostname); -+ -+ httpClearFields(con->http); -+ -+#ifdef CUPSD_USE_CHUNKING -+ /* -+ * Because older versions of CUPS (1.1.17 and older) and some IPP -+ * clients do not implement chunking properly, we cannot use -+ * chunking by default. This may become the default in future -+ * CUPS releases, or we might add a configuration directive for -+ * it. -+ */ -+ -+ if (con->http->version == HTTP_1_1) -+ { -+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Transfer-Encoding: chunked"); -+ cupsdSetLength(con->http, 0); -+ } -+ else -+#endif /* CUPSD_USE_CHUNKING */ -+ { -+ size_t length; /* Length of response */ -+ -+ -+ length = ippLength(con->response); -+ -+ if (con->file >= 0 && !con->pipe_pid) -+ { -+ struct stat fileinfo; /* File information */ -+ -+ if (!fstat(con->file, &fileinfo)) -+ length += (size_t)fileinfo.st_size; -+ } -+ -+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Content-Length: " CUPS_LLFMT, CUPS_LLCAST length); -+ httpSetLength(con->http, length); -+ } -+ -+ if (cupsdSendHeader(con, HTTP_STATUS_OK, "application/ipp", CUPSD_AUTH_NONE)) -+ { -+ /* -+ * Tell the caller the response header was sent successfully... -+ */ -+ -+ cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, (cupsd_selfunc_t)cupsdWriteClient, con); -+ -+ ret = 1; -+ } -+ -+ _cupsMutexUnlock(&mutex); -+ -+ return (ret); -+} -+ -+ -+/* - * 'set_default()' - Set the default destination... - */ - -@@ -10302,7 +10428,7 @@ - *oldprinter; /* Old default printer */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -10384,7 +10510,7 @@ - int check_jobs; /* Check jobs? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -10764,7 +10890,7 @@ - int changed = 0; /* Was anything changed? */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_printer_attrs(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_printer_attrs(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -11110,7 +11236,7 @@ - cupsd_printer_t *printer; /* Printer data */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_printer(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_printer(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -11192,7 +11318,7 @@ - ipp_attribute_t *attr; /* printer-state-message attribute */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "stop_printer(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "stop_printer(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -11434,7 +11560,7 @@ - cupsd_printer_t *printer; /* Printer */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_job(%p[%d], %s)", con, -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_job(%p[%d], %s)", (void *)con, - con->number, uri->values[0].string.text); - - /* -@@ -11627,7 +11753,7 @@ - cupsd_printer_t *printer; /* Printer for job */ - - -- cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_user(job=%d, con=%d, owner=\"%s\", username=%p, userlen=" CUPS_LLFMT ")", job->id, con ? con->number : 0, owner ? owner : "(null)", username, CUPS_LLCAST userlen); -+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_user(job=%d, con=%d, owner=\"%s\", username=%p, userlen=" CUPS_LLFMT ")", job->id, con ? con->number : 0, owner ? owner : "(null)", (void *)username, CUPS_LLCAST userlen); - - /* - * Validate input... ---- a/scheduler/policy.h -+++ b/scheduler/policy.h -@@ -22,8 +22,6 @@ - *ops; /* Operations */ - } cupsd_policy_t; - --typedef struct cupsd_printer_s cupsd_printer_t; -- - - /* - * Globals... ---- a/scheduler/printers.c -+++ b/scheduler/printers.c -@@ -620,7 +620,7 @@ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeletePrinter(p=%p(%s), update=%d)", -- p, p->name, update); -+ (void *)p, p->name, update); - - /* - * Save the current position in the Printers array... -@@ -782,11 +782,11 @@ - "cupsdDeleteTemporaryPrinters: Removing unused temporary printers"); - - /* -- * Allow temporary printers to stick around for 60 seconds after the last job -+ * Allow temporary printers to stick around for 5 minutes after the last job - * completes. - */ - -- unused_time = time(NULL) - 60; -+ unused_time = time(NULL) - 300; - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { -@@ -2550,7 +2550,7 @@ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, -- "cupsdSetPrinterReasons(p=%p(%s),s=\"%s\"", p, p->name, s); -+ "cupsdSetPrinterReasons(p=%p(%s),s=\"%s\"", (void *)p, p->name, s); - - if (s[0] == '-' || s[0] == '+') - { -@@ -3396,7 +3396,7 @@ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "add_printer_filter(p=%p(%s), filtertype=%p(%s/%s), " -- "filter=\"%s\")", p, p->name, filtertype, filtertype->super, -+ "filter=\"%s\")", (void *)p, p->name, (void *)filtertype, filtertype->super, - filtertype->type, filter); - - /* ---- a/scheduler/printers.h -+++ b/scheduler/printers.h -@@ -50,8 +50,6 @@ - * Printer/class information structure... - */ - --typedef struct cupsd_job_s cupsd_job_t; -- - struct cupsd_printer_s - { - _cups_rwlock_t lock; /* Concurrency lock for background updates */ ---- a/scheduler/client.c -+++ b/scheduler/client.c -@@ -430,6 +430,14 @@ - con->file = -1; - } - -+ if (con->bg_pending) -+ { -+ /* -+ * Don't close connection when there is a background thread pending -+ */ -+ partial = 1; -+ } -+ - /* - * Close the socket and clear the file from the input set for select()... - */ diff --git a/cups-2.4.7-source.tar.gz b/cups-2.4.11-source.tar.gz similarity index 53% rename from cups-2.4.7-source.tar.gz rename to cups-2.4.11-source.tar.gz index fea8d377aba092b611dfa1b8cac3c6737f2d33bf..f1343908e2ce06b4921d49291a6f1fedce166f10 100644 Binary files a/cups-2.4.7-source.tar.gz and b/cups-2.4.11-source.tar.gz differ diff --git a/cups-lspp.patch b/cups-lspp.patch new file mode 100644 index 0000000000000000000000000000000000000000..1c64970fe308880b598fe3f8a8491c84f7e46eab --- /dev/null +++ b/cups-lspp.patch @@ -0,0 +1,2040 @@ +diff --git a/Makedefs.in b/Makedefs.in +index 9211338..8a1e0be 100644 +--- a/Makedefs.in ++++ b/Makedefs.in +@@ -162,7 +162,7 @@ ARFLAGS = @ARFLAGS@ + BACKLIBS = @BACKLIBS@ + BUILDDIRS = @BUILDDIRS@ + CFLAGS = @CPPFLAGS@ @CFLAGS@ +-COMMONLIBS = @LIBS@ ++COMMONLIBS = @LIBS@ @LIBAUDIT@ @LIBSELINUX@ + CXXFLAGS = @CPPFLAGS@ @CXXFLAGS@ + CXXLIBS = @CXXLIBS@ + DBUS_NOTIFIER = @DBUS_NOTIFIER@ +diff --git a/config-scripts/cups-lspp.m4 b/config-scripts/cups-lspp.m4 +new file mode 100644 +index 0000000..55bd1bb +--- /dev/null ++++ b/config-scripts/cups-lspp.m4 +@@ -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 --git a/config.h.in b/config.h.in +index 6940b96..363780a 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -684,6 +684,13 @@ static __inline int _cups_abs(int i) { return (i < 0 ? -i : i); } + #endif /* !HAVE_ABS && !abs */ + + ++/* ++ * Are we trying to meet LSPP requirements? ++ */ ++ ++#undef WITH_LSPP ++ ++ + /* + * Building as a snap (snapcraft.io)? + */ +diff --git a/configure.ac b/configure.ac +index 3b5dd73..0e61044 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -40,6 +40,8 @@ sinclude(config-scripts/cups-container.m4) + sinclude(config-scripts/cups-startup.m4) + sinclude(config-scripts/cups-defaults.m4) + ++sinclude(config-scripts/cups-lspp.m4) ++ + dnl See what languages are available and make sure we generate the localization + dnl files as needed... + INSTALL_LANGUAGES="" +diff --git a/filter/common.c b/filter/common.c +index 22217be..b8629e6 100644 +--- a/filter/common.c ++++ b/filter/common.c +@@ -12,6 +12,12 @@ + * Include necessary headers... + */ + ++#include "config.h" ++#ifdef WITH_LSPP ++#define _GNU_SOURCE ++#include ++#endif /* WITH_LSPP */ ++ + #include "common.h" + #include + +@@ -294,6 +300,18 @@ WriteLabelProlog(const char *label, /* I - Page label */ + { + 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 */ + + + /* +@@ -316,6 +334,128 @@ WriteLabelProlog(const char *label, /* I - Page label */ + 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... + */ +@@ -396,7 +536,10 @@ WriteLabelProlog(const char *label, /* I - Page label */ + printf(" %.0f moveto ESPpl show\n", top - 14.0); + puts("pop"); + puts("}bind put"); ++ } ++#ifdef WITH_LSPP + } ++#endif /* WITH_LSPP */ + + + /* +diff --git a/filter/pstops.c b/filter/pstops.c +index 41090c8..87da143 100644 +--- a/filter/pstops.c ++++ b/filter/pstops.c +@@ -3171,6 +3171,18 @@ write_label_prolog(pstops_doc_t *doc, /* I - Document info */ + { + 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 */ + + + /* +@@ -3193,6 +3205,124 @@ write_label_prolog(pstops_doc_t *doc, /* I - Document info */ + 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... + */ +@@ -3271,7 +3401,10 @@ write_label_prolog(pstops_doc_t *doc, /* I - Document info */ + 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 --git a/scheduler/client.c b/scheduler/client.c +index 779404c..7044ebd 100644 +--- a/scheduler/client.c ++++ b/scheduler/client.c +@@ -20,12 +20,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 */ + + + /* +@@ -264,6 +272,59 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ + } + #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) + { +@@ -526,6 +587,11 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ + } + #endif /* HAVE_AUTHORIZATION_H */ + ++#ifdef WITH_LSPP ++ if (con->scon) ++ cupsdClearString(&con->scon); ++#endif /* WITH_LSPP */ ++ + /* + * Re-enable new client connections if we are going back under the + * limit... +@@ -566,6 +632,13 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ + 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; +@@ -1737,7 +1810,75 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ + fchmod(con->file, 0640); + fchown(con->file, RunUser, Group); + 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) + { +@@ -3235,6 +3376,49 @@ is_path_absolute(const char *path) /* I - Input path */ + 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 --git a/scheduler/client.h b/scheduler/client.h +index 9fe4e2e..51c3ab5 100644 +--- a/scheduler/client.h ++++ b/scheduler/client.h +@@ -14,6 +14,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... + */ +@@ -66,6 +73,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) +@@ -138,6 +149,10 @@ 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_TLS + extern int cupsdEndTLS(cupsd_client_t *con); + extern int cupsdStartTLS(cupsd_client_t *con); +diff --git a/scheduler/conf.c b/scheduler/conf.c +index 0d4bb6a..88d67cf 100644 +--- a/scheduler/conf.c ++++ b/scheduler/conf.c +@@ -38,6 +38,9 @@ + # define INADDR_NONE 0xffffffff + #endif /* !INADDR_NONE */ + ++#ifdef WITH_LSPP ++# include ++#endif /* WITH_LSPP */ + + /* + * Configuration variable structure... +@@ -129,6 +132,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[] = +@@ -539,6 +546,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 */ + + + /* +@@ -866,6 +876,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"); + +@@ -1272,7 +1301,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... +@@ -3880,6 +3921,18 @@ read_location(cups_file_t *fp, /* I - Configuration file */ + 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 --git a/scheduler/conf.h b/scheduler/conf.h +index 2e5aac6..df22b07 100644 +--- a/scheduler/conf.h ++++ b/scheduler/conf.h +@@ -242,6 +242,13 @@ VAR char *ServerKeychain VALUE(NULL); + /* Keychain holding cert + key */ + #endif /* HAVE_TLS */ + ++#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 */ +@@ -260,6 +267,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 --git a/scheduler/cupsd.h b/scheduler/cupsd.h +index 164df6e..2d66464 100644 +--- a/scheduler/cupsd.h ++++ b/scheduler/cupsd.h +@@ -9,6 +9,8 @@ + * information. + */ + ++/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ + + /* + * Include necessary headers. +@@ -34,6 +36,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 --git a/scheduler/ipp.c b/scheduler/ipp.c +index 67ee8ed..e7fa758 100644 +--- a/scheduler/ipp.c ++++ b/scheduler/ipp.c +@@ -12,6 +12,9 @@ + * information. + */ + ++/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ + /* + * Include necessary headers... + */ +@@ -28,6 +31,12 @@ extern int mbr_group_name_to_uuid(const char* name, uuid_t uu); + extern int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember); + #endif /* __APPLE__ */ + ++#ifdef WITH_LSPP ++#include ++#include ++#include ++#include ++#endif /* WITH_LSPP */ + + /* + * Local functions... +@@ -52,6 +61,9 @@ static void cancel_all_jobs(cupsd_client_t *con, ipp_attribute_t *uri); + 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, +@@ -1188,6 +1200,21 @@ add_job(cupsd_client_t *con, /* I - Client connection */ + "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))", +@@ -1516,6 +1543,106 @@ add_job(cupsd_client_t *con, /* I - Client connection */ + + 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 = string_to_security_class("file"); ++ avr = string_to_av_perm(tclass, "write"); ++ } ++ else if (S_ISCHR(printerstat.st_mode)) ++ { ++ tclass = string_to_security_class("chr_file"); ++ avr = string_to_av_perm(tclass, "write"); ++ } ++ else if (S_ISREG(printerstat.st_mode)) ++ { ++ tclass = string_to_security_class("file"); ++ avr = string_to_av_perm(tclass, "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, +@@ -1524,6 +1651,32 @@ add_job(cupsd_client_t *con, /* I - Client connection */ + 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; +@@ -1711,6 +1864,29 @@ add_job(cupsd_client_t *con, /* I - Client connection */ + 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; + +@@ -1741,6 +1917,9 @@ add_job(cupsd_client_t *con, /* I - Client connection */ + "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, +@@ -1759,6 +1938,9 @@ add_job(cupsd_client_t *con, /* I - Client connection */ + "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") && +@@ -1779,6 +1961,9 @@ add_job(cupsd_client_t *con, /* I - Client connection */ + "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) && +@@ -1819,9 +2004,55 @@ add_job(cupsd_client_t *con, /* I - Client connection */ + "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); ++ } + } ++#endif /* WITH_LSPP */ + } + ++#ifdef WITH_LSPP ++ if (userheader) ++ free(userheader); ++ if (userfooter) ++ free(userfooter); ++#endif /* WITH_LSPP */ ++ ++ + /* + * See if we need to add the starting sheet... + */ +@@ -3647,6 +3878,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 = string_to_security_class("file"); ++ avr = string_to_av_perm(tclass, "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. + */ +@@ -4102,6 +4455,15 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ + 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, +@@ -4137,6 +4499,85 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ + + 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... +@@ -4231,6 +4672,24 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ + 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); +@@ -6681,6 +7140,22 @@ get_job_attrs(cupsd_client_t *con, /* I - Client connection */ + + 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... + */ +@@ -7079,6 +7554,11 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ + 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); + +@@ -11810,6 +12290,11 @@ validate_user(cupsd_job_t *job, /* I - Job */ + + 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 --git a/scheduler/job.c b/scheduler/job.c +index 822a247..2f952bc 100644 +--- a/scheduler/job.c ++++ b/scheduler/job.c +@@ -9,6 +9,9 @@ + * information. + */ + ++/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ + /* + * Include necessary headers... + */ +@@ -24,6 +27,12 @@ + # endif /* HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */ + #endif /* __APPLE__ */ + ++#ifdef WITH_LSPP ++#include ++#include ++#include ++#include ++#endif /* WITH_LSPP */ + + /* + * Design Notes for Job Management +@@ -544,6 +553,14 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ + /* PRINTER env variable */ + *printer_state_reasons = NULL; + /* PRINTER_STATE_REASONS env var */ ++#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, +@@ -1070,6 +1087,67 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ + 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", +@@ -1404,6 +1482,11 @@ cupsdDeleteJob(cupsd_job_t *job, /* I - Job */ + + cupsdClearString(&job->username); + cupsdClearString(&job->dest); ++ ++#ifdef WITH_LSPP ++ cupsdClearString(&job->scon); ++#endif ++ + for (i = 0; + i < (int)(sizeof(job->auth_env) / sizeof(job->auth_env[0])); + i ++) +@@ -1856,6 +1939,22 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ + ippSetString(job->attrs, &job->reasons, 0, "job-completed-successfully"); + } + ++#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); +@@ -2268,6 +2367,14 @@ cupsdSaveJob(cupsd_job_t *job) /* I - Job */ + { + 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", +@@ -2290,6 +2397,78 @@ cupsdSaveJob(cupsd_job_t *job) /* I - Job */ + + 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, +@@ -4020,6 +4199,19 @@ get_options(cupsd_job_t *job, /* I - Job */ + 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... + */ +@@ -4834,6 +5026,18 @@ start_job(cupsd_job_t *job, /* I - Job ID */ + 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); +@@ -5022,6 +5226,113 @@ start_job(cupsd_job_t *job, /* I - Job ID */ + 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 = string_to_security_class("file"); ++ avr = string_to_av_perm(tclass, "write"); ++ } ++ else if (S_ISCHR(printerstat.st_mode)) ++ { ++ tclass = string_to_security_class("chr_file"); ++ avr = string_to_av_perm(tclass, "write"); ++ } ++ else if (S_ISREG(printerstat.st_mode)) ++ { ++ tclass = string_to_security_class("file"); ++ avr = string_to_av_perm(tclass, "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 --git a/scheduler/job.h b/scheduler/job.h +index 619353d..310b66a 100644 +--- a/scheduler/job.h ++++ b/scheduler/job.h +@@ -8,6 +8,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... + */ +@@ -85,6 +92,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 --git a/scheduler/main.c b/scheduler/main.c +index ae2409e..21bd989 100644 +--- a/scheduler/main.c ++++ b/scheduler/main.c +@@ -58,6 +58,9 @@ + # include + #endif /* HAVE_SYS_PARAM_H */ + ++#ifdef WITH_LSPP ++# include ++#endif /* WITH_LSPP */ + + /* + * Local functions... +@@ -124,6 +127,9 @@ main(int argc, /* I - Number of command-line args */ + #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 +@@ -494,6 +500,25 @@ main(int argc, /* I - Number of command-line args */ + 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... + */ +@@ -1203,6 +1228,11 @@ main(int argc, /* I - Number of command-line args */ + + cupsdStopSelect(); + ++#ifdef WITH_LSPP ++ if (AuditLog != -1) ++ audit_close(AuditLog); ++#endif /* WITH_LSPP */ ++ + return (!stop_scheduler); + } + +diff --git a/scheduler/printers.c b/scheduler/printers.c +index bf493a3..d06bd93 100644 +--- a/scheduler/printers.c ++++ b/scheduler/printers.c +@@ -9,6 +9,8 @@ + * information. + */ + ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ + /* + * Include necessary headers... + */ +@@ -33,6 +35,10 @@ + # include + #endif /* __APPLE__ */ + ++#ifdef WITH_LSPP ++# include ++# include ++#endif /* WITH_LSPP */ + + /* + * Local functions... +@@ -2184,6 +2190,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ + 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 */ + + + /* +@@ -2309,6 +2322,45 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ + 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.spec b/cups.spec index bc72fa79ecb70c5a06ab196c0ea7c6ad613df06d..43fa44ddb1c1a5072fa17c37acddba545da9e59b 100644 --- a/cups.spec +++ b/cups.spec @@ -2,12 +2,11 @@ Name: cups Epoch: 1 -Version: 2.4.7 -Release: 5 +Version: 2.4.11 +Release: 1 Summary: CUPS is the standards-based, open source printing system for linux operating systems. License: Apache-2.0 Url: https://openprinting.github.io/cups/ -# Apple stopped uploading the new versions into github, use OpenPrinting fork Source0: https://github.com/OpenPrinting/cups/releases/download/v%{version}/cups-%{version}-source.tar.gz Source1: cupsprinter.png @@ -23,31 +22,19 @@ Patch7: cups-uri-compat.patch Patch8: cups-freebind.patch Patch9: cups-ipp-multifile.patch Patch10: cups-web-devices-timeout.patch +Patch100: cups-lspp.patch +Patch101: fix-httpAddrGetList-test-case-fail.patch -Patch6004: fix-httpAddrGetList-test-case-fail.patch -Patch6005: backport-Fix-CVE-2024-35235.patch -Patch6006: backport-Fix-CVE-2024-35235-regression.patch -Patch6007: backport-delay-creating-driverless-printer-until-ppd-generated.patch -Patch6008: backport-0001-CVE-2024-47175.patch -Patch6009: backport-0002-CVE-2024-47175.patch -Patch6010: backport-0003-CVE-2024-47175.patch -Patch6011: backport-0004-CVE-2024-47175.patch -Patch6012: backport-0005-CVE-2024-47175.patch - -BuildRequires: pam-devel pkgconf-pkg-config pkgconfig(gnutls) libacl-devel openldap-devel pkgconfig(libusb-1.0) +BuildRequires: pam-devel pkgconfig(gnutls) libacl-devel openldap-devel pkgconfig(libusb-1.0) BuildRequires: krb5-devel pkgconfig(avahi-client) systemd pkgconfig(libsystemd) pkgconfig(dbus-1) python3-cups BuildRequires: automake zlib-devel gcc gcc-c++ libselinux-devel audit-libs-devel make Requires: dbus systemd acl cups-filters /usr/sbin/alternatives Requires: %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} Requires: %{name}-client%{?_isa} = %{epoch}:%{version}-%{release} Requires: %{name}-filesystem = %{epoch}:%{version}-%{release} - +%{?systemd_requires} # Requires working PrivateTmp (bug #807672) -Requires(pre): systemd -Requires(post): systemd Requires(post): grep, sed -Requires(preun): systemd -Requires(postun): systemd %description CUPS is the standards-based, open source printing system developed by Apple Inc. @@ -58,8 +45,10 @@ Protocol (IPP) to support printing to local and network printers. Summary: CUPS printing system - client programs License: Apache-2.0 Requires: %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-help = %{epoch}:%{version}-%{release} Provides: /usr/bin/lpq /usr/bin/lpr /usr/bin/lp /usr/bin/cancel /usr/bin/lprm /usr/bin/lpstat -Requires: /usr/sbin/alternatives +Requires(post): /usr/sbin/alternatives +Requires(preun): /usr/sbin/alternatives Provides: lpr %description client @@ -71,7 +60,7 @@ programs. Summary: CUPS printing system - development environment License: Apache-2.0 Requires: %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} -Requires: gnutls-devel krb5-devel zlib-devel pkgconf-pkg-config +Requires: gnutls-devel krb5-devel zlib-devel %description devel CUPS is the standards-based, open source printing system developed by Apple Inc. @@ -104,6 +93,7 @@ Summary: CUPS printing system - lpd emulation Requires: %{name}%{?_isa} = %{epoch}:%{version}-%{release} Requires: %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} Provides: lpd +%{?systemd_requires} %description lpd CUPS printing system provides a portable printing layer for @@ -130,12 +120,7 @@ application enables older printers for IPP everywhere standard - so if older pri is installed with a printer application, its print queue acts as IPP everywhere printer to CUPS daemon. This solution will substitute printer drivers and raw queues in the future. -%package help -Summary: Documents for cups -Buildarch: noarch - -%description help -Man pages and other related documents. +%package_help %prep %autosetup -n %{name}-%{version} -p1 @@ -148,8 +133,8 @@ aclocal -I config-scripts autoconf -f -I config-scripts %build -export DSOFLAGS="$DSOFLAGS -L../cgi-bin -L../filter -L../ppdc -L../scheduler -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/generic-hardened-ld -Wl,-z,relro,-z,now -fPIE -pie" -export CFLAGS="$RPM_OPT_FLAGS -fstack-protector-all -DLDAP_DEPRECATED=1" +export DSOFLAGS="$DSOFLAGS %{build_ldflags}" +export CFLAGS="%{build_cflags} -DLDAP_DEPRECATED=1" # --enable-debug to avoid stripping binaries %configure --with-docdir=%{_datadir}/%{name}/www --enable-debug \ --enable-lspp \ @@ -172,7 +157,7 @@ export CFLAGS="$RPM_OPT_FLAGS -fstack-protector-all -DLDAP_DEPRECATED=1" %make_build %check -make check +%make_build check %install make BUILDROOT=${RPM_BUILD_ROOT} install @@ -261,8 +246,6 @@ install -d ${RPM_BUILD_ROOT}%{_localstatedir}/run/cups/certs %post lpd %systemd_post cups-lpd.socket -%ldconfig_scriptlets libs - %preun %systemd_preun %{name}.path %{name}.socket %{name}.service @@ -338,24 +321,11 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %dir %{_datadir}/%{name}/www/pt_BR %dir %{_datadir}/%{name}/www/ru %{_datadir}/pixmaps/cupsprinter.png +%ghost %dir %attr(0770,root,lp) %{_localstatedir}/cache/cups +%ghost %dir %attr(0775,root,lp) %{_localstatedir}/cache/cups/rss %dir %attr(1770,root,lp) %{_localstatedir}/spool/cups/tmp %dir %attr(0710,root,lp) %{_localstatedir}/spool/cups %dir %attr(0755,root,lp) %{_localstatedir}/log/cups -# client subpackage -%exclude %{_mandir}/man1/lp*.1.gz -%exclude %{_mandir}/man1/cancel-cups.1.gz -%exclude %{_mandir}/man8/lpc-cups.8.gz -# devel subpackage -%exclude %{_mandir}/man1/cups-config.1.gz -# ipptool subpackage -%exclude %{_mandir}/man1/ipptool.1.gz -%exclude %{_mandir}/man5/ipptoolfile.5.gz -# lpd subpackage -%exclude %{_mandir}/man8/cups-lpd.8.gz -# printerapp -%exclude %{_mandir}/man1/ippeveprinter.1.gz -%exclude %{_mandir}/man7/ippevepcl.7.gz -%exclude %{_mandir}/man7/ippeveps.7.gz %dir %attr(0755,root,lp) %{_rundir}/cups %dir %attr(0511,lp,sys) %{_rundir}/cups/certs %dir %attr(0755,root,lp) %{_sysconfdir}/cups @@ -379,14 +349,12 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %attr(0644, root, root)%{_unitdir}/%{name}.service %attr(0644, root, root)%{_unitdir}/%{name}.socket %attr(0644, root, root)%{_unitdir}/%{name}.path +%attr(0644, root, root)%{_unitdir}/system-cups.slice %files client %{_bindir}/cancel* %{_bindir}/lp* %{_sbindir}/lpc.cups -%{_mandir}/man1/cancel-cups.1.gz -%{_mandir}/man1/lp*.1.gz -%{_mandir}/man8/lpc-cups.8.gz %files libs %{license} LICENSE @@ -413,11 +381,9 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %{_libdir}/*.so %{_libdir}/pkgconfig/cups.pc %{_rpmconfigdir}/macros.d/macros.cups - %files lpd %{cups_serverbin}/daemon/cups-lpd -%{_mandir}/man8/cups-lpd.8.gz %attr(0644, root, root)%{_unitdir}/cups-lpd.socket %attr(0644, root, root)%{_unitdir}/cups-lpd@.service @@ -426,35 +392,32 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %{_bindir}/ipptool %dir %{_datadir}/cups/ipptool %{_datadir}/cups/ipptool/* -%{_mandir}/man1/ipptool.1.gz -%{_mandir}/man5/ipptoolfile.5.gz %files printerapp %{_bindir}/ippeveprinter %dir %{cups_serverbin}/command %{cups_serverbin}/command/ippevepcl %{cups_serverbin}/command/ippeveps -%{_mandir}/man1/ippeveprinter.1.gz -%{_mandir}/man7/ippevepcl.7.gz -%{_mandir}/man7/ippeveps.7.gz %files help -%{_mandir}/man[1578]/* -%{_mandir}/man1/cups-config.1.gz +%{_mandir}/man?/* %doc README.md CREDITS.md CHANGES.md %doc %{_datadir}/%{name}/www/index.html %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 +%lang(de) %doc %{_datadir}/%{name}/www/de/index.html +%lang(da) %doc %{_datadir}/%{name}/www/da/index.html +%lang(es) %doc %{_datadir}/%{name}/www/es/index.html +%lang(fr) %doc %{_datadir}/%{name}/www/fr/index.html +%lang(ja) %doc %{_datadir}/%{name}/www/ja/index.html +%lang(ru) %doc %{_datadir}/%{name}/www/ru/index.html +%lang(pt_BR) %doc %{_datadir}/%{name}/www/pt_BR/index.html %doc %{_datadir}/%{name}/www/apple-touch-icon.png %changelog +* Wed Oct 09 2024 Funda Wang - 1:2.4.11-1 +- update to version 2.4.11 + * Tue Oct 8 2024 zhangpan - 1:2.4.7-5 - fix CVE-2024-47175 @@ -486,89 +449,89 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb * Sat Jun 3 2023 zhouwenpei - 1:2.4.0-6 - fix CVE-2023-32324 -* Tue Feb 21 2023 zhouwenpei - 2.4.0-5 +* Tue Feb 21 2023 zhouwenpei - 1:2.4.0-5 - fix update conflict of devel and help -* Wed Jun 15 2022 hanhui - 2.4.0-4 +* Wed Jun 15 2022 hanhui - 1:2.4.0-4 - Remove legacy code for RIP_MAX_CACHE environment variable -* Thu Jun 9 2022 hanhui - 2.4.0-3 +* Thu Jun 9 2022 hanhui - 1:2.4.0-3 - fix CVE-2022-26691 -* Thu May 12 2022 zhanzhimin - 2.4.0-2 +* Thu May 12 2022 zhanzhimin - 1:2.4.0-2 - fix official website address -* Thu Dec 9 2021 hanhui - 2.4.0-1 +* Thu Dec 9 2021 hanhui - 1:2.4.0-1 - DESC:update to cups-2.4.0 -* Thu Nov 04 2021 wangkerong - 2.3.3-8 +* Thu Nov 04 2021 wangkerong - 1:2.3.3-8 - Type:bugfix - ID:NA - SUG:NA - DESC:fix cups-devel requires error -* Fri Sep 24 2021 liuyumeng - 2.3.3-7 +* Fri Sep 24 2021 liuyumeng - 1:2.3.3-7 - Type:CVE - ID:CVE-2020-10001 - SUG:NA - DESC:Fix CVE-2020-10001 -* Tue Jun 08 2021 wangkerong - 2.3.3-6 +* Tue Jun 08 2021 wangkerong - 1:2.3.3-6 - Type:CVE - ID:CVE-2021-25317 - SUG:NA - DESC:Fix CVE-2021-25317 -* Tue May 25 2021 liuyumeng - 2.3.3-5 +* Tue May 25 2021 liuyumeng - 1:2.3.3-5 - remove unused ncp backend -* Mon May 24 2021 liuyumeng - 2.3.3-4 +* Mon May 24 2021 liuyumeng - 1:2.3.3-4 - Type:bugfix - ID:NA - SUG:NA - DESC:Compilation optimization -* Tue Sep 29 2020 hanhui - 2.3.3-3 +* Tue Sep 29 2020 hanhui - 1:2.3.3-3 - Type:bugfix - ID:NA - SUG:NA - DESC:fix build bug -* Wed Sep 9 2020 hanhui - 2.3.3-2 +* Wed Sep 9 2020 hanhui - 1:2.3.3-2 - Type:bugfix - ID:NA - SUG:NA - DESC:modify source url -* Mon Jul 20 2020 wangye - 2.3.3-1 +* Mon Jul 20 2020 wangye - 1:2.3.3-1 - Type:enhancement - ID:NA - SUG:NA - DESC:upgrade to 2.3.3 -* Fri Jun 12 2020 hanhui - 2.2.13-1 +* Fri Jun 12 2020 hanhui - 1:2.2.13-1 - Type:enhancement - ID:NA - SUG:NA - DESC:upgrade to 2.2.13 -* Thu Mar 26 2020 gaihuiying - 2.2.8-9 +* Thu Mar 26 2020 gaihuiying - 1:2.2.8-9 - Type:cves - ID:CVE-2019-2228 - SUG:restart - DESC:fix CVE-2019-2228 -* Sat Jan 11 2020 openEuler Buildteam - 2.2.8-8 +* Sat Jan 11 2020 openEuler Buildteam - 1:2.2.8-8 - Type:enhancement - ID:NA - SUG:NA - DESC: delete patches -* Wed Sep 25 2019 gaoguanghui - 2.2.8-7 +* Wed Sep 25 2019 gaoguanghui - 1:2.2.8-7 - Type:cves - ID:CVE-2019-8675 CVE-2019-8696 - SUG:restart - DESC:fix CVE-2019-8675 CVE-2019-8696 -* Wed Sep 18 2019 Guan Yanjie - 2.2.8-6 +* Wed Sep 18 2019 Guan Yanjie - 1:2.2.8-6 - Package init