From d714713c3ed347a9fcae8c1ae12ce636ab67bfee Mon Sep 17 00:00:00 2001 From: zppzhangpan Date: Tue, 8 Oct 2024 14:35:05 +0800 Subject: [PATCH] fix CVE-2024-47175 (cherry picked from commit c195b24c6f7f6b4c55b62e2aabd76fe9cf2bd307) --- backport-0001-CVE-2024-47175.patch | 72 ++ backport-0002-CVE-2024-47175.patch | 143 +++ backport-0003-CVE-2024-47175.patch | 111 ++ backport-0004-CVE-2024-47175.patch | 241 ++++ backport-0005-CVE-2024-47175.patch | 32 + ...iverless-printer-until-ppd-generated.patch | 1121 +++++++++++++++++ cups.spec | 11 +- 7 files changed, 1730 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2024-47175.patch create mode 100644 backport-0002-CVE-2024-47175.patch create mode 100644 backport-0003-CVE-2024-47175.patch create mode 100644 backport-0004-CVE-2024-47175.patch create mode 100644 backport-0005-CVE-2024-47175.patch create mode 100644 backport-delay-creating-driverless-printer-until-ppd-generated.patch diff --git a/backport-0001-CVE-2024-47175.patch b/backport-0001-CVE-2024-47175.patch new file mode 100644 index 0000000..61a4e04 --- /dev/null +++ b/backport-0001-CVE-2024-47175.patch @@ -0,0 +1,72 @@ +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 new file mode 100644 index 0000000..592bb08 --- /dev/null +++ b/backport-0002-CVE-2024-47175.patch @@ -0,0 +1,143 @@ +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 new file mode 100644 index 0000000..0580c14 --- /dev/null +++ b/backport-0003-CVE-2024-47175.patch @@ -0,0 +1,111 @@ +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 new file mode 100644 index 0000000..e516be7 --- /dev/null +++ b/backport-0004-CVE-2024-47175.patch @@ -0,0 +1,241 @@ +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 new file mode 100644 index 0000000..aae3f56 --- /dev/null +++ b/backport-0005-CVE-2024-47175.patch @@ -0,0 +1,32 @@ +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-delay-creating-driverless-printer-until-ppd-generated.patch b/backport-delay-creating-driverless-printer-until-ppd-generated.patch new file mode 100644 index 0000000..4c3ce86 --- /dev/null +++ b/backport-delay-creating-driverless-printer-until-ppd-generated.patch @@ -0,0 +1,1121 @@ +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.spec b/cups.spec index 63ca877..bc72fa7 100644 --- a/cups.spec +++ b/cups.spec @@ -3,7 +3,7 @@ Name: cups Epoch: 1 Version: 2.4.7 -Release: 4 +Release: 5 Summary: CUPS is the standards-based, open source printing system for linux operating systems. License: Apache-2.0 Url: https://openprinting.github.io/cups/ @@ -27,6 +27,12 @@ Patch10: cups-web-devices-timeout.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: krb5-devel pkgconfig(avahi-client) systemd pkgconfig(libsystemd) pkgconfig(dbus-1) python3-cups @@ -449,6 +455,9 @@ rm -f %{_exec_prefix}/lib/cups/backend/smb %doc %{_datadir}/%{name}/www/apple-touch-icon.png %changelog +* Tue Oct 8 2024 zhangpan - 1:2.4.7-5 +- fix CVE-2024-47175 + * Wed Aug 14 2024 Funda Wang - 1:2.4.7-4 - Fix regression of fixing CVE-2024-35235 (upstream issue#985) -- Gitee