diff --git a/SOURCES/0001-Fix-cupsGetPPD-with-IPP-print-queues-STR-4725.patch b/SOURCES/0001-Fix-cupsGetPPD-with-IPP-print-queues-STR-4725.patch new file mode 100644 index 0000000..bef126f --- /dev/null +++ b/SOURCES/0001-Fix-cupsGetPPD-with-IPP-print-queues-STR-4725.patch @@ -0,0 +1,17 @@ +diff -up cups-1.6.3/cups/util.c.download-ppd cups-1.6.3/cups/util.c +--- cups-1.6.3/cups/util.c.download-ppd 2020-02-11 13:36:26.923903558 +0100 ++++ cups-1.6.3/cups/util.c 2020-02-11 13:38:25.473972412 +0100 +@@ -1712,10 +1712,9 @@ cups_get_printer_uri( + device_uri = attr->values[0].string.text; + + if (device_uri && +- (!strncmp(device_uri, "ipp://", 6) || +- !strncmp(device_uri, "ipps://", 7) || +- ((strstr(device_uri, "._ipp.") != NULL || +- strstr(device_uri, "._ipps.") != NULL) && ++ (((!strncmp(device_uri, "ipp://", 6) || !strncmp(device_uri, "ipps://", 7)) && ++ (strstr(device_uri, "/printers/") != NULL || strstr(device_uri, "/classes/") != NULL)) || ++ ((strstr(device_uri, "._ipp.") != NULL || strstr(device_uri, "._ipps.") != NULL) && + !strcmp(device_uri + strlen(device_uri) - 5, "/cups")))) + { + /* diff --git a/SOURCES/0001-Multiple-security-disclosure-issues.patch b/SOURCES/0001-Multiple-security-disclosure-issues.patch new file mode 100644 index 0000000..0473789 --- /dev/null +++ b/SOURCES/0001-Multiple-security-disclosure-issues.patch @@ -0,0 +1,184 @@ +diff --git a/cups/http-private.h b/cups/http-private.h +index f2640f1..b7f9b6e 100644 +--- a/cups/http-private.h ++++ b/cups/http-private.h +@@ -380,6 +380,7 @@ extern const char *_httpResolveURI(const char *uri, char *resolved_uri, + int (*cb)(void *context), + void *context); + extern int _httpUpdate(http_t *http, http_status_t *status); ++extern size_t _httpTLSPending(http_t *http); + extern int _httpWait(http_t *http, int msec, int usessl); + + extern void _httpTLSSetOptions(int options); +diff --git a/cups/http.c b/cups/http.c +index e02b66d..128a52a 100644 +--- a/cups/http.c ++++ b/cups/http.c +@@ -1817,7 +1817,7 @@ httpPrintf(http_t *http, /* I - Connection to server */ + ...) /* I - Additional args as needed */ + { + int bytes; /* Number of bytes to write */ +- char buf[16384]; /* Buffer for formatted string */ ++ char buf[65536]; /* Buffer for formatted string */ + va_list ap; /* Variable argument pointer */ + + +@@ -1829,7 +1829,12 @@ httpPrintf(http_t *http, /* I - Connection to server */ + + DEBUG_printf(("3httpPrintf: %s", buf)); + +- if (http->data_encoding == HTTP_ENCODE_FIELDS) ++ if (bytes > (ssize_t)(sizeof(buf) - 1)) ++ { ++ http->error = ENOMEM; ++ return (-1); ++ } ++ else if (http->data_encoding == HTTP_ENCODE_FIELDS) + return (httpWrite2(http, buf, bytes)); + else + { +diff --git a/cups/ipp.c b/cups/ipp.c +index 0384792..2b613d7 100644 +--- a/cups/ipp.c ++++ b/cups/ipp.c +@@ -3847,9 +3847,7 @@ ippSetValueTag( + break; + + case IPP_TAG_NAME : +- if (temp_tag != IPP_TAG_KEYWORD && temp_tag != IPP_TAG_URI && +- temp_tag != IPP_TAG_URISCHEME && temp_tag != IPP_TAG_LANGUAGE && +- temp_tag != IPP_TAG_MIMETYPE) ++ if (temp_tag != IPP_TAG_KEYWORD) + return (0); + + (*attr)->value_tag = (ipp_tag_t)(IPP_TAG_NAME | ((*attr)->value_tag & IPP_TAG_COPY)); +@@ -3857,10 +3855,7 @@ ippSetValueTag( + + case IPP_TAG_NAMELANG : + case IPP_TAG_TEXTLANG : +- if (value_tag == IPP_TAG_NAMELANG && +- (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD && +- temp_tag != IPP_TAG_URI && temp_tag != IPP_TAG_URISCHEME && +- temp_tag != IPP_TAG_LANGUAGE && temp_tag != IPP_TAG_MIMETYPE)) ++ if (value_tag == IPP_TAG_NAMELANG && (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD)) + return (0); + + if (value_tag == IPP_TAG_TEXTLANG && temp_tag != IPP_TAG_TEXT) +diff --git a/cups/snmp.c b/cups/snmp.c +index 0c0e520..ff4fcd4 100644 +--- a/cups/snmp.c ++++ b/cups/snmp.c +@@ -1279,6 +1279,9 @@ asn1_get_integer( + int value; /* Integer value */ + + ++ if (*buffer >= bufend) ++ return (0); ++ + if (length > sizeof(int)) + { + (*buffer) += length; +@@ -1305,6 +1308,9 @@ asn1_get_length(unsigned char **buffer, /* IO - Pointer in buffer */ + unsigned length; /* Length */ + + ++ if (*buffer >= bufend) ++ return (0); ++ + length = **buffer; + (*buffer) ++; + +@@ -1347,6 +1353,9 @@ asn1_get_oid( + int number; /* OID number */ + + ++ if (*buffer >= bufend) ++ return (0); ++ + valend = *buffer + length; + oidptr = oid; + oidend = oid + oidsize - 1; +@@ -1395,9 +1404,12 @@ asn1_get_packed( + int value; /* Value */ + + ++ if (*buffer >= bufend) ++ return (0); ++ + value = 0; + +- while ((**buffer & 128) && *buffer < bufend) ++ while (*buffer < bufend && (**buffer & 128)) + { + value = (value << 7) | (**buffer & 127); + (*buffer) ++; +@@ -1425,6 +1437,9 @@ asn1_get_string( + char *string, /* I - String buffer */ + int strsize) /* I - String buffer size */ + { ++ if (*buffer >= bufend) ++ return (NULL); ++ + if (length > (bufend - *buffer)) + length = bufend - *buffer; + +@@ -1475,6 +1490,9 @@ asn1_get_type(unsigned char **buffer, /* IO - Pointer in buffer */ + int type; /* Type */ + + ++ if (*buffer >= bufend) ++ return (0); ++ + type = **buffer; + (*buffer) ++; + +diff --git a/scheduler/client.c b/scheduler/client.c +index 6e2f7e6..e20344d 100644 +--- a/scheduler/client.c ++++ b/scheduler/client.c +@@ -770,6 +770,23 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ + con->request ? ipp_states[con->request->state] : "", + con->file); + ++ if (con->http.error == EPIPE && ++ (con->http.used == 0 ++#ifdef HAVE_SSL ++ || _httpTLSPending(&(con->http)) == 0 ++#endif /* HAVE_SSL */ ++ ) && recv(con->http.fd, buf, 1, MSG_PEEK) < 1) ++ { ++ /* ++ * Connection closed... ++ */ ++ ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Closing on EOF.", con->http.fd); ++ cupsdCloseClient(con); ++ return; ++ } ++ ++ + #ifdef HAVE_SSL + if (con->auto_ssl) + { +diff --git a/scheduler/tls-openssl.c b/scheduler/tls-openssl.c +index 759f393..a7a8e85 100644 +--- a/scheduler/tls-openssl.c ++++ b/scheduler/tls-openssl.c +@@ -144,6 +144,17 @@ cupsdStartTLS(cupsd_client_t *con) /* I - Client connection */ + } + + ++/* ++ * '_httpTLSPending()' - Return the number of pending TLS-encrypted bytes. ++ */ ++ ++size_t /* O - Bytes available */ ++_httpTLSPending(http_t *http) /* I - HTTP connection */ ++{ ++ return (SSL_pending(http->tls)); ++} ++ ++ + /* + * 'make_certificate()' - Make a self-signed SSL/TLS certificate. + */ diff --git a/SOURCES/cups-cupsdsavejob-sigsegv.patch b/SOURCES/cups-cupsdsavejob-sigsegv.patch new file mode 100644 index 0000000..d5e9f24 --- /dev/null +++ b/SOURCES/cups-cupsdsavejob-sigsegv.patch @@ -0,0 +1,16 @@ +diff -Napur cups-1.4.2-bz01540662.old/scheduler/job.c cups-1.4.2-bz01540662.new/scheduler/job.c +--- cups-1.4.2-bz01540662.old/scheduler/job.c 2015-11-18 17:46:03.401809520 -0800 ++++ cups-1.4.2-bz01540662.new/scheduler/job.c 2015-11-18 17:48:53.420396480 -0800 +@@ -2777,7 +2777,11 @@ cupsdUnloadCompletedJobs(void) + if (job->dirty) + cupsdSaveJob(job); + +- unload_job(job); ++ /* ++ * Don't unload jobs that couldn't be saved (i.e. still dirty) ++ */ ++ if ( !job->dirty ) ++ unload_job(job); + } + } + diff --git a/SOURCES/cups-cve-rebound-fix.patch b/SOURCES/cups-cve-rebound-fix.patch new file mode 100644 index 0000000..a194a85 --- /dev/null +++ b/SOURCES/cups-cve-rebound-fix.patch @@ -0,0 +1,15 @@ +diff --git a/scheduler/client.c b/scheduler/client.c +index e20344d..c83aa76 100644 +--- a/scheduler/client.c ++++ b/scheduler/client.c +@@ -4274,10 +4274,6 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ + !_cups_strncasecmp(host, "localhost:", 10) || + !_cups_strcasecmp(host, "localhost.") || + !_cups_strncasecmp(host, "localhost.:", 11) || +-#ifdef __linux +- !_cups_strcasecmp(host, "localhost.localdomain") || +- !_cups_strncasecmp(host, "localhost.localdomain:", 22) || +-#endif /* __linux */ + !strcmp(host, "127.0.0.1") || + !strncmp(host, "127.0.0.1:", 10) || + !strcmp(host, "[::1]") || diff --git a/SOURCES/cups-memory-consumption.patch b/SOURCES/cups-memory-consumption.patch new file mode 100644 index 0000000..530c536 --- /dev/null +++ b/SOURCES/cups-memory-consumption.patch @@ -0,0 +1,1252 @@ +diff --git a/cups/mark.c b/cups/mark.c +index dc2257f..b3d7d0d 100644 +--- a/cups/mark.c ++++ b/cups/mark.c +@@ -890,9 +890,9 @@ ppd_mark_option(ppd_file_t *ppd, /* I - PPD file */ + case PPD_CUSTOM_PASSWORD : + case PPD_CUSTOM_STRING : + if (cparam->current.custom_string) +- _cupsStrFree(cparam->current.custom_string); ++ free(cparam->current.custom_string); + +- cparam->current.custom_string = _cupsStrAlloc(choice + 7); ++ cparam->current.custom_string = strdup(choice + 7); + break; + } + } +@@ -967,9 +967,9 @@ ppd_mark_option(ppd_file_t *ppd, /* I - PPD file */ + case PPD_CUSTOM_PASSWORD : + case PPD_CUSTOM_STRING : + if (cparam->current.custom_string) +- _cupsStrFree(cparam->current.custom_string); ++ free(cparam->current.custom_string); + +- cparam->current.custom_string = _cupsStrRetain(val->value); ++ cparam->current.custom_string = strdup(val->value); + break; + } + } +diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c +index ca1c773..072b9ff 100644 +--- a/cups/ppd-cache.c ++++ b/cups/ppd-cache.c +@@ -199,24 +199,20 @@ _ppdCacheCreateWithFile( + else if (!_cups_strcasecmp(line, "Filter")) + { + if (!pc->filters) +- pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, +- (cups_acopy_func_t)_cupsStrAlloc, +- (cups_afree_func_t)_cupsStrFree); ++ pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free); + + cupsArrayAdd(pc->filters, value); + } + else if (!_cups_strcasecmp(line, "PreFilter")) + { + if (!pc->prefilters) +- pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, +- (cups_acopy_func_t)_cupsStrAlloc, +- (cups_afree_func_t)_cupsStrFree); ++ pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free); + + cupsArrayAdd(pc->prefilters, value); + } + else if (!_cups_strcasecmp(line, "Product")) + { +- pc->product = _cupsStrAlloc(value); ++ pc->product = strdup(value); + } + else if (!_cups_strcasecmp(line, "SingleFile")) + { +@@ -316,8 +312,8 @@ _ppdCacheCreateWithFile( + } + + map = pc->bins + pc->num_bins; +- map->pwg = _cupsStrAlloc(pwg_keyword); +- map->ppd = _cupsStrAlloc(ppd_keyword); ++ map->pwg = strdup(pwg_keyword); ++ map->ppd = strdup(ppd_keyword); + + pc->num_bins ++; + } +@@ -371,8 +367,8 @@ _ppdCacheCreateWithFile( + goto create_error; + } + +- size->map.pwg = _cupsStrAlloc(pwg_keyword); +- size->map.ppd = _cupsStrAlloc(ppd_keyword); ++ size->map.pwg = strdup(pwg_keyword); ++ size->map.ppd = strdup(ppd_keyword); + + pc->num_sizes ++; + } +@@ -400,15 +396,15 @@ _ppdCacheCreateWithFile( + + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max", + pc->custom_max_width, pc->custom_max_length); +- pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword); ++ pc->custom_max_keyword = strdup(pwg_keyword); + + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min", + pc->custom_min_width, pc->custom_min_length); +- pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword); ++ pc->custom_min_keyword = strdup(pwg_keyword); + } + else if (!_cups_strcasecmp(line, "SourceOption")) + { +- pc->source_option = _cupsStrAlloc(value); ++ pc->source_option = strdup(value); + } + else if (!_cups_strcasecmp(line, "NumSources")) + { +@@ -455,8 +451,8 @@ _ppdCacheCreateWithFile( + } + + map = pc->sources + pc->num_sources; +- map->pwg = _cupsStrAlloc(pwg_keyword); +- map->ppd = _cupsStrAlloc(ppd_keyword); ++ map->pwg = strdup(pwg_keyword); ++ map->ppd = strdup(ppd_keyword); + + pc->num_sources ++; + } +@@ -504,8 +500,8 @@ _ppdCacheCreateWithFile( + } + + map = pc->types + pc->num_types; +- map->pwg = _cupsStrAlloc(pwg_keyword); +- map->ppd = _cupsStrAlloc(ppd_keyword); ++ map->pwg = strdup(pwg_keyword); ++ map->ppd = strdup(ppd_keyword); + + pc->num_types ++; + } +@@ -535,13 +531,13 @@ _ppdCacheCreateWithFile( + pc->presets[print_color_mode] + print_quality); + } + else if (!_cups_strcasecmp(line, "SidesOption")) +- pc->sides_option = _cupsStrAlloc(value); ++ pc->sides_option = strdup(value); + else if (!_cups_strcasecmp(line, "Sides1Sided")) +- pc->sides_1sided = _cupsStrAlloc(value); ++ pc->sides_1sided = strdup(value); + else if (!_cups_strcasecmp(line, "Sides2SidedLong")) +- pc->sides_2sided_long = _cupsStrAlloc(value); ++ pc->sides_2sided_long = strdup(value); + else if (!_cups_strcasecmp(line, "Sides2SidedShort")) +- pc->sides_2sided_short = _cupsStrAlloc(value); ++ pc->sides_2sided_short = strdup(value); + else if (!_cups_strcasecmp(line, "Finishings")) + { + if (!pc->finishings) +@@ -796,8 +792,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + */ + + new_size = old_size; +- _cupsStrFree(old_size->map.ppd); +- _cupsStrFree(old_size->map.pwg); ++ free(old_size->map.ppd); ++ free(old_size->map.pwg); + } + } + +@@ -818,8 +814,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + * Save this size... + */ + +- new_size->map.ppd = _cupsStrAlloc(ppd_size->name); +- new_size->map.pwg = _cupsStrAlloc(pwg_name); ++ new_size->map.ppd = strdup(ppd_size->name); ++ new_size->map.pwg = strdup(pwg_name); + new_size->width = new_width; + new_size->length = new_length; + new_size->left = new_left; +@@ -839,14 +835,14 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max", + _PWG_FROMPTS(ppd->custom_max[0]), + _PWG_FROMPTS(ppd->custom_max[1])); +- pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword); ++ pc->custom_max_keyword = strdup(pwg_keyword); + pc->custom_max_width = _PWG_FROMPTS(ppd->custom_max[0]); + pc->custom_max_length = _PWG_FROMPTS(ppd->custom_max[1]); + + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min", + _PWG_FROMPTS(ppd->custom_min[0]), + _PWG_FROMPTS(ppd->custom_min[1])); +- pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword); ++ pc->custom_min_keyword = strdup(pwg_keyword); + pc->custom_min_width = _PWG_FROMPTS(ppd->custom_min[0]); + pc->custom_min_length = _PWG_FROMPTS(ppd->custom_min[1]); + +@@ -865,7 +861,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + + if (input_slot) + { +- pc->source_option = _cupsStrAlloc(input_slot->keyword); ++ pc->source_option = strdup(input_slot->keyword); + + if ((pc->sources = calloc(input_slot->num_choices, + sizeof(_pwg_map_t))) == NULL) +@@ -918,8 +914,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + "_"); + } + +- map->pwg = _cupsStrAlloc(pwg_name); +- map->ppd = _cupsStrAlloc(choice->choice); ++ map->pwg = strdup(pwg_name); ++ map->ppd = strdup(choice->choice); + } + } + +@@ -983,8 +979,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + "_"); + } + +- map->pwg = _cupsStrAlloc(pwg_name); +- map->ppd = _cupsStrAlloc(choice->choice); ++ map->pwg = strdup(pwg_name); ++ map->ppd = strdup(choice->choice); + } + } + +@@ -1011,8 +1007,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + { + pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword), "_"); + +- map->pwg = _cupsStrAlloc(pwg_keyword); +- map->ppd = _cupsStrAlloc(choice->choice); ++ map->pwg = strdup(pwg_keyword); ++ map->ppd = strdup(choice->choice); + } + } + +@@ -1227,7 +1223,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + + if (duplex) + { +- pc->sides_option = _cupsStrAlloc(duplex->keyword); ++ pc->sides_option = strdup(duplex->keyword); + + for (i = duplex->num_choices, choice = duplex->choices; + i > 0; +@@ -1235,16 +1231,16 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + { + if ((!_cups_strcasecmp(choice->choice, "None") || + !_cups_strcasecmp(choice->choice, "False")) && !pc->sides_1sided) +- pc->sides_1sided = _cupsStrAlloc(choice->choice); ++ pc->sides_1sided = strdup(choice->choice); + else if ((!_cups_strcasecmp(choice->choice, "DuplexNoTumble") || + !_cups_strcasecmp(choice->choice, "LongEdge") || + !_cups_strcasecmp(choice->choice, "Top")) && !pc->sides_2sided_long) +- pc->sides_2sided_long = _cupsStrAlloc(choice->choice); ++ pc->sides_2sided_long = strdup(choice->choice); + else if ((!_cups_strcasecmp(choice->choice, "DuplexTumble") || + !_cups_strcasecmp(choice->choice, "ShortEdge") || + !_cups_strcasecmp(choice->choice, "Bottom")) && + !pc->sides_2sided_short) +- pc->sides_2sided_short = _cupsStrAlloc(choice->choice); ++ pc->sides_2sided_short = strdup(choice->choice); + } + } + +@@ -1252,9 +1248,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + * Copy filters and pre-filters... + */ + +- pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, +- (cups_acopy_func_t)_cupsStrAlloc, +- (cups_afree_func_t)_cupsStrFree); ++ pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free); + + cupsArrayAdd(pc->filters, + "application/vnd.cups-raw application/octet-stream 0 -"); +@@ -1311,9 +1305,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + + if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL) + { +- pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, +- (cups_acopy_func_t)_cupsStrAlloc, +- (cups_afree_func_t)_cupsStrFree); ++ pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free); + + do + { +@@ -1330,7 +1322,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ + */ + + if (ppd->product) +- pc->product = _cupsStrAlloc(ppd->product); ++ pc->product = strdup(ppd->product); + + /* + * Copy finishings mapping data... +@@ -1415,8 +1407,8 @@ _ppdCacheDestroy(_ppd_cache_t *pc) /* I - PPD cache and mapping data */ + { + for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++) + { +- _cupsStrFree(map->pwg); +- _cupsStrFree(map->ppd); ++ free(map->pwg); ++ free(map->ppd); + } + + free(pc->bins); +@@ -1426,22 +1418,21 @@ _ppdCacheDestroy(_ppd_cache_t *pc) /* I - PPD cache and mapping data */ + { + for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++) + { +- _cupsStrFree(size->map.pwg); +- _cupsStrFree(size->map.ppd); ++ free(size->map.pwg); ++ free(size->map.ppd); + } + + free(pc->sizes); + } + +- if (pc->source_option) +- _cupsStrFree(pc->source_option); ++ free(pc->source_option); + + if (pc->sources) + { + for (i = pc->num_sources, map = pc->sources; i > 0; i --, map ++) + { +- _cupsStrFree(map->pwg); +- _cupsStrFree(map->ppd); ++ free(map->pwg); ++ free(map->ppd); + } + + free(pc->sources); +@@ -1451,20 +1442,17 @@ _ppdCacheDestroy(_ppd_cache_t *pc) /* I - PPD cache and mapping data */ + { + for (i = pc->num_types, map = pc->types; i > 0; i --, map ++) + { +- _cupsStrFree(map->pwg); +- _cupsStrFree(map->ppd); ++ free(map->pwg); ++ free(map->ppd); + } + + free(pc->types); + } + +- if (pc->custom_max_keyword) +- _cupsStrFree(pc->custom_max_keyword); +- +- if (pc->custom_min_keyword) +- _cupsStrFree(pc->custom_min_keyword); ++ free(pc->custom_max_keyword); ++ free(pc->custom_min_keyword); + +- _cupsStrFree(pc->product); ++ free(pc->product); + cupsArrayDelete(pc->filters); + cupsArrayDelete(pc->prefilters); + cupsArrayDelete(pc->finishings); +diff --git a/cups/ppd.c b/cups/ppd.c +index dd18cc2..c0e55a3 100644 +--- a/cups/ppd.c ++++ b/cups/ppd.c +@@ -78,8 +78,6 @@ + # define WRITE_BINARY "w" /* Open a binary file for writing */ + #endif /* WIN32 || __EMX__ */ + +-#define ppd_free(p) if (p) free(p) /* Safe free macro */ +- + #define PPD_KEYWORD 1 /* Line contained a keyword */ + #define PPD_OPTION 2 /* Line contained an option name */ + #define PPD_TEXT 4 /* Line contained human-readable text */ +@@ -142,7 +140,6 @@ void + ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + { + int i; /* Looping var */ +- ppd_emul_t *emul; /* Current emulation */ + ppd_group_t *group; /* Current group */ + char **font; /* Current font */ + ppd_attr_t **attr; /* Current attribute */ +@@ -161,28 +158,12 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + * Free all strings at the top level... + */ + +- _cupsStrFree(ppd->lang_encoding); +- _cupsStrFree(ppd->nickname); +- if (ppd->patches) +- free(ppd->patches); +- _cupsStrFree(ppd->jcl_begin); +- _cupsStrFree(ppd->jcl_end); +- _cupsStrFree(ppd->jcl_ps); +- +- /* +- * Free any emulations... +- */ +- +- if (ppd->num_emulations > 0) +- { +- for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++) +- { +- _cupsStrFree(emul->start); +- _cupsStrFree(emul->stop); +- } +- +- ppd_free(ppd->emulations); +- } ++ free(ppd->lang_encoding); ++ free(ppd->nickname); ++ free(ppd->patches); ++ free(ppd->jcl_begin); ++ free(ppd->jcl_end); ++ free(ppd->jcl_ps); + + /* + * Free any UI groups, subgroups, and options... +@@ -193,7 +174,7 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) + ppd_free_group(group); + +- ppd_free(ppd->groups); ++ free(ppd->groups); + } + + cupsArrayDelete(ppd->options); +@@ -204,14 +185,14 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + */ + + if (ppd->num_sizes > 0) +- ppd_free(ppd->sizes); ++ free(ppd->sizes); + + /* + * Free any constraints... + */ + + if (ppd->num_consts > 0) +- ppd_free(ppd->consts); ++ free(ppd->consts); + + /* + * Free any filters... +@@ -226,9 +207,9 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + if (ppd->num_fonts > 0) + { + for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++) +- _cupsStrFree(*font); ++ free(*font); + +- ppd_free(ppd->fonts); ++ free(ppd->fonts); + } + + /* +@@ -236,7 +217,7 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + */ + + if (ppd->num_profiles > 0) +- ppd_free(ppd->profiles); ++ free(ppd->profiles); + + /* + * Free any attributes... +@@ -246,11 +227,11 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + { + for (i = ppd->num_attrs, attr = ppd->attrs; i > 0; i --, attr ++) + { +- _cupsStrFree((*attr)->value); +- ppd_free(*attr); ++ free((*attr)->value); ++ free(*attr); + } + +- ppd_free(ppd->attrs); ++ free(ppd->attrs); + } + + cupsArrayDelete(ppd->sorted_attrs); +@@ -272,7 +253,7 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + case PPD_CUSTOM_PASSCODE : + case PPD_CUSTOM_PASSWORD : + case PPD_CUSTOM_STRING : +- _cupsStrFree(cparam->current.custom_string); ++ free(cparam->current.custom_string); + break; + + default : +@@ -320,7 +301,7 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ + * Free the whole record... + */ + +- ppd_free(ppd); ++ free(ppd); + } + + +@@ -426,7 +407,6 @@ _ppdOpen( + _ppd_localization_t localization) /* I - Localization to load */ + { + int i, j, k; /* Looping vars */ +- int count; /* Temporary count */ + _ppd_line_t line; /* Line buffer */ + ppd_file_t *ppd; /* PPD file record */ + ppd_group_t *group, /* Current group */ +@@ -444,7 +424,6 @@ _ppdOpen( + /* Human-readable text from file */ + *string, /* Code/text from file */ + *sptr, /* Pointer into string */ +- *nameptr, /* Pointer into name */ + *temp, /* Temporary string pointer */ + **tempfonts; /* Temporary fonts pointer */ + float order; /* Order dependency number */ +@@ -592,16 +571,14 @@ _ppdOpen( + if (cg->ppd_status == PPD_OK) + cg->ppd_status = PPD_MISSING_PPDADOBE4; + +- _cupsStrFree(string); +- ppd_free(line.buffer); ++ free(string); ++ free(line.buffer); + + return (NULL); + } + + DEBUG_printf(("2_ppdOpen: keyword=%s, string=%p", keyword, string)); + +- _cupsStrFree(string); +- + /* + * Allocate memory for the PPD file record... + */ +@@ -610,8 +587,8 @@ _ppdOpen( + { + cg->ppd_status = PPD_ALLOC_ERROR; + +- _cupsStrFree(string); +- ppd_free(line.buffer); ++ free(string); ++ free(line.buffer); + + return (NULL); + } +@@ -694,6 +671,8 @@ _ppdOpen( + strncmp(ll, keyword, ll_len))) + { + DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword)); ++ free(string); ++ string = NULL; + continue; + } + else if (localization == _PPD_LOCALIZATION_ICC_PROFILES) +@@ -713,6 +692,8 @@ _ppdOpen( + if (i >= (int)(sizeof(color_keywords) / sizeof(color_keywords[0]))) + { + DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword)); ++ free(string); ++ string = NULL; + continue; + } + } +@@ -808,7 +789,7 @@ _ppdOpen( + * Say all PPD files are UTF-8, since we convert to UTF-8... + */ + +- ppd->lang_encoding = _cupsStrAlloc("UTF-8"); ++ ppd->lang_encoding = strdup("UTF-8"); + encoding = _ppdGetEncoding(string); + } + else if (!strcmp(keyword, "LanguageVersion")) +@@ -829,10 +810,10 @@ _ppdOpen( + + + cupsCharsetToUTF8(utf8, string, sizeof(utf8), encoding); +- ppd->nickname = _cupsStrAlloc((char *)utf8); ++ ppd->nickname = strdup((char *)utf8); + } + else +- ppd->nickname = _cupsStrAlloc(string); ++ ppd->nickname = strdup(string); + } + else if (!strcmp(keyword, "Product")) + ppd->product = string; +@@ -842,17 +823,17 @@ _ppdOpen( + ppd->ttrasterizer = string; + else if (!strcmp(keyword, "JCLBegin")) + { +- ppd->jcl_begin = _cupsStrAlloc(string); ++ ppd->jcl_begin = strdup(string); + ppd_decode(ppd->jcl_begin); /* Decode quoted string */ + } + else if (!strcmp(keyword, "JCLEnd")) + { +- ppd->jcl_end = _cupsStrAlloc(string); ++ ppd->jcl_end = strdup(string); + ppd_decode(ppd->jcl_end); /* Decode quoted string */ + } + else if (!strcmp(keyword, "JCLToPSInterpreter")) + { +- ppd->jcl_ps = _cupsStrAlloc(string); ++ ppd->jcl_ps = strdup(string); + ppd_decode(ppd->jcl_ps); /* Decode quoted string */ + } + else if (!strcmp(keyword, "AccurateScreensSupport")) +@@ -921,10 +902,10 @@ _ppdOpen( + ppd->num_filters ++; + + /* +- * Retain a copy of the filter string... ++ * Make a copy of the filter string... + */ + +- *filter = _cupsStrRetain(string); ++ *filter = strdup(string); + } + else if (!strcmp(keyword, "Throughput")) + ppd->throughput = atoi(string); +@@ -948,7 +929,7 @@ _ppdOpen( + } + + ppd->fonts = tempfonts; +- ppd->fonts[ppd->num_fonts] = _cupsStrAlloc(name); ++ ppd->fonts[ppd->num_fonts] = strdup(name); + ppd->num_fonts ++; + } + else if (!strncmp(keyword, "ParamCustom", 11)) +@@ -1113,7 +1094,7 @@ _ppdOpen( + strlcpy(choice->text, text[0] ? text : _("Custom"), + sizeof(choice->text)); + +- choice->code = _cupsStrAlloc(string); ++ choice->code = strdup(string); + + if (custom_option->section == PPD_ORDER_JCL) + ppd_decode(choice->code); +@@ -1162,59 +1143,23 @@ _ppdOpen( + else if (!strcmp(string, "Plus90")) + ppd->landscape = 90; + } +- else if (!strcmp(keyword, "Emulators") && string) ++ else if (!strcmp(keyword, "Emulators") && string && ppd->num_emulations == 0) + { +- for (count = 1, sptr = string; sptr != NULL;) +- if ((sptr = strchr(sptr, ' ')) != NULL) +- { +- count ++; +- while (*sptr == ' ') +- sptr ++; +- } +- +- ppd->num_emulations = count; +- if ((ppd->emulations = calloc(count, sizeof(ppd_emul_t))) == NULL) +- { +- cg->ppd_status = PPD_ALLOC_ERROR; +- +- goto error; +- } +- +- for (i = 0, sptr = string; i < count; i ++) +- { +- for (nameptr = ppd->emulations[i].name; +- *sptr != '\0' && *sptr != ' '; +- sptr ++) +- if (nameptr < (ppd->emulations[i].name + sizeof(ppd->emulations[i].name) - 1)) +- *nameptr++ = *sptr; +- +- *nameptr = '\0'; +- +- while (*sptr == ' ') +- sptr ++; +- } +- } +- else if (!strncmp(keyword, "StartEmulator_", 14)) +- { +- ppd_decode(string); ++ /* ++ * Issue #5562: Samsung printer drivers incorrectly use Emulators keyword ++ * to configure themselves ++ * ++ * The Emulators keyword was loaded but never used by anything in CUPS, ++ * and has no valid purpose in CUPS. The old code was removed due to a ++ * memory leak (Issue #5475), so the following (new) code supports a single ++ * name for the Emulators keyword, allowing these drivers to work until we ++ * remove PPD and driver support entirely in a future version of CUPS. ++ */ + +- for (i = 0; i < ppd->num_emulations; i ++) +- if (!strcmp(keyword + 14, ppd->emulations[i].name)) +- { +- ppd->emulations[i].start = string; +- string = NULL; +- } +- } +- else if (!strncmp(keyword, "StopEmulator_", 13)) +- { +- ppd_decode(string); ++ ppd->num_emulations = 1; ++ ppd->emulations = calloc(1, sizeof(ppd_emul_t)); + +- for (i = 0; i < ppd->num_emulations; i ++) +- if (!strcmp(keyword + 13, ppd->emulations[i].name)) +- { +- ppd->emulations[i].stop = string; +- string = NULL; +- } ++ strlcpy(ppd->emulations[0].name, string, sizeof(ppd->emulations[0].name)); + } + else if (!strcmp(keyword, "JobPatchFile")) + { +@@ -1369,7 +1314,7 @@ _ppdOpen( + + option->section = PPD_ORDER_ANY; + +- _cupsStrFree(string); ++ free(string); + string = NULL; + + /* +@@ -1397,7 +1342,7 @@ _ppdOpen( + strlcpy(choice->text, + custom_attr->text[0] ? custom_attr->text : _("Custom"), + sizeof(choice->text)); +- choice->code = _cupsStrRetain(custom_attr->value); ++ choice->code = strdup(custom_attr->value); + } + } + else if (!strcmp(keyword, "JCLOpenUI")) +@@ -1476,7 +1421,7 @@ _ppdOpen( + option->section = PPD_ORDER_JCL; + group = NULL; + +- _cupsStrFree(string); ++ free(string); + string = NULL; + + /* +@@ -1500,14 +1445,14 @@ _ppdOpen( + strlcpy(choice->text, + custom_attr->text[0] ? custom_attr->text : _("Custom"), + sizeof(choice->text)); +- choice->code = _cupsStrRetain(custom_attr->value); ++ choice->code = strdup(custom_attr->value); + } + } + else if (!strcmp(keyword, "CloseUI") || !strcmp(keyword, "JCLCloseUI")) + { + option = NULL; + +- _cupsStrFree(string); ++ free(string); + string = NULL; + } + else if (!strcmp(keyword, "OpenGroup")) +@@ -1554,14 +1499,14 @@ _ppdOpen( + if (group == NULL) + goto error; + +- _cupsStrFree(string); ++ free(string); + string = NULL; + } + else if (!strcmp(keyword, "CloseGroup")) + { + group = NULL; + +- _cupsStrFree(string); ++ free(string); + string = NULL; + } + else if (!strcmp(keyword, "OrderDependency")) +@@ -1619,7 +1564,7 @@ _ppdOpen( + option->order = order; + } + +- _cupsStrFree(string); ++ free(string); + string = NULL; + } + else if (!strncmp(keyword, "Default", 7)) +@@ -1863,7 +1808,7 @@ _ppdOpen( + * Don't add this one as an attribute... + */ + +- _cupsStrFree(string); ++ free(string); + string = NULL; + } + else if (!strcmp(keyword, "PaperDimension")) +@@ -1885,7 +1830,7 @@ _ppdOpen( + size->width = (float)_cupsStrScand(string, &sptr, loc); + size->length = (float)_cupsStrScand(sptr, NULL, loc); + +- _cupsStrFree(string); ++ free(string); + string = NULL; + } + else if (!strcmp(keyword, "ImageableArea")) +@@ -1909,7 +1854,7 @@ _ppdOpen( + size->right = (float)_cupsStrScand(sptr, &sptr, loc); + size->top = (float)_cupsStrScand(sptr, NULL, loc); + +- _cupsStrFree(string); ++ free(string); + string = NULL; + } + else if (option != NULL && +@@ -1965,7 +1910,7 @@ _ppdOpen( + (mask & (PPD_KEYWORD | PPD_STRING)) == (PPD_KEYWORD | PPD_STRING)) + ppd_add_attr(ppd, keyword, name, text, string); + else +- _cupsStrFree(string); ++ free(string); + } + + /* +@@ -1978,7 +1923,8 @@ _ppdOpen( + goto error; + } + +- ppd_free(line.buffer); ++ free(string); ++ free(line.buffer); + + /* + * Reset language preferences... +@@ -2060,8 +2006,8 @@ _ppdOpen( + + error: + +- _cupsStrFree(string); +- ppd_free(line.buffer); ++ free(string); ++ free(line.buffer); + + ppdClose(ppd); + +@@ -2500,9 +2446,9 @@ ppd_free_filters(ppd_file_t *ppd) /* I - PPD file */ + if (ppd->num_filters > 0) + { + for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++) +- _cupsStrFree(*filter); ++ free(*filter); + +- ppd_free(ppd->filters); ++ free(ppd->filters); + + ppd->num_filters = 0; + ppd->filters = NULL; +@@ -2529,7 +2475,7 @@ ppd_free_group(ppd_group_t *group) /* I - Group to free */ + i --, option ++) + ppd_free_option(option); + +- ppd_free(group->options); ++ free(group->options); + } + + if (group->num_subgroups > 0) +@@ -2539,7 +2485,7 @@ ppd_free_group(ppd_group_t *group) /* I - Group to free */ + i --, subgroup ++) + ppd_free_group(subgroup); + +- ppd_free(group->subgroups); ++ free(group->subgroups); + } + } + +@@ -2561,10 +2507,10 @@ ppd_free_option(ppd_option_t *option) /* I - Option to free */ + i > 0; + i --, choice ++) + { +- _cupsStrFree(choice->code); ++ free(choice->code); + } + +- ppd_free(option->choices); ++ free(option->choices); + } + } + +@@ -3262,7 +3208,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ + lineptr ++; + } + +- *string = _cupsStrAlloc(lineptr); ++ *string = strdup(lineptr); + + mask |= PPD_STRING; + } +@@ -3384,7 +3330,7 @@ ppd_update_filters(ppd_file_t *ppd,/* I - PPD file */ + filter += ppd->num_filters; + ppd->num_filters ++; + +- *filter = _cupsStrAlloc(buffer); ++ *filter = strdup(buffer); + } + while ((attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL); + +diff --git a/cups/ppd.h b/cups/ppd.h +index 3e281bd..340b7ca 100644 +--- a/cups/ppd.h ++++ b/cups/ppd.h +@@ -315,8 +315,8 @@ typedef struct ppd_file_s /**** PPD File ****/ + int throughput; /* Pages per minute */ + ppd_cs_t colorspace; /* Default colorspace */ + char *patches; /* Patch commands to be sent to printer */ +- int num_emulations; /* Number of emulations supported */ +- ppd_emul_t *emulations; /* Emulations and the code to invoke them */ ++ int num_emulations; /* Number of emulations supported (no longer supported) @private@ */ ++ ppd_emul_t *emulations; /* Emulations and the code to invoke them (no longer supported) @private@ */ + char *jcl_begin; /* Start JCL commands */ + char *jcl_ps; /* Enter PostScript interpreter */ + char *jcl_end; /* End JCL commands */ +diff --git a/cups/string.c b/cups/string.c +index 538a263..bb148dd 100644 +--- a/cups/string.c ++++ b/cups/string.c +@@ -303,6 +303,13 @@ _cupsStrFree(const char *s) /* I - String to free */ + + key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str)); + ++ if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL && ++ item == key) ++ { ++ /* ++ * Found it, dereference... ++ */ ++ + #ifdef DEBUG_GUARDS + if (key->guard != _CUPS_STR_GUARD) + { +@@ -312,13 +319,6 @@ _cupsStrFree(const char *s) /* I - String to free */ + } + #endif /* DEBUG_GUARDS */ + +- if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL && +- item == key) +- { +- /* +- * Found it, dereference... +- */ +- + item->ref_count --; + + if (!item->ref_count) +diff --git a/ppdc/ppdc-import.cxx b/ppdc/ppdc-import.cxx +index d41cbb9..2999312 100644 +--- a/ppdc/ppdc-import.cxx ++++ b/ppdc/ppdc-import.cxx +@@ -334,6 +334,9 @@ ppdcSource::import_ppd(const char *f) // I - Filename + } + } + ++ if (ppd) ++ ppdClose(ppd); ++ + return (1); + } + +diff --git a/scheduler/ipp.c b/scheduler/ipp.c +index 767ed25..207ebe7 100644 +--- a/scheduler/ipp.c ++++ b/scheduler/ipp.c +@@ -2859,8 +2859,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ + if (!strcmp(attr->values[i].string.text, "none")) + continue; + +- printer->reasons[printer->num_reasons] = +- _cupsStrRetain(attr->values[i].string.text); ++ printer->reasons[printer->num_reasons] = _cupsStrAlloc(attr->values[i].string.text); + printer->num_reasons ++; + + if (!strcmp(attr->values[i].string.text, "paused") && +@@ -5310,8 +5309,7 @@ copy_printer_attrs( + + if ((p2_uri = ippFindAttribute(p2->attrs, "printer-uri-supported", + IPP_TAG_URI)) != NULL) +- member_uris->values[i].string.text = +- _cupsStrRetain(p2_uri->values[0].string.text); ++ member_uris->values[i].string.text = _cupsStrAlloc(p2_uri->values[0].string.text); + else + { + httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, +diff --git a/scheduler/printers.c b/scheduler/printers.c +index 2484db6..91cbc74 100644 +--- a/scheduler/printers.c ++++ b/scheduler/printers.c +@@ -100,8 +100,7 @@ static void delete_printer_filters(cupsd_printer_t *p); + static void dirty_printer(cupsd_printer_t *p); + static void load_ppd(cupsd_printer_t *p); + static void log_ipp_conformance(cupsd_printer_t *p, const char *reason); +-static ipp_t *new_media_col(_pwg_size_t *size, const char *source, +- const char *type); ++static ipp_t *new_media_col(_pwg_size_t *size); + #ifdef __sgi + static void write_irix_config(cupsd_printer_t *p); + static void write_irix_state(cupsd_printer_t *p); +@@ -2219,7 +2218,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ + for (i = 0, name = (char *)cupsArrayFirst(p->users); + name; + i ++, name = (char *)cupsArrayNext(p->users)) +- attr->values[i].string.text = _cupsStrRetain(name); ++ attr->values[i].string.text = _cupsStrAlloc(name); + } + + ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, +@@ -2325,7 +2324,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ + for (i = 0; i < p->num_printers; i ++) + { + if (attr != NULL) +- attr->values[i].string.text = _cupsStrRetain(p->printers[i]->name); ++ attr->values[i].string.text = _cupsStrAlloc(p->printers[i]->name); + + p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type; + } +@@ -2425,7 +2424,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ + { + for (i = 0; i < oldattr->num_values; i ++) + attr->values[i].string.text = +- _cupsStrRetain(oldattr->values[i].string.text); ++ _cupsStrAlloc(oldattr->values[i].string.text); + } + } + +@@ -2479,7 +2478,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ + { + for (i = 0; i < oldattr->num_values; i ++) + attr->values[i].string.text = +- _cupsStrRetain(oldattr->values[i].string.text); ++ _cupsStrAlloc(oldattr->values[i].string.text); + } + } + +@@ -2492,7 +2491,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ + { + for (i = 0; i < oldattr->num_values; i ++) + attr->values[i].string.text = +- _cupsStrRetain(oldattr->values[i].string.text); ++ _cupsStrAlloc(oldattr->values[i].string.text); + } + } + +@@ -3799,21 +3798,19 @@ dirty_printer(cupsd_printer_t *p) /* I - Printer */ + static void + load_ppd(cupsd_printer_t *p) /* I - Printer */ + { +- int i, j, k; /* Looping vars */ ++ int i, j; /* Looping vars */ + char cache_name[1024]; /* Cache filename */ + struct stat cache_info; /* Cache file info */ + ppd_file_t *ppd; /* PPD file */ + char ppd_name[1024]; /* PPD filename */ + struct stat ppd_info; /* PPD file info */ +- int num_media; /* Number of media options */ ++ int num_media; /* Number of media values */ + ppd_size_t *size; /* Current PPD size */ + ppd_option_t *duplex, /* Duplex option */ + *output_bin, /* OutputBin option */ + *output_mode, /* OutputMode option */ + *resolution; /* (Set|JCL|)Resolution option */ +- ppd_choice_t *choice, /* Current PPD choice */ +- *input_slot, /* Current input slot */ +- *media_type; /* Current media type */ ++ ppd_choice_t *choice; /* Current PPD choice */ + ppd_attr_t *ppd_attr; /* PPD attribute */ + int xdpi, /* Horizontal resolution */ + ydpi; /* Vertical resolution */ +@@ -4037,18 +4034,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ + { + ipp_t *col; /* Collection value */ + +- input_slot = ppdFindMarkedChoice(ppd, "InputSlot"); +- media_type = ppdFindMarkedChoice(ppd, "MediaType"); +- col = new_media_col(pwgsize, +- input_slot ? +- _ppdCacheGetSource(p->pc, +- input_slot->choice) : +- NULL, +- media_type ? +- _ppdCacheGetType(p->pc, +- media_type->choice) : +- NULL); +- ++ col = new_media_col(pwgsize); + ippAddCollection(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-default", + col); + ippDelete(col); +@@ -4071,13 +4057,13 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ + for (i = p->pc->num_sizes, pwgsize = p->pc->sizes; + i > 0; + i --, pwgsize ++, val ++) +- val->string.text = _cupsStrRetain(pwgsize->map.pwg); ++ val->string.text = _cupsStrAlloc(pwgsize->map.pwg); + + if (p->pc->custom_min_keyword) + { +- val->string.text = _cupsStrRetain(p->pc->custom_min_keyword); ++ val->string.text = _cupsStrAlloc(p->pc->custom_min_keyword); + val ++; +- val->string.text = _cupsStrRetain(p->pc->custom_max_keyword); ++ val->string.text = _cupsStrAlloc(p->pc->custom_max_keyword); + } + } + +@@ -4129,7 +4115,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ + val = attr->values; + i > 0; + i --, pwgsource ++, val ++) +- val->string.text = _cupsStrRetain(pwgsource->pwg); ++ val->string.text = _cupsStrAlloc(pwgsource->pwg); + } + + /* +@@ -4145,7 +4131,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ + val = attr->values; + i > 0; + i --, pwgtype ++, val ++) +- val->string.text = _cupsStrRetain(pwgtype->pwg); ++ val->string.text = _cupsStrAlloc(pwgtype->pwg); + } + + /* +@@ -4244,89 +4230,19 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ + * media-col-database + */ + +- num_media = p->pc->num_sizes; +- if (p->pc->num_sources) ++ if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-database", p->pc->num_sizes, NULL)) != NULL) + { +- if (p->pc->num_types > 0) +- num_media += p->pc->num_sizes * p->pc->num_sources * +- p->pc->num_types; +- else +- num_media += p->pc->num_sizes * p->pc->num_sources; +- } +- else if (p->pc->num_types) +- num_media += p->pc->num_sizes * p->pc->num_types; ++ /* ++ * Add each page size without source or type... ++ */ + +- if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, +- "media-col-database", num_media, +- NULL)) != NULL) +- { +- for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, val = attr->values; +- i > 0; +- i --, pwgsize ++) ++ for (i = 0, pwgsize = p->pc->sizes; i < p->pc->num_sizes; i ++, pwgsize ++) + { +- /* +- * Start by adding the page size without source or type... +- */ ++ ipp_t *col = new_media_col(pwgsize); + +- ppdMarkOption(ppd, "PageSize", pwgsize->map.ppd); +- +- val->collection = new_media_col(pwgsize, NULL, NULL); +- val ++; +- +- /* +- * Then add the specific, supported combinations of size, source, and +- * type... +- */ +- +- if (p->pc->num_sources > 0) +- { +- for (j = p->pc->num_sources, pwgsource = p->pc->sources; +- j > 0; +- j --, pwgsource ++) +- { +- ppdMarkOption(ppd, "InputSlot", pwgsource->ppd); +- +- if (p->pc->num_types > 0) +- { +- for (k = p->pc->num_types, pwgtype = p->pc->types; +- k > 0; +- k --, pwgtype ++) +- { +- if (!ppdMarkOption(ppd, "MediaType", pwgtype->ppd)) +- { +- val->collection = new_media_col(pwgsize, pwgsource->pwg, +- pwgtype->pwg); +- val ++; +- } +- } +- } +- else if (!ppdConflicts(ppd)) +- { +- val->collection = new_media_col(pwgsize, pwgsource->pwg, NULL); +- val ++; +- } +- } +- } +- else if (p->pc->num_types > 0) +- { +- for (j = p->pc->num_types, pwgtype = p->pc->types; +- j > 0; +- j --, pwgtype ++) +- { +- if (!ppdMarkOption(ppd, "MediaType", pwgtype->ppd)) +- { +- val->collection = new_media_col(pwgsize, NULL, pwgtype->pwg); +- val ++; +- } +- } +- } ++ ippSetCollection(p->ppd_attrs, &attr, i, col); ++ ippDelete(col); + } +- +- /* +- * Update the number of media-col-database values... +- */ +- +- attr->num_values = val - attr->values; + } + } + +@@ -5081,9 +4997,7 @@ log_ipp_conformance( + */ + + static ipp_t * /* O - Collection value */ +-new_media_col(_pwg_size_t *size, /* I - media-size/margin values */ +- const char *source, /* I - media-source value */ +- const char *type) /* I - media-type value */ ++new_media_col(_pwg_size_t *size) /* I - media-size/margin values */ + { + ipp_t *media_col, /* Collection value */ + *media_size; /* media-size value */ +@@ -5092,29 +5006,15 @@ new_media_col(_pwg_size_t *size, /* I - media-size/margin values */ + media_col = ippNew(); + + media_size = ippNew(); +- ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER, +- "x-dimension", size->width); +- ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER, +- "y-dimension", size->length); ++ ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "x-dimension", size->width); ++ ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "y-dimension", size->length); + ippAddCollection(media_col, IPP_TAG_PRINTER, "media-size", media_size); + ippDelete(media_size); + +- ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, +- "media-bottom-margin", size->bottom); +- ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, +- "media-left-margin", size->left); +- ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, +- "media-right-margin", size->right); +- ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, +- "media-top-margin", size->top); +- +- if (source) +- ippAddString(media_col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-source", +- NULL, source); +- +- if (type) +- ippAddString(media_col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-type", +- NULL, type); ++ ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-bottom-margin", size->bottom); ++ ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-left-margin", size->left); ++ ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-right-margin", size->right); ++ ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-top-margin", size->top); + + return (media_col); + } diff --git a/SOURCES/cups-str4528.patch b/SOURCES/cups-str4528.patch new file mode 100644 index 0000000..2705fac --- /dev/null +++ b/SOURCES/cups-str4528.patch @@ -0,0 +1,739 @@ +diff --git a/cups/usersys.c b/cups/usersys.c +index ae66578..5a78f5d 100644 +--- a/cups/usersys.c ++++ b/cups/usersys.c +@@ -59,23 +59,45 @@ + + + /* +- * Local functions... ++ * Local types... + */ + +-static void cups_read_client_conf(cups_file_t *fp, +- _cups_globals_t *cg, +- const char *cups_encryption, +- const char *cups_server, +- const char *cups_user, ++typedef struct _cups_client_conf_s /**** client.conf config data ****/ ++{ ++#ifdef HAVE_SSL ++ int ssl_options; /* SSLOptions values */ ++#endif /* HAVE_SSL */ ++ int any_root, /* Allow any (e.g., self-signed) root */ ++ expired_certs, /* Allow expired certs */ ++ expired_root; /* Allow expired root */ ++ http_encryption_t encryption; /* Encryption setting */ ++ char user[65], /* User name */ ++ server_name[256]; ++ /* Server hostname */ + #ifdef HAVE_GSSAPI +- const char *cups_gssservicename, ++ char gss_service_name[32]; ++ /* Kerberos service name */ + #endif /* HAVE_GSSAPI */ +- const char *cups_anyroot, +- const char *cups_expiredroot, +- const char *cups_expiredcerts, +- int ssl_options); ++} _cups_client_conf_t; + + ++/* ++ * Local functions... ++ */ ++ ++static void cups_finalize_client_conf(_cups_client_conf_t *cc); ++static void cups_init_client_conf(_cups_client_conf_t *cc); ++static void cups_read_client_conf(cups_file_t *fp, _cups_client_conf_t *cc); ++static void cups_set_encryption(_cups_client_conf_t *cc, const char *value); ++#ifdef HAVE_GSSAPI ++static void cups_set_gss_service_name(_cups_client_conf_t *cc, const char *value); ++#endif /* HAVE_GSSAPI */ ++static void cups_set_server_name(_cups_client_conf_t *cc, const char *value); ++#ifdef HAVE_SSL ++static void cups_set_ssl_options(_cups_client_conf_t *cc, const char *value); ++#endif /* HAVE_SSL */ ++static void cups_set_user(_cups_client_conf_t *cc, const char *value); ++ + /* + * 'cupsEncryption()' - Get the current encryption settings. + * +@@ -784,119 +806,249 @@ void + _cupsSetDefaults(void) + { + cups_file_t *fp; /* File */ +- const char *home, /* Home directory of user */ +- *cups_encryption, /* CUPS_ENCRYPTION env var */ +- *cups_server, /* CUPS_SERVER env var */ +- *cups_user, /* CUPS_USER/USER env var */ +-#ifdef HAVE_GSSAPI +- *cups_gssservicename, /* CUPS_GSSSERVICENAME env var */ +-#endif /* HAVE_GSSAPI */ +- *cups_anyroot, /* CUPS_ANYROOT env var */ +- *cups_expiredroot, /* CUPS_EXPIREDROOT env var */ +- *cups_expiredcerts; /* CUPS_EXPIREDCERTS env var */ ++ const char *home; /* Home directory of user */ + char filename[1024]; /* Filename */ ++ _cups_client_conf_t cc; /* client.conf values */ + _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ + + + DEBUG_puts("_cupsSetDefaults()"); + + /* +- * First collect environment variables... ++ * Load initial client.conf values... + */ + +- cups_encryption = getenv("CUPS_ENCRYPTION"); +- cups_server = getenv("CUPS_SERVER"); +-#ifdef HAVE_GSSAPI +- cups_gssservicename = getenv("CUPS_GSSSERVICENAME"); +-#endif /* HAVE_GSSAPI */ +- cups_anyroot = getenv("CUPS_ANYROOT"); +- cups_expiredroot = getenv("CUPS_EXPIREDROOT"); +- cups_expiredcerts = getenv("CUPS_EXPIREDCERTS"); ++ cups_init_client_conf(&cc); + +- if ((cups_user = getenv("CUPS_USER")) == NULL) ++ /* ++ * Read the /etc/cups/client.conf and ~/.cups/client.conf files, if ++ * present. ++ */ ++ ++ snprintf(filename, sizeof(filename), "%s/client.conf", cg->cups_serverroot); ++ if ((fp = cupsFileOpen(filename, "r")) != NULL) ++ { ++ cups_read_client_conf(fp, &cc); ++ cupsFileClose(fp); ++ } ++ ++# ifdef HAVE_GETEUID ++ if ((geteuid() == getuid() || !getuid()) && getegid() == getgid() && ++ (home = getenv("HOME")) != NULL) ++# else ++ if ((home = getenv("HOME")) != NULL) ++# endif + { + /* +- * Try the USER environment variable... ++ * Look for ~/.cups/client.conf... + */ + +- if ((cups_user = getenv("USER")) != NULL) ++ snprintf(filename, sizeof(filename), "%s/.cups/client.conf", home); ++ if ((fp = cupsFileOpen(filename, "r")) != NULL) + { +- /* +- * Validate USER matches the current UID, otherwise don't allow it to +- * override things... This makes sure that printing after doing su or +- * sudo records the correct username. +- */ ++ cups_read_client_conf(fp, &cc); ++ cupsFileClose(fp); ++ } ++ } ++ ++ /* ++ * Finalize things so every client.conf value is set... ++ */ + +- struct passwd *pw; /* Account information */ ++ cups_finalize_client_conf(&cc); + +- if ((pw = getpwnam(cups_user)) == NULL || pw->pw_uid != getuid()) +- cups_user = NULL; ++ if (cg->encryption == (http_encryption_t)-1) ++ cg->encryption = cc.encryption; ++ ++ if (!cg->server[0] || !cg->ipp_port) ++ cupsSetServer(cc.server_name); ++ ++ if (!cg->ipp_port) ++ { ++ const char *ipp_port; /* IPP_PORT environment variable */ ++ ++ if ((ipp_port = getenv("IPP_PORT")) != NULL) ++ { ++ if ((cg->ipp_port = atoi(ipp_port)) <= 0) ++ cg->ipp_port = CUPS_DEFAULT_IPP_PORT; + } ++ else ++ cg->ipp_port = CUPS_DEFAULT_IPP_PORT; + } + ++ if (!cg->user[0]) ++ strlcpy(cg->user, cc.user, sizeof(cg->user)); ++ ++#ifdef HAVE_GSSAPI ++ if (!cg->gss_service_name[0]) ++ strlcpy(cg->gss_service_name, cc.gss_service_name, sizeof(cg->gss_service_name)); ++#endif /* HAVE_GSSAPI */ ++ ++ if (cg->any_root < 0) ++ cg->any_root = cc.any_root; ++ ++ if (cg->expired_certs < 0) ++ cg->expired_certs = cc.expired_certs; ++ ++ if (cg->expired_root < 0) ++ cg->expired_root = cc.expired_root; ++ ++#ifdef HAVE_SSL ++ _httpTLSSetOptions(cc.ssl_options); ++#endif /* HAVE_SSL */ ++} ++ ++ ++/* ++ * 'cups_boolean_value()' - Convert a string to a boolean value. ++ */ ++ ++static int /* O - Boolean value */ ++cups_boolean_value(const char *value) /* I - String value */ ++{ ++ return (!_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "true")); ++} ++ ++ ++/* ++ * 'cups_finalize_client_conf()' - Finalize client.conf values. ++ */ ++ ++static void ++cups_finalize_client_conf( ++ _cups_client_conf_t *cc) /* I - client.conf values */ ++{ ++ const char *value; /* Environment variable */ ++ ++ ++ if ((value = getenv("CUPS_ANYROOT")) != NULL) ++ cc->any_root = cups_boolean_value(value); ++ ++ if ((value = getenv("CUPS_ENCRYPTION")) != NULL) ++ cups_set_encryption(cc, value); ++ ++ if ((value = getenv("CUPS_EXPIREDCERTS")) != NULL) ++ cc->expired_certs = cups_boolean_value(value); ++ ++#ifdef HAVE_GSSAPI ++ if ((value = getenv("CUPS_GSSSERVICENAME")) != NULL) ++ cups_set_gss_service_name(cc, value); ++#endif /* HAVE_GSSAPI */ ++ ++ if ((value = getenv("CUPS_SERVER")) != NULL) ++ cups_set_server_name(cc, value); ++ ++ if ((value = getenv("CUPS_USER")) != NULL) ++ cups_set_user(cc, value); ++ ++ if ((value = getenv("CUPS_EXPIREDROOT")) != NULL) ++ cc->expired_root = cups_boolean_value(value); ++ + /* +- * Then, if needed, read the ~/.cups/client.conf or /etc/cups/client.conf +- * files to get the default values... ++ * Then apply defaults for those values that haven't been set... + */ + +- if (cg->encryption == (http_encryption_t)-1 || !cg->server[0] || +- !cg->user[0] || !cg->ipp_port) ++ if (cc->any_root < 0) ++ cc->any_root = 1; ++ ++ if (cc->encryption == (http_encryption_t)-1) ++ cc->encryption = HTTP_ENCRYPT_IF_REQUESTED; ++ ++ if (cc->expired_certs < 0) ++ cc->expired_certs = 1; ++ ++ if (cc->expired_root < 0) ++ cc->expired_root = 0; ++ ++#ifdef HAVE_GSSAPI ++ if (!cc->gss_service_name[0]) ++ cups_set_gss_service_name(cc, CUPS_DEFAULT_GSSSERVICENAME); ++#endif /* HAVE_GSSAPI */ ++ ++ if (!cc->server_name[0]) + { ++#ifdef CUPS_DEFAULT_DOMAINSOCKET + /* +- * Look for CUPS_SERVERROOT/client.conf... ++ * If we are compiled with domain socket support, only use the ++ * domain socket if it exists and has the right permissions... + */ + +- snprintf(filename, sizeof(filename), "%s/client.conf", +- cg->cups_serverroot); +- fp = cupsFileOpen(filename, "r"); ++ if (!access(CUPS_DEFAULT_DOMAINSOCKET, R_OK)) ++ cups_set_server_name(cc, CUPS_DEFAULT_DOMAINSOCKET); ++ else ++#endif /* CUPS_DEFAULT_DOMAINSOCKET */ ++ cups_set_server_name(cc, "localhost"); ++ } + ++ if (!cc->user[0]) ++ { ++#ifdef WIN32 + /* +- * Read the configuration file and apply any environment variables; both +- * functions handle NULL cups_file_t pointers... ++ * Get the current user name from the OS... + */ + +- cups_read_client_conf(fp, cg, cups_encryption, cups_server, cups_user, +-#ifdef HAVE_GSSAPI +- cups_gssservicename, +-#endif /* HAVE_GSSAPI */ +- cups_anyroot, cups_expiredroot, +- cups_expiredcerts, 1); +- cupsFileClose(fp); ++ DWORD size; /* Size of string */ + ++ size = sizeof(cc->user); ++ if (!GetUserName(cc->user, &size)) ++#else + /* +- * Then user defaults, if it is safe to do so... ++ * Try the USER environment variable as the default username... + */ + +-#ifdef HAVE_GETEUID +- if ((geteuid() == getuid() || !getuid()) && getegid() == getgid() && +- (home = getenv("HOME")) != NULL) +-#else +- if ((home = getenv("HOME")) != NULL) +-#endif ++ const char *envuser = getenv("USER"); ++ /* Default username */ ++ struct passwd *pw = NULL; /* Account information */ ++ ++ if (envuser) + { + /* +- * Look for ~/.cups/client.conf... ++ * Validate USER matches the current UID, otherwise don't allow it to ++ * override things... This makes sure that printing after doing su ++ * or sudo records the correct username. + */ + +- snprintf(filename, sizeof(filename), "%s/.cups/client.conf", home); +- fp = cupsFileOpen(filename, "r"); ++ if ((pw = getpwnam(envuser)) != NULL && pw->pw_uid != getuid()) ++ pw = NULL; ++ } ++ ++ if (!pw) ++ pw = getpwuid(getuid()); + ++ if (pw) ++ strlcpy(cc->user, pw->pw_name, sizeof(cc->user)); ++ else ++#endif /* WIN32 */ ++ { + /* +- * Read the configuration file and apply any environment variables; both +- * functions handle NULL cups_file_t pointers... ++ * Use the default "unknown" user name... + */ + +- cups_read_client_conf(fp, cg, cups_encryption, cups_server, cups_user, +-#ifdef HAVE_GSSAPI +- cups_gssservicename, +-#endif /* HAVE_GSSAPI */ +- cups_anyroot, cups_expiredroot, +- cups_expiredcerts, 0); +- cupsFileClose(fp); ++ strlcpy(cc->user, "unknown", sizeof(cc->user)); + } + } + } + ++/* ++ * 'cups_init_client_conf()' - Initialize client.conf values. ++ */ ++ ++static void ++cups_init_client_conf( ++ _cups_client_conf_t *cc) /* I - client.conf values */ ++{ ++ /* ++ * Clear all values to "not set"... ++ */ ++ ++ memset(cc, 0, sizeof(_cups_client_conf_t)); ++ ++ cc->encryption = (http_encryption_t)-1; ++ cc->any_root = -1; ++ cc->expired_certs = -1; ++ cc->expired_root = -1; ++} ++ + + /* + * 'cups_read_client_conf()' - Read a client.conf file. +@@ -904,35 +1056,12 @@ _cupsSetDefaults(void) + + static void + cups_read_client_conf( +- cups_file_t *fp, /* I - File to read */ +- _cups_globals_t *cg, /* I - Global data */ +- const char *cups_encryption, /* I - CUPS_ENCRYPTION env var */ +- const char *cups_server, /* I - CUPS_SERVER env var */ +- const char *cups_user, /* I - CUPS_USER env var */ +-#ifdef HAVE_GSSAPI +- const char *cups_gssservicename, +- /* I - CUPS_GSSSERVICENAME env var */ +-#endif /* HAVE_GSSAPI */ +- const char *cups_anyroot, /* I - CUPS_ANYROOT env var */ +- const char *cups_expiredroot, /* I - CUPS_EXPIREDROOT env var */ +- const char *cups_expiredcerts, /* I - CUPS_EXPIREDCERTS env var */ +- int ssl_options) /* I - Allow setting of SSLOptions? */ ++ cups_file_t *fp, /* I - File to read */ ++ _cups_client_conf_t *cc) /* I - client.conf values */ + { + int linenum; /* Current line number */ + char line[1024], /* Line from file */ +- *value, /* Pointer into line */ +- encryption[1024], /* Encryption value */ +-#ifndef __APPLE__ +- server_name[1024], /* ServerName value */ +-#endif /* !__APPLE__ */ +- user[256], /* User value */ +- any_root[1024], /* AllowAnyRoot value */ +- expired_root[1024], /* AllowExpiredRoot value */ +- expired_certs[1024]; /* AllowExpiredCerts value */ +-#ifdef HAVE_GSSAPI +- char gss_service_name[32]; /* GSSServiceName value */ +-#endif /* HAVE_GSSAPI */ +- ++ *value; /* Pointer into line */ + + /* + * Read from the file... +@@ -941,214 +1070,146 @@ cups_read_client_conf( + linenum = 0; + while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) + { +- if (!cups_encryption && cg->encryption == (http_encryption_t)-1 && +- !_cups_strcasecmp(line, "Encryption") && value) +- { +- strlcpy(encryption, value, sizeof(encryption)); +- cups_encryption = encryption; +- } ++ if (!_cups_strcasecmp(line, "Encryption") && value) ++ cups_set_encryption(cc, value); + #ifndef __APPLE__ + /* + * The Server directive is not supported on OS X due to app sandboxing + * restrictions, i.e. not all apps request network access. + */ +- else if (!cups_server && (!cg->server[0] || !cg->ipp_port) && +- !_cups_strcasecmp(line, "ServerName") && value) +- { +- strlcpy(server_name, value, sizeof(server_name)); +- cups_server = server_name; +- } ++ else if (!_cups_strcasecmp(line, "ServerName") && value) ++ cups_set_server_name(cc, value); + #endif /* !__APPLE__ */ +- else if (!cups_user && !_cups_strcasecmp(line, "User") && value) +- { +- strlcpy(user, value, sizeof(user)); +- cups_user = user; +- } +- else if (!cups_anyroot && !_cups_strcasecmp(line, "AllowAnyRoot") && value) +- { +- strlcpy(any_root, value, sizeof(any_root)); +- cups_anyroot = any_root; +- } +- else if (!cups_expiredroot && !_cups_strcasecmp(line, "AllowExpiredRoot") && +- value) +- { +- strlcpy(expired_root, value, sizeof(expired_root)); +- cups_expiredroot = expired_root; +- } +- else if (!cups_expiredcerts && !_cups_strcasecmp(line, "AllowExpiredCerts") && +- value) +- { +- strlcpy(expired_certs, value, sizeof(expired_certs)); +- cups_expiredcerts = expired_certs; +- } ++ else if (!_cups_strcasecmp(line, "User") && value) ++ cups_set_user(cc, value); ++ else if (!_cups_strcasecmp(line, "AllowAnyRoot") && value) ++ cc->any_root = cups_boolean_value(value); ++ else if (!_cups_strcasecmp(line, "AllowExpiredRoot") && value) ++ cc->expired_root = cups_boolean_value(value); ++ else if (!_cups_strcasecmp(line, "AllowExpiredCerts") && value) ++ cc->expired_certs = cups_boolean_value(value); + #ifdef HAVE_GSSAPI +- else if (!cups_gssservicename && !_cups_strcasecmp(line, "GSSServiceName") && +- value) +- { +- strlcpy(gss_service_name, value, sizeof(gss_service_name)); +- cups_gssservicename = gss_service_name; +- } ++ else if (!_cups_strcasecmp(line, "GSSServiceName") && value) ++ cups_set_gss_service_name(cc, value); + #endif /* HAVE_GSSAPI */ +- else if (ssl_options && !_cups_strcasecmp(line, "SSLOptions") && value) +- { +- /* +- * SSLOptions [AllowRC4] [AllowSSL3] [MinTLS1.2] [None] +- */ +- +- int options = 0; /* SSL/TLS options */ +- char *start, /* Start of option */ +- *end; /* End of option */ +- +- for (start = value; *start; start = end) +- { +- /* +- * Find end of keyword... +- */ +- +- end = start; +- while (*end && !_cups_isspace(*end)) +- end++; +- +- if (*end) +- *end++ = '\0'; +- +- /* +- * Compare... +- */ +- +- if (!_cups_strcasecmp(start, "AllowRC4")) +- options |= _HTTP_TLS_ALLOW_RC4; +- else if (!_cups_strcasecmp(start, "AllowSSL3")) +- options |= _HTTP_TLS_ALLOW_SSL3; +- else if (!_cups_strcasecmp(start, "MinTLS1.2")) +- options |= _HTTP_TLS_MIN_TLS12; +- else if (!_cups_strcasecmp(start, "None")) +- options = 0; +- } +- +- _httpTLSSetOptions(options); +- } ++ else if (!_cups_strcasecmp(line, "SSLOptions") && value) ++ cups_set_ssl_options(cc, value); + } ++} + +- /* +- * Set values... +- */ ++/* ++ * 'cups_set_encryption()' - Set the Encryption value. ++ */ + +- if (cg->encryption == (http_encryption_t)-1 && cups_encryption) +- { +- if (!_cups_strcasecmp(cups_encryption, "never")) +- cg->encryption = HTTP_ENCRYPT_NEVER; +- else if (!_cups_strcasecmp(cups_encryption, "always")) +- cg->encryption = HTTP_ENCRYPT_ALWAYS; +- else if (!_cups_strcasecmp(cups_encryption, "required")) +- cg->encryption = HTTP_ENCRYPT_REQUIRED; +- else +- cg->encryption = HTTP_ENCRYPT_IF_REQUESTED; +- } ++static void ++cups_set_encryption( ++ _cups_client_conf_t *cc, /* I - client.conf values */ ++ const char *value) /* I - Value */ ++{ ++ if (!_cups_strcasecmp(value, "never")) ++ cc->encryption = HTTP_ENCRYPT_NEVER; ++ else if (!_cups_strcasecmp(value, "always")) ++ cc->encryption = HTTP_ENCRYPT_ALWAYS; ++ else if (!_cups_strcasecmp(value, "required")) ++ cc->encryption = HTTP_ENCRYPT_REQUIRED; ++ else ++ cc->encryption = HTTP_ENCRYPT_IF_REQUESTED; ++} + +- if ((!cg->server[0] || !cg->ipp_port) && cups_server) +- cupsSetServer(cups_server); + +- if (!cg->server[0]) +- { +-#ifdef CUPS_DEFAULT_DOMAINSOCKET +- /* +- * If we are compiled with domain socket support, only use the +- * domain socket if it exists and has the right permissions... +- */ + +- struct stat sockinfo; /* Domain socket information */ ++/* ++ * 'cups_set_gss_service_name()' - Set the GSSServiceName value. ++ */ + +- if (!stat(CUPS_DEFAULT_DOMAINSOCKET, &sockinfo) && +- (sockinfo.st_mode & (S_IROTH | S_IWOTH)) == (S_IROTH | S_IWOTH)) +- cups_server = CUPS_DEFAULT_DOMAINSOCKET; +- else +-#endif /* CUPS_DEFAULT_DOMAINSOCKET */ +- cups_server = "localhost"; ++#ifdef HAVE_GSSAPI ++static void ++cups_set_gss_service_name( ++ _cups_client_conf_t *cc, /* I - client.conf values */ ++ const char *value) /* I - Value */ ++{ ++ strlcpy(cc->gss_service_name, value, sizeof(cc->gss_service_name)); ++} ++#endif /* HAVE_GSSAPI */ + +- cupsSetServer(cups_server); +- } + +- if (!cg->ipp_port) +- { +- const char *ipp_port; /* IPP_PORT environment variable */ ++/* ++ * 'cups_set_server_name()' - Set the ServerName value. ++ */ + +- if ((ipp_port = getenv("IPP_PORT")) != NULL) +- { +- if ((cg->ipp_port = atoi(ipp_port)) <= 0) +- cg->ipp_port = CUPS_DEFAULT_IPP_PORT; +- } +- else +- cg->ipp_port = CUPS_DEFAULT_IPP_PORT; +- } ++static void ++cups_set_server_name( ++ _cups_client_conf_t *cc, /* I - client.conf values */ ++ const char *value) /* I - Value */ ++{ ++ strlcpy(cc->server_name, value, sizeof(cc->server_name)); ++} + +- if (!cg->user[0]) +- { +- if (cups_user) +- strlcpy(cg->user, cups_user, sizeof(cg->user)); +- else +- { +-#ifdef WIN32 +- /* +- * Get the current user name from the OS... +- */ + +- DWORD size; /* Size of string */ ++/* ++ * 'cups_set_ssl_options()' - Set the SSLOptions value. ++ */ + +- size = sizeof(cg->user); +- if (!GetUserName(cg->user, &size)) +-#else +- /* +- * Get the user name corresponding to the current UID... +- */ ++#ifdef HAVE_SSL ++static void ++cups_set_ssl_options( ++ _cups_client_conf_t *cc, /* I - client.conf values */ ++ const char *value) /* I - Value */ ++{ ++ /* ++ * SSLOptions [AllowRC4] [AllowSSL3] [MinTLS1.2] [None] ++ */ + +- struct passwd *pwd; /* User/password entry */ ++ int options = 0; /* SSL/TLS options */ ++ char temp[256], /* Copy of value */ ++ *start, /* Start of option */ ++ *end; /* End of option */ + +- setpwent(); +- if ((pwd = getpwuid(getuid())) != NULL) +- { +- /* +- * Found a match! +- */ + +- strlcpy(cg->user, pwd->pw_name, sizeof(cg->user)); +- } +- else +-#endif /* WIN32 */ +- { +- /* +- * Use the default "unknown" user name... +- */ ++ strlcpy(temp, value, sizeof(temp)); + +- strcpy(cg->user, "unknown"); +- } +- } +- } ++ for (start = temp; *start; start = end) ++ { ++ /* ++ * Find end of keyword... ++ */ + +-#ifdef HAVE_GSSAPI +- if (!cups_gssservicename) +- cups_gssservicename = CUPS_DEFAULT_GSSSERVICENAME; ++ end = start; ++ while (*end && !_cups_isspace(*end)) ++ end ++; + +- strlcpy(cg->gss_service_name, cups_gssservicename, +- sizeof(cg->gss_service_name)); +-#endif /* HAVE_GSSAPI */ ++ if (*end) ++ *end++ = '\0'; + +- if (cups_anyroot) +- cg->any_root = !_cups_strcasecmp(cups_anyroot, "yes") || +- !_cups_strcasecmp(cups_anyroot, "on") || +- !_cups_strcasecmp(cups_anyroot, "true"); ++ /* ++ * Compare... ++ */ + +- if (cups_expiredroot) +- cg->expired_root = !_cups_strcasecmp(cups_expiredroot, "yes") || +- !_cups_strcasecmp(cups_expiredroot, "on") || +- !_cups_strcasecmp(cups_expiredroot, "true"); ++ if (!_cups_strcasecmp(start, "AllowRC4")) ++ options |= _HTTP_TLS_ALLOW_RC4; ++ else if (!_cups_strcasecmp(start, "AllowSSL3")) ++ options |= _HTTP_TLS_ALLOW_SSL3; ++ else if ( !_cups_strcasecmp(start, "MinTLS1.2")) ++ options|= _HTTP_TLS_MIN_TLS12; ++ else if (!_cups_strcasecmp(start, "None")) ++ options = 0; ++ } + +- if (cups_expiredcerts) +- cg->expired_certs = !_cups_strcasecmp(cups_expiredcerts, "yes") || +- !_cups_strcasecmp(cups_expiredcerts, "on") || +- !_cups_strcasecmp(cups_expiredcerts, "true"); ++ cc->ssl_options = options; + } ++#endif /* HAVE_SSL */ ++ ++/* ++ * 'cups_set_user()' - Set the User value. ++ */ + ++static void ++cups_set_user( ++ _cups_client_conf_t *cc, /* I - client.conf values */ ++ const char *value) /* I - Value */ ++{ ++ strlcpy(cc->user, value, sizeof(cc->user)); ++} + + /* + * End of "$Id: usersys.c 8498 2009-04-13 17:03:15Z mike $". diff --git a/SPECS/cups.spec b/SPECS/cups.spec index 17b9c82..e5fdbea 100644 --- a/SPECS/cups.spec +++ b/SPECS/cups.spec @@ -11,7 +11,7 @@ Summary: CUPS printing system Name: cups Epoch: 1 Version: 1.6.3 -Release: 43%{?dist} +Release: 51%{?dist} License: GPLv2 Group: System Environment/Daemons Url: http://www.cups.org/ @@ -106,6 +106,12 @@ Patch75: cups-dont-send-http-options-field.patch Patch76: cups-CVE-2018-4180.patch Patch77: cups-CVE-2018-4700.patch Patch78: cups-unlink-filename.patch +Patch79: 0001-Multiple-security-disclosure-issues.patch +Patch80: cups-str4528.patch +Patch81: 0001-Fix-cupsGetPPD-with-IPP-print-queues-STR-4725.patch +Patch82: cups-memory-consumption.patch +Patch83: cups-cupsdsavejob-sigsegv.patch +Patch84: cups-cve-rebound-fix.patch Patch100: cups-lspp.patch @@ -407,6 +413,18 @@ Sends IPP requests to the specified URI and tests and/or displays the results. %patch77 -p1 -b .session-cookie-fix # 1687571 - cupsd doesn't clean up temp files if client connection is terminated abnormally %patch78 -p1 -b .unlink-tmp-file +# 1774460 - CVE-2019-8696 and CVE-2019-8675 [rhel-7] +%patch79 -p1 -b .snmp-cve +# 1753809 - Settings in ~/.cups/client.conf aren't used +%patch80 -p1 -b .home-client +# 1715907 - CUPS- client: cupsGetPPD3() function tries to load PPD from IPP printer +# and not from the CUPS queue +%patch81 -p1 -b .download-ppd +# 1672212 - cupsd eats a lot of memory when lots of queue with extensive PPDs are created +%patch82 -p1 -b .memory-consumption +# 1813413 - [RHEL 7.7] segfault in cupsdSaveJob() caused by no space in /var +%patch83 -p1 -b .cupsdsavejob-sigsegv +%patch84 -p1 -b .cve-rebound-fix sed -i -e '1iMaxLogSize 0' conf/cupsd.conf.in @@ -581,6 +599,9 @@ for keyword in AccessLogLevel PageLogFormat; do /bin/sed -i -e "s,^$keyword\b,#$keyword,i" "$OUT" || : done +# remove cached information about queues (#1672212) +%{_bindir}/rm -f /var/cache/cups/*.data + exit 0 %post client @@ -800,6 +821,32 @@ rm -f %{cups_serverbin}/backend/smb %{_mandir}/man5/ipptoolfile.5.gz %changelog +* Mon Apr 20 2020 Zdenek Dohnal - 1:1.6.3-51 +- 1823758 - CVE-2017-18190 cups: DNS rebinding attacks via incorrect whitelist [rhel-7] + +* Wed Mar 25 2020 Zdenek Dohnal - 1:1.6.3-50 +- 1813413 - [RHEL 7.7] segfault in cupsdSaveJob() caused by no space in /var + +* Fri Feb 14 2020 Zdenek Dohnal - 1:1.6.3-49 +- more covscan issues raised from the fix 1672212 + +* Fri Feb 14 2020 Zdenek Dohnal - 1:1.6.3-48 +- fixing covscan issue from 1672212 + +* Fri Feb 14 2020 Zdenek Dohnal - 1:1.6.3-47 + - 1672212 - cupsd eats a lot of memory when lots of queue with extensive PPDs are created + +* Tue Feb 11 2020 Zdenek Dohnal - 1:1.6.3-46 +- 1715907 - CUPS- client: cupsGetPPD3() function tries to load PPD from IPP printer and not from the CUPS queue + +* Thu Feb 06 2020 Zdenek Dohnal - 1:1.6.3-45 +- fixing covscan issue from 1774460 + +* Mon Feb 03 2020 Zdenek Dohnal - 1:1.6.3-44 +- 1774460 - CVE-2019-8696 cups: stack-buffer-overflow in libcups's asn1_get_packed function [rhel-7] +- 1774461 - CVE-2019-8675 cups: stack-buffer-overflow in libcups's asn1_get_type function [rhel-7] +- 1753809 - Settings in ~/.cups/client.conf aren't used + * Thu Aug 08 2019 Tomas Korbar - 1:1.6.3-43 - 1687571 - cupsd doesn't clean tmp files if client conn is terminated abnormally