Package: cups Version: 1.4.1-5 Severity: grave Tags: security patch Hi Martin
The recent DSA (DSA-1933-1) fixed a few cross-site scripting issues. Please include the patch in the unstable/testing distribution. Cheers Steffen
diff -u cupsys-1.2.2/debian/changelog cupsys-1.2.2/debian/changelog --- cupsys-1.2.2/debian/changelog +++ cupsys-1.2.2/debian/changelog @@ -1,3 +1,15 @@ +cupsys (1.2.2-0ubuntu0.6.06.15) dapper-security; urgency=low + + * SECURITY UPDATE: XSS and CRLF injection in headers + - debian/patches/83_CVE-2009-2820.dpatch: Introduce cgiClearVariables() + in cgi-bin/{var.c,cgi.h}. Clear out variables in + cgi-bin/{classes,help,ipp-var,jobs,printers}.c. Encode URL string and + clear out variables in cgi-bin/admin.c. Filter more characters in + cgi-bin/template.c. + - CVE-2009-2820 + + -- Marc Deslauriers <marc.deslauri...@ubuntu.com> Fri, 30 Oct 2009 21:40:07 -0400 + cupsys (1.2.2-0ubuntu0.6.06.14) dapper-security; urgency=low * SECURITY UPDATE: Remote denial-of-service via IPP_TAG_UNSUPPORTED tags. diff -u cupsys-1.2.2/debian/patches/00list cupsys-1.2.2/debian/patches/00list --- cupsys-1.2.2/debian/patches/00list +++ cupsys-1.2.2/debian/patches/00list @@ -39,0 +40 @@ +83_CVE-2009-2820 only in patch2: unchanged: --- cupsys-1.2.2.orig/debian/patches/83_CVE-2009-2820.dpatch +++ cupsys-1.2.2/debian/patches/83_CVE-2009-2820.dpatch @@ -0,0 +1,409 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 83_CVE-2009-2820.dpatch by Marc Deslauriers <marc.deslauri...@ubuntu.com> +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: Description: fix XSS and CRLF injection in headers +## DP: Patch: backported from Aaron Sigel's patch + +...@dpatch@ +diff -urNad cupsys-1.2.2~/cgi-bin/admin.c cupsys-1.2.2/cgi-bin/admin.c +--- cupsys-1.2.2~/cgi-bin/admin.c 2006-05-22 14:47:09.000000000 -0400 ++++ cupsys-1.2.2/cgi-bin/admin.c 2009-10-30 21:39:59.000000000 -0400 +@@ -107,6 +107,7 @@ + */ + + cgiSetVariable("SECTION", "admin"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * See if we have form data... +@@ -137,16 +138,61 @@ + + + if (getenv("HTTPS")) +- snprintf(prefix, sizeof(prefix), "https://%s:%s", +- getenv("SERVER_NAME"), getenv("SERVER_PORT")); ++ snprintf(prefix, sizeof(prefix), "https://%s:%s", ++ getenv("SERVER_NAME"), getenv("SERVER_PORT")); + else +- snprintf(prefix, sizeof(prefix), "http://%s:%s", +- getenv("SERVER_NAME"), getenv("SERVER_PORT")); ++ snprintf(prefix, sizeof(prefix), "http://%s:%s", ++ getenv("SERVER_NAME"), getenv("SERVER_PORT")); ++ ++ fprintf(stderr, "DEBUG: redirecting with prefix %s!\n", prefix); + + if ((url = cgiGetVariable("URL")) != NULL) +- printf("Location: %s%s\n\n", prefix, url); ++ { ++ char encoded[1024], /* Encoded URL string */ ++ *ptr; /* Pointer into encoded string */ ++ ++ ++ ptr = encoded; ++ if (*url != '/') ++ *ptr++ = '/'; ++ ++ for (; *url && ptr < (encoded + sizeof(encoded) - 4); url ++) ++ { ++ if (strchr("%@&+ <>#=", *url) || *url < ' ' || *url & 128) ++ { ++ /* ++ * Percent-encode this character; safe because we have at least 4 ++ * bytes left in the array... ++ */ ++ ++ sprintf(ptr, "%%%02X", *url & 255); ++ ptr += 3; ++ } ++ else ++ *ptr++ = *url; ++ } ++ ++ *ptr = '\0'; ++ ++ if (*url) ++ { ++ /* ++ * URL was too long, just redirect to the admin page... ++ */ ++ ++ printf("Location: %s/admin\n\n", prefix); ++ } ++ else ++ { ++ /* ++ * URL is OK, redirect there... ++ */ ++ ++ printf("Location: %s%s\n\n", prefix, encoded); ++ } ++ } + else +- printf("Location: %s/admin\n\n", prefix); ++ printf("Location: %s/admin\n\n", prefix); + } + else if (!strcmp(op, "start-printer")) + do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Printer"))); +@@ -238,6 +284,7 @@ + ipp_attribute_t *attr; /* member-uris attribute */ + char uri[HTTP_MAX_URI]; /* Device or printer URI */ + const char *name, /* Pointer to class name */ ++ *op, /* Operation name */ + *ptr; /* Pointer to CGI variable */ + const char *title; /* Title of page */ + static const char * const pattrs[] = /* Requested printer attributes */ +@@ -249,6 +296,7 @@ + + + title = cgiText(modify ? _("Modify Class") : _("Add Class")); ++ op = cgiGetVariable("OP"); + name = cgiGetVariable("PRINTER_NAME"); + + if (cgiGetVariable("PRINTER_LOCATION") == NULL) +@@ -271,6 +319,12 @@ + * Do the request and get back a response... + */ + ++ cgiClearVariables(); ++ if (op) ++ cgiSetVariable("OP", op); ++ if (name) ++ cgiSetVariable("PRINTER_NAME", name); ++ + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + /* +diff -urNad cupsys-1.2.2~/cgi-bin/cgi.h cupsys-1.2.2/cgi-bin/cgi.h +--- cupsys-1.2.2~/cgi-bin/cgi.h 2006-01-14 15:37:40.000000000 -0500 ++++ cupsys-1.2.2/cgi-bin/cgi.h 2009-10-30 21:39:46.000000000 -0400 +@@ -63,6 +63,7 @@ + extern void cgiAbort(const char *title, const char *stylesheet, + const char *format, ...); + extern int cgiCheckVariables(const char *names); ++extern void cgiClearVariables(void); + extern void *cgiCompileSearch(const char *query); + extern void cgiCopyTemplateFile(FILE *out, const char *tmpl); + extern void cgiCopyTemplateLang(const char *tmpl); +diff -urNad cupsys-1.2.2~/cgi-bin/classes.c cupsys-1.2.2/cgi-bin/classes.c +--- cupsys-1.2.2~/cgi-bin/classes.c 2006-05-22 14:47:09.000000000 -0400 ++++ cupsys-1.2.2/cgi-bin/classes.c 2009-10-30 21:39:46.000000000 -0400 +@@ -78,6 +78,7 @@ + */ + + cgiSetVariable("SECTION", "classes"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * See if we are displaying a printer or all classes... +diff -urNad cupsys-1.2.2~/cgi-bin/help.c cupsys-1.2.2/cgi-bin/help.c +--- cupsys-1.2.2~/cgi-bin/help.c 2006-05-19 15:39:28.000000000 -0400 ++++ cupsys-1.2.2/cgi-bin/help.c 2009-10-30 21:39:46.000000000 -0400 +@@ -72,6 +72,7 @@ + */ + + cgiSetVariable("SECTION", "help"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * Load the help index... +@@ -111,7 +112,7 @@ + */ + + for (i = 0; i < argc; i ++) +- fprintf(stderr, "argv[%d]=\"%s\"\n", i, argv[i]); ++ fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); + + if ((helpfile = getenv("PATH_INFO")) != NULL) + { +@@ -187,6 +188,12 @@ + topic = cgiGetVariable("TOPIC"); + si = helpSearchIndex(hi, query, topic, helpfile); + ++ cgiClearVariables(); ++ if (query) ++ cgiSetVariable("QUERY", query); ++ if (topic) ++ cgiSetVariable("TOPIC", topic); ++ + fprintf(stderr, "DEBUG: query=\"%s\", topic=\"%s\"\n", + query ? query : "(null)", topic ? topic : "(null)"); + +diff -urNad cupsys-1.2.2~/cgi-bin/ipp-var.c cupsys-1.2.2/cgi-bin/ipp-var.c +--- cupsys-1.2.2~/cgi-bin/ipp-var.c 2006-05-22 14:47:09.000000000 -0400 ++++ cupsys-1.2.2/cgi-bin/ipp-var.c 2009-10-30 21:39:46.000000000 -0400 +@@ -1075,7 +1075,9 @@ + int ascending, /* Order of jobs (0 = descending) */ + first, /* First job to show */ + count; /* Number of jobs */ +- const char *var; /* Form variable */ ++ const char *var, /* Form variable */ ++ *query, /* Query string */ ++ *section; /* Section in web interface */ + void *search; /* Search data */ + char url[1024], /* URL for prev/next/this */ + *urlptr, /* Position in URL */ +@@ -1120,10 +1122,13 @@ + * Get a list of matching job objects. + */ + +- if ((var = cgiGetVariable("QUERY")) != NULL) +- search = cgiCompileSearch(var); ++ if ((query = cgiGetVariable("QUERY")) != NULL) ++ search = cgiCompileSearch(query); + else ++ { ++ query = NULL; + search = NULL; ++ } + + jobs = cgiGetIPPObjects(response, search); + count = cupsArrayCount(jobs); +@@ -1148,16 +1153,27 @@ + if (first < 0) + first = 0; + +- sprintf(url, "%d", count); +- cgiSetVariable("TOTAL", url); +- + if ((var = cgiGetVariable("ORDER")) != NULL) + ascending = !strcasecmp(var, "asc"); + else +- { + ascending = !which_jobs || !strcasecmp(which_jobs, "not-completed"); +- cgiSetVariable("ORDER", ascending ? "asc" : "dec"); +- } ++ ++ section = cgiGetVariable("SECTION"); ++ ++ cgiClearVariables(); ++ ++ if (query) ++ cgiSetVariable("QUERY", query); ++ ++ cgiSetVariable("ORDER", ascending ? "asc" : "dec"); ++ ++ cgiSetVariable("SECTION", section); ++ ++ sprintf(url, "%d", count); ++ cgiSetVariable("TOTAL", url); ++ ++ if (which_jobs) ++ cgiSetVariable("WHICH_JOBS", which_jobs); + + if (ascending) + { +@@ -1180,11 +1196,10 @@ + + urlend = url + sizeof(url); + +- if ((var = cgiGetVariable("QUERY")) != NULL) ++ if (query != NULL) + { + if (dest) +- snprintf(url, sizeof(url), "/%s/%s?QUERY=", cgiGetVariable("SECTION"), +- dest); ++ snprintf(url, sizeof(url), "/%s/%s?QUERY=", section, dest); + else + strlcpy(url, "/jobs/?QUERY=", sizeof(url)); + +@@ -1199,7 +1214,7 @@ + else + { + if (dest) +- snprintf(url, sizeof(url), "/%s/%s?", cgiGetVariable("SECTION"), dest); ++ snprintf(url, sizeof(url), "/%s/%s?", section, dest); + else + strlcpy(url, "/jobs/?", sizeof(url)); + +diff -urNad cupsys-1.2.2~/cgi-bin/jobs.c cupsys-1.2.2/cgi-bin/jobs.c +--- cupsys-1.2.2~/cgi-bin/jobs.c 2006-02-14 22:21:04.000000000 -0500 ++++ cupsys-1.2.2/cgi-bin/jobs.c 2009-10-30 21:39:46.000000000 -0400 +@@ -66,6 +66,7 @@ + */ + + cgiSetVariable("SECTION", "jobs"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * Connect to the HTTP server... +diff -urNad cupsys-1.2.2~/cgi-bin/printers.c cupsys-1.2.2/cgi-bin/printers.c +--- cupsys-1.2.2~/cgi-bin/printers.c 2006-05-22 14:47:09.000000000 -0400 ++++ cupsys-1.2.2/cgi-bin/printers.c 2009-10-30 21:39:46.000000000 -0400 +@@ -81,6 +81,7 @@ + */ + + cgiSetVariable("SECTION", "printers"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * See if we are displaying a printer or all printers... +diff -urNad cupsys-1.2.2~/cgi-bin/template.c cupsys-1.2.2/cgi-bin/template.c +--- cupsys-1.2.2~/cgi-bin/template.c 2006-05-19 15:39:28.000000000 -0400 ++++ cupsys-1.2.2/cgi-bin/template.c 2009-10-30 21:39:46.000000000 -0400 +@@ -639,6 +639,8 @@ + fputs(">", out); + else if (*s == '\"') + fputs(""", out); ++ else if (*s == '\'') ++ fputs("'", out); + else if (*s == '&') + fputs("&", out); + else +@@ -659,7 +661,7 @@ + { + while (*s) + { +- if (strchr("%&+ <>#=", *s) || *s & 128) ++ if (strchr("%@&+ <>#=", *s) || *s < ' ' || *s & 128) + fprintf(out, "%%%02X", *s & 255); + else + putc(*s, out); +diff -urNad cupsys-1.2.2~/cgi-bin/var.c cupsys-1.2.2/cgi-bin/var.c +--- cupsys-1.2.2~/cgi-bin/var.c 2006-05-19 15:39:28.000000000 -0400 ++++ cupsys-1.2.2/cgi-bin/var.c 2009-10-30 21:39:46.000000000 -0400 +@@ -24,6 +24,7 @@ + * Contents: + * + * cgiCheckVariables() - Check for the presence of "required" variables. ++ * cgiClearVariables() - Clear all form variables. + * cgiGetArray() - Get an element from a form array... + * cgiGetFile() - Get the file (if any) that was submitted in the form. + * cgiGetSize() - Get the size of a form array value. +@@ -144,6 +145,31 @@ + + + /* ++ * 'cgiClearVariables()' - Clear all form variables. ++ */ ++ ++void ++cgiClearVariables(void) ++{ ++ int i, j; /* Looping vars */ ++ _cgi_var_t *v; /* Current variable */ ++ ++ ++ for (v = form_vars, i = form_count; i > 0; v ++, i --) ++ { ++ _cupsStrFree(v->name); ++ for (j = 0; j < v->nvalues; j ++) ++ if (v->values[j]) ++ _cupsStrFree(v->values[j]); ++ } ++ ++ form_count = 0; ++ ++ cgi_unlink_file(); ++} ++ ++ ++/* + * 'cgiGetArray()' - Get an element from a form array... + */ + +@@ -163,7 +189,7 @@ + if (element < 0 || element >= var->nvalues) + return (NULL); + +- return (var->values[element]); ++ return (_cupsStrAlloc(var->values[element])); + } + + +@@ -218,7 +244,7 @@ + var->values[var->nvalues - 1]); + #endif /* DEBUG */ + +- return ((var == NULL) ? NULL : var->values[var->nvalues - 1]); ++ return ((var == NULL) ? NULL : _cupsStrAlloc(var->values[var->nvalues - 1])); + } + + +@@ -344,9 +370,9 @@ + var->nvalues = element + 1; + } + else if (var->values[element]) +- free((char *)var->values[element]); ++ _cupsStrFree((char *)var->values[element]); + +- var->values[element] = strdup(value); ++ var->values[element] = _cupsStrAlloc(value); + } + } + +@@ -385,7 +411,7 @@ + { + for (i = size; i < var->nvalues; i ++) + if (var->values[i]) +- free((void *)(var->values[i])); ++ _cupsStrFree((void *)(var->values[i])); + } + + var->nvalues = size; +@@ -418,9 +444,9 @@ + { + for (i = 0; i < var->nvalues; i ++) + if (var->values[i]) +- free((char *)var->values[i]); ++ _cupsStrFree((char *)var->values[i]); + +- var->values[0] = strdup(value); ++ var->values[0] = _cupsStrAlloc(value); + var->nvalues = 1; + } + } +@@ -456,11 +482,11 @@ + } + + var = form_vars + form_count; +- var->name = strdup(name); ++ var->name = _cupsStrAlloc(name); + var->nvalues = element + 1; + var->avalues = element + 1; + var->values = calloc(element + 1, sizeof(char *)); +- var->values[element] = strdup(value); ++ var->values[element] = _cupsStrAlloc(value); + + form_count ++; + }