From e33d6ffd80ea8ec6b5d03f2e65253af396ba057a Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jan 21 2020 19:27:22 +0000 Subject: import cups-2.2.6-30.el8 --- diff --git a/SOURCES/0001-Multiple-security-disclosure-issues.patch b/SOURCES/0001-Multiple-security-disclosure-issues.patch new file mode 100644 index 0000000..88f81f9 --- /dev/null +++ b/SOURCES/0001-Multiple-security-disclosure-issues.patch @@ -0,0 +1,183 @@ +From 2c030c7a06e0c2b8227c7e85f5c58dfb339731d0 Mon Sep 17 00:00:00 2001 +From: Michael R Sweet +Date: Thu, 15 Aug 2019 14:06:47 -0400 +Subject: [PATCH] Multiple security/disclosure issues: + +- CVE-2019-8696 and CVE-2019-8675: Fixed SNMP buffer overflows (rdar://51685251) +- Fixed IPP buffer overflow (rdar://50035411) +- Fixed memory disclosure issue in the scheduler (rdar://51373853) +- Fixed DoS issues in the scheduler (rdar://51373929) + +diff --git a/cups/http.c b/cups/http.c +index 266a15791..fbb1bf13c 100644 +--- a/cups/http.c ++++ b/cups/http.c +@@ -1860,7 +1860,7 @@ httpPrintf(http_t *http, /* I - HTTP connection */ + ...) /* I - Additional args as needed */ + { + ssize_t 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 */ + + +@@ -1872,7 +1872,12 @@ httpPrintf(http_t *http, /* I - HTTP connection */ + + DEBUG_printf(("3httpPrintf: (" CUPS_LLFMT " bytes) %s", CUPS_LLCAST bytes, buf)); + +- if (http->data_encoding == HTTP_ENCODING_FIELDS) ++ if (bytes > (ssize_t)(sizeof(buf) - 1)) ++ { ++ http->error = ENOMEM; ++ return (-1); ++ } ++ else if (http->data_encoding == HTTP_ENCODING_FIELDS) + return ((int)httpWrite2(http, buf, (size_t)bytes)); + else + { +diff --git a/cups/ipp.c b/cups/ipp.c +index 6fae52a00..1bd59cef1 100644 +--- a/cups/ipp.c ++++ b/cups/ipp.c +@@ -4550,9 +4550,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_CUPS_CONST)); +@@ -4560,10 +4558,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 5cefee454..1d9da01f2 100644 +--- a/cups/snmp.c ++++ b/cups/snmp.c +@@ -1233,6 +1233,9 @@ asn1_get_integer( + int value; /* Integer value */ + + ++ if (*buffer >= bufend) ++ return (0); ++ + if (length > sizeof(int)) + { + (*buffer) += length; +@@ -1259,6 +1262,9 @@ asn1_get_length(unsigned char **buffer, /* IO - Pointer in buffer */ + unsigned length; /* Length */ + + ++ if (*buffer >= bufend) ++ return (0); ++ + length = **buffer; + (*buffer) ++; + +@@ -1301,6 +1307,9 @@ asn1_get_oid( + int number; /* OID number */ + + ++ if (*buffer >= bufend) ++ return (0); ++ + valend = *buffer + length; + oidptr = oid; + oidend = oid + oidsize - 1; +@@ -1349,9 +1358,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) ++; +@@ -1379,6 +1391,9 @@ asn1_get_string( + char *string, /* I - String buffer */ + size_t strsize) /* I - String buffer size */ + { ++ if (*buffer >= bufend) ++ return (NULL); ++ + if (length > (unsigned)(bufend - *buffer)) + length = (unsigned)(bufend - *buffer); + +@@ -1421,6 +1436,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 923a6e67a..f693e7c49 100644 +--- a/scheduler/client.c ++++ b/scheduler/client.c +@@ -564,6 +564,17 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ + + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cupsdReadClient: error=%d, used=%d, state=%s, data_encoding=HTTP_ENCODING_%s, data_remaining=" CUPS_LLFMT ", request=%p(%s), file=%d", httpError(con->http), (int)httpGetReady(con->http), httpStateString(httpGetState(con->http)), httpIsChunked(con->http) ? "CHUNKED" : "LENGTH", CUPS_LLCAST httpGetRemaining(con->http), con->request, con->request ? ippStateString(ippGetState(con->request)) : "", con->file); + ++ if (httpError(con->http) == EPIPE && !httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1) ++ { ++ /* ++ * Connection closed... ++ */ ++ ++ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF."); ++ cupsdCloseClient(con); ++ return; ++ } ++ + if (httpGetState(con->http) == HTTP_STATE_GET_SEND || + httpGetState(con->http) == HTTP_STATE_POST_SEND || + httpGetState(con->http) == HTTP_STATE_STATUS) +@@ -573,17 +584,6 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ + * connection and we need to shut it down... + */ + +- if (!httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1) +- { +- /* +- * Connection closed... +- */ +- +- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF."); +- cupsdCloseClient(con); +- return; +- } +- + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on unexpected HTTP read state %s.", httpStateString(httpGetState(con->http))); + cupsdCloseClient(con); + return; +@@ -1950,6 +1950,7 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ + strlcpy(location, httpGetField(con->http, HTTP_FIELD_LOCATION), sizeof(location)); + + httpClearFields(con->http); ++ httpClearCookie(con->http); + + httpSetField(con->http, HTTP_FIELD_LOCATION, location); + +-- +2.21.0 + diff --git a/SOURCES/cups-do-not-advertise-http-methods.patch b/SOURCES/cups-do-not-advertise-http-methods.patch new file mode 100644 index 0000000..541da15 --- /dev/null +++ b/SOURCES/cups-do-not-advertise-http-methods.patch @@ -0,0 +1,13 @@ +diff --git a/scheduler/client.c b/scheduler/client.c +index bf284e6..0382b01 100644 +--- a/scheduler/client.c ++++ b/scheduler/client.c +@@ -1011,8 +1011,6 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ + } + + httpClearFields(con->http); +- httpSetField(con->http, HTTP_FIELD_ALLOW, +- "GET, HEAD, OPTIONS, POST, PUT"); + httpSetField(con->http, HTTP_FIELD_CONTENT_LENGTH, "0"); + + if (!cupsdSendHeader(con, HTTP_STATUS_OK, NULL, CUPSD_AUTH_NONE)) diff --git a/SOURCES/cups-fips-compliance.patch b/SOURCES/cups-fips-compliance.patch new file mode 100644 index 0000000..df13e75 --- /dev/null +++ b/SOURCES/cups-fips-compliance.patch @@ -0,0 +1,371 @@ +diff --git a/cups/cups.h b/cups/cups.h +index 8f5c818..9d8c3a3 100644 +--- a/cups/cups.h ++++ b/cups/cups.h +@@ -606,6 +606,9 @@ extern ssize_t cupsHashData(const char *algorithm, const void *data, size_t dat + extern int cupsAddIntegerOption(const char *name, int value, int num_options, cups_option_t **options) _CUPS_API_2_2_4; + extern int cupsGetIntegerOption(const char *name, int num_options, cups_option_t *options) _CUPS_API_2_2_4; + ++/* New in CUPS 2.3 */ ++extern const char *cupsHashString(const unsigned char *hash, size_t hashsize, char *buffer, size_t bufsize); ++ + # ifdef __cplusplus + } + # endif /* __cplusplus */ +diff --git a/cups/hash.c b/cups/hash.c +index ede5461..8ebe20b 100644 +--- a/cups/hash.c ++++ b/cups/hash.c +@@ -21,6 +21,8 @@ + # include + #elif defined(HAVE_GNUTLS) + # include ++#else ++# include "md5-private.h" + #endif /* __APPLE__ */ + + +@@ -171,7 +173,9 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ + unsigned char temp[64]; /* Temporary hash buffer */ + size_t tempsize = 0; /* Truncate to this size? */ + +- if (!strcmp(algorithm, "sha")) ++ if (!strcmp(algorithm, "md5")) ++ alg = GNUTLS_DIG_MD5; ++ else if (!strcmp(algorithm, "sha")) + alg = GNUTLS_DIG_SHA1; + else if (!strcmp(algorithm, "sha2-224")) + alg = GNUTLS_DIG_SHA224; +@@ -219,10 +223,20 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ + + #else + /* +- * No hash support without CommonCrypto or GNU TLS... ++ * No hash support beyond MD5 without CommonCrypto or GNU TLS... + */ + +- if (hashsize < 64) ++ if (!strcmp(algorithm, "md5")) ++ { ++ _cups_md5_state_t state; /* MD5 state info */ ++ ++ _cupsMD5Init(&state); ++ _cupsMD5Append(&state, data, datalen); ++ _cupsMD5Finish(&state, hash); ++ ++ return (16); ++ } ++ else if (hashsize < 64) + goto too_small; + #endif /* __APPLE__ */ + +@@ -243,3 +257,51 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hash buffer too small."), 1); + return (-1); + } ++ ++ ++/* ++ * 'cupsHashString()' - Format a hash value as a hexadecimal string. ++ * ++ * The passed buffer must be at least 2 * hashsize + 1 characters in length. ++ */ ++ ++const char * /* O - Formatted string */ ++cupsHashString( ++ const unsigned char *hash, /* I - Hash */ ++ size_t hashsize, /* I - Size of hash */ ++ char *buffer, /* I - String buffer */ ++ size_t bufsize) /* I - Size of string buffer */ ++{ ++ char *bufptr = buffer; /* Pointer into buffer */ ++ static const char *hex = "0123456789abcdef"; ++ /* Hex characters (lowercase!) */ ++ ++ ++ /* ++ * Range check input... ++ */ ++ ++ if (!hash || hashsize < 1 || !buffer || bufsize < (2 * hashsize + 1)) ++ { ++ if (buffer) ++ *buffer = '\0'; ++ return (NULL); ++ } ++ ++ /* ++ * Loop until we've converted the whole hash... ++ */ ++ ++ while (hashsize > 0) ++ { ++ *bufptr++ = hex[*hash >> 4]; ++ *bufptr++ = hex[*hash & 15]; ++ ++ hash ++; ++ hashsize --; ++ } ++ ++ *bufptr = '\0'; ++ ++ return (buffer); ++} +diff --git a/cups/md5passwd.c b/cups/md5passwd.c +index a9817aa..c9ffe04 100644 +--- a/cups/md5passwd.c ++++ b/cups/md5passwd.c +@@ -17,6 +17,7 @@ + * Include necessary headers... + */ + ++#include + #include "http-private.h" + #include "string-private.h" + +@@ -31,7 +32,6 @@ httpMD5(const char *username, /* I - User name */ + const char *passwd, /* I - Password string */ + char md5[33]) /* O - MD5 string */ + { +- _cups_md5_state_t state; /* MD5 state info */ + unsigned char sum[16]; /* Sum data */ + char line[256]; /* Line to sum */ + +@@ -41,15 +41,13 @@ httpMD5(const char *username, /* I - User name */ + */ + + snprintf(line, sizeof(line), "%s:%s:%s", username, realm, passwd); +- _cupsMD5Init(&state); +- _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); +- _cupsMD5Finish(&state, sum); ++ cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); + + /* + * Return the sum... + */ + +- return (httpMD5String(sum, md5)); ++ return ((char *)cupsHashString(sum, sizeof(sum), md5, 33)); + } + + +@@ -65,7 +63,6 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ + const char *resource, /* I - Resource path */ + char md5[33]) /* IO - MD5 sum */ + { +- _cups_md5_state_t state; /* MD5 state info */ + unsigned char sum[16]; /* Sum data */ + char line[1024]; /* Line of data */ + char a2[33]; /* Hash of method and resource */ +@@ -76,9 +73,7 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ + */ + + snprintf(line, sizeof(line), "%s:%s", method, resource); +- _cupsMD5Init(&state); +- _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); +- _cupsMD5Finish(&state, sum); ++ cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); + httpMD5String(sum, a2); + + /* +@@ -88,12 +83,9 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ + */ + + snprintf(line, sizeof(line), "%s:%s:%s", md5, nonce, a2); ++ cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); + +- _cupsMD5Init(&state); +- _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); +- _cupsMD5Finish(&state, sum); +- +- return (httpMD5String(sum, md5)); ++ return ((char *)cupsHashString(sum, sizeof(sum), md5, 33)); + } + + +@@ -106,23 +98,5 @@ httpMD5String(const unsigned char *sum, /* I - MD5 sum data */ + char md5[33]) + /* O - MD5 sum in hex */ + { +- int i; /* Looping var */ +- char *md5ptr; /* Pointer into MD5 string */ +- static const char hex[] = "0123456789abcdef"; +- /* Hex digits */ +- +- +- /* +- * Convert the MD5 sum to hexadecimal... +- */ +- +- for (i = 16, md5ptr = md5; i > 0; i --, sum ++) +- { +- *md5ptr++ = hex[*sum >> 4]; +- *md5ptr++ = hex[*sum & 15]; +- } +- +- *md5ptr = '\0'; +- +- return (md5); ++ return ((char *)cupsHashString(sum, 16, md5, 33)); + } +diff --git a/scheduler/auth.c b/scheduler/auth.c +index 71df9dc..e7d0006 100644 +--- a/scheduler/auth.c ++++ b/scheduler/auth.c +@@ -72,9 +72,6 @@ static int check_authref(cupsd_client_t *con, const char *right); + static int compare_locations(cupsd_location_t *a, + cupsd_location_t *b); + static cupsd_authmask_t *copy_authmask(cupsd_authmask_t *am, void *data); +-#if !HAVE_LIBPAM +-static char *cups_crypt(const char *pw, const char *salt); +-#endif /* !HAVE_LIBPAM */ + static void free_authmask(cupsd_authmask_t *am, void *data); + #if HAVE_LIBPAM + static int pam_func(int, const struct pam_message **, +@@ -695,14 +692,14 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ + * client... + */ + +- pass = cups_crypt(password, pw->pw_passwd); ++ pass = crypt(password, pw->pw_passwd); + + if (!pass || strcmp(pw->pw_passwd, pass)) + { + # ifdef HAVE_SHADOW_H + if (spw) + { +- pass = cups_crypt(password, spw->sp_pwdp); ++ pass = crypt(password, spw->sp_pwdp); + + if (pass == NULL || strcmp(spw->sp_pwdp, pass)) + { +@@ -1988,129 +1985,6 @@ copy_authmask(cupsd_authmask_t *mask, /* I - Existing auth mask */ + } + + +-#if !HAVE_LIBPAM +-/* +- * 'cups_crypt()' - Encrypt the password using the DES or MD5 algorithms, +- * as needed. +- */ +- +-static char * /* O - Encrypted password */ +-cups_crypt(const char *pw, /* I - Password string */ +- const char *salt) /* I - Salt (key) string */ +-{ +- if (!strncmp(salt, "$1$", 3)) +- { +- /* +- * Use MD5 passwords without the benefit of PAM; this is for +- * Slackware Linux, and the algorithm was taken from the +- * old shadow-19990827/lib/md5crypt.c source code... :( +- */ +- +- int i; /* Looping var */ +- unsigned long n; /* Output number */ +- int pwlen; /* Length of password string */ +- const char *salt_end; /* End of "salt" data for MD5 */ +- char *ptr; /* Pointer into result string */ +- _cups_md5_state_t state; /* Primary MD5 state info */ +- _cups_md5_state_t state2; /* Secondary MD5 state info */ +- unsigned char digest[16]; /* MD5 digest result */ +- static char result[120]; /* Final password string */ +- +- +- /* +- * Get the salt data between dollar signs, e.g. $1$saltdata$md5. +- * Get a maximum of 8 characters of salt data after $1$... +- */ +- +- for (salt_end = salt + 3; *salt_end && (salt_end - salt) < 11; salt_end ++) +- if (*salt_end == '$') +- break; +- +- /* +- * Compute the MD5 sum we need... +- */ +- +- pwlen = strlen(pw); +- +- _cupsMD5Init(&state); +- _cupsMD5Append(&state, (unsigned char *)pw, pwlen); +- _cupsMD5Append(&state, (unsigned char *)salt, salt_end - salt); +- +- _cupsMD5Init(&state2); +- _cupsMD5Append(&state2, (unsigned char *)pw, pwlen); +- _cupsMD5Append(&state2, (unsigned char *)salt + 3, salt_end - salt - 3); +- _cupsMD5Append(&state2, (unsigned char *)pw, pwlen); +- _cupsMD5Finish(&state2, digest); +- +- for (i = pwlen; i > 0; i -= 16) +- _cupsMD5Append(&state, digest, i > 16 ? 16 : i); +- +- for (i = pwlen; i > 0; i >>= 1) +- _cupsMD5Append(&state, (unsigned char *)((i & 1) ? "" : pw), 1); +- +- _cupsMD5Finish(&state, digest); +- +- for (i = 0; i < 1000; i ++) +- { +- _cupsMD5Init(&state); +- +- if (i & 1) +- _cupsMD5Append(&state, (unsigned char *)pw, pwlen); +- else +- _cupsMD5Append(&state, digest, 16); +- +- if (i % 3) +- _cupsMD5Append(&state, (unsigned char *)salt + 3, salt_end - salt - 3); +- +- if (i % 7) +- _cupsMD5Append(&state, (unsigned char *)pw, pwlen); +- +- if (i & 1) +- _cupsMD5Append(&state, digest, 16); +- else +- _cupsMD5Append(&state, (unsigned char *)pw, pwlen); +- +- _cupsMD5Finish(&state, digest); +- } +- +- /* +- * Copy the final sum to the result string and return... +- */ +- +- memcpy(result, salt, (size_t)(salt_end - salt)); +- ptr = result + (salt_end - salt); +- *ptr++ = '$'; +- +- for (i = 0; i < 5; i ++, ptr += 4) +- { +- n = ((((unsigned)digest[i] << 8) | (unsigned)digest[i + 6]) << 8); +- +- if (i < 4) +- n |= (unsigned)digest[i + 12]; +- else +- n |= (unsigned)digest[5]; +- +- to64(ptr, n, 4); +- } +- +- to64(ptr, (unsigned)digest[11], 2); +- ptr += 2; +- *ptr = '\0'; +- +- return (result); +- } +- else +- { +- /* +- * Use the standard crypt() function... +- */ +- +- return (crypt(pw, salt)); +- } +-} +-#endif /* !HAVE_LIBPAM */ +- +- + /* + * 'free_authmask()' - Free function for auth masks. + */ diff --git a/SPECS/cups.spec b/SPECS/cups.spec index 1c3e7c8..bb99862 100644 --- a/SPECS/cups.spec +++ b/SPECS/cups.spec @@ -15,7 +15,7 @@ Summary: CUPS printing system Name: cups Epoch: 1 Version: 2.2.6 -Release: 27%{?dist} +Release: 30%{?dist} License: GPLv2+ and LGPLv2 with exceptions and AML Url: http://www.cups.org/ Source0: https://github.com/apple/cups/releases/download/v%{VERSION}/cups-%{VERSION}-source.tar.gz @@ -80,6 +80,13 @@ Patch46: 0001-CVE-2018-4700-Linux-session-cookies-used-a-predictab.patch Patch47: 0001-The-scheduler-could-crash-while-adding-an-IPP-Everyw.patch # 1677577 - Remove 'View X log' buttons from web ui Patch48: 0001-Remove-web-log-buttons.patch +# 1650233 - cups uses md5 for hashing credentials sent through tls connection +Patch49: cups-fips-compliance.patch +# 1700663 - Stop advertising the HTTP methods that are supported +Patch50: cups-do-not-advertise-http-methods.patch +# 1774462, 1774463 - CVE-2019-8696, CVE-2019-8675 - buffer overflow in SNMP and IPP, +# memory disclosure and DoS in scheduler +Patch51: 0001-Multiple-security-disclosure-issues.patch Patch100: cups-lspp.patch @@ -303,6 +310,13 @@ Sends IPP requests to the specified URI and tests and/or displays the results. %patch47 -p1 -b .ippeve-crash # 1677577 - Remove 'View X log' buttons from web ui %patch48 -p1 -b .rm-webui-buttons +# 1650233 - cups uses md5 for hashing credentials sent through tls connection +%patch49 -p1 -b .fips-compliance +# 1700663 - Stop advertising the HTTP methods that are supported +%patch50 -p1 -b .do-not-advertise-http-methods +# 1774462, 1774463 - CVE-2019-8696, CVE-2019-8675 - buffer overflow in SNMP and IPP, +# memory disclosure and DoS in scheduler +%patch51 -p1 -b .cve-in-scheduler sed -i -e '1iMaxLogSize 0' conf/cupsd.conf.in @@ -706,6 +720,16 @@ rm -f %{cups_serverbin}/backend/smb %{_mandir}/man5/ipptoolfile.5.gz %changelog +* Tue Nov 26 2019 Zdenek Dohnal - 1:2.2.6-30 +- 1774462 - CVE-2019-8675 - buffer overflow in SNMP and IPP, memory disclosure and DoS in scheduler +- 1774463 - CVE-2019-8696 + +* Mon Oct 07 2019 Zdenek Dohnal - 1:2.2.6-29 +- 1700663 - Stop advertising the HTTP methods that are supported + +* Tue Aug 13 2019 Zdenek Dohnal - 1:2.2.6-28 +- 1650233 - cups uses md5 for hashing credentials sent through tls connection + * Mon Jun 10 2019 Tomas Korbar - 1:2.2.6-27 - 1677577 - Remove 'View X log' buttons from web ui