diff -up cups-1.3.7/cgi-bin/admin.c.CVE-2009-2820 cups-1.3.7/cgi-bin/admin.c --- cups-1.3.7/cgi-bin/admin.c.CVE-2009-2820 2009-11-11 16:21:42.498768682 +0000 +++ cups-1.3.7/cgi-bin/admin.c 2009-11-11 16:36:49.970893773 +0000 @@ -104,6 +104,7 @@ main(int argc, /* I - Number of comm */ cgiSetVariable("SECTION", "admin"); + cgiSetVariable("REFRESH_PAGE", ""); /* * See if we have form data... @@ -134,16 +135,61 @@ main(int argc, /* I - Number of comm 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"))); @@ -293,6 +339,31 @@ do_add_rss_subscription(http_t *http) /* * and classes and (re)show the add page... */ + if (cgiGetVariable("EVENT_JOB_CREATED")) + cgiSetVariable("EVENT_JOB_CREATED", "CHECKED"); + if (cgiGetVariable("EVENT_JOB_COMPLETED")) + cgiSetVariable("EVENT_JOB_COMPLETED", "CHECKED"); + if (cgiGetVariable("EVENT_JOB_STOPPED")) + cgiSetVariable("EVENT_JOB_STOPPED", "CHECKED"); + if (cgiGetVariable("EVENT_JOB_CONFIG_CHANGED")) + cgiSetVariable("EVENT_JOB_CONFIG_CHANGED", "CHECKED"); + if (cgiGetVariable("EVENT_PRINTER_STOPPED")) + cgiSetVariable("EVENT_PRINTER_STOPPED", "CHECKED"); + if (cgiGetVariable("EVENT_PRINTER_ADDED")) + cgiSetVariable("EVENT_PRINTER_ADDED", "CHECKED"); + if (cgiGetVariable("EVENT_PRINTER_MODIFIED")) + cgiSetVariable("EVENT_PRINTER_MODIFIED", "CHECKED"); + if (cgiGetVariable("EVENT_PRINTER_DELETED")) + cgiSetVariable("EVENT_PRINTER_DELETED", "CHECKED"); + if (cgiGetVariable("EVENT_SERVER_STARTED")) + cgiSetVariable("EVENT_SERVER_STARTED", "CHECKED"); + if (cgiGetVariable("EVENT_SERVER_STOPPED")) + cgiSetVariable("EVENT_SERVER_STOPPED", "CHECKED"); + if (cgiGetVariable("EVENT_SERVER_RESTARTED")) + cgiSetVariable("EVENT_SERVER_RESTARTED", "CHECKED"); + if (cgiGetVariable("EVENT_SERVER_AUDIT")) + cgiSetVariable("EVENT_SERVER_AUDIT", "CHECKED"); + request = ippNewRequest(CUPS_GET_PRINTERS); response = cupsDoRequest(http, request, "/"); @@ -415,6 +486,7 @@ do_am_class(http_t *http, /* I - HTTP c 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 */ @@ -426,6 +498,7 @@ do_am_class(http_t *http, /* I - HTTP c title = cgiText(modify ? _("Modify Class") : _("Add Class")); + op = cgiGetVariable("OP"); name = cgiGetVariable("PRINTER_NAME"); if (cgiGetVariable("PRINTER_LOCATION") == NULL) @@ -444,6 +517,12 @@ do_am_class(http_t *http, /* I - HTTP c * 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) { /* @@ -2330,7 +2409,9 @@ do_menu(http_t *http) /* I - HTTP conn if ((val = cupsGetOption("DefaultAuthType", num_settings, settings)) != NULL && !strcasecmp(val, "Negotiate")) cgiSetVariable("KERBEROS", "CHECKED"); + else #endif /* HAVE_GSSAPI */ + cgiSetVariable("KERBEROS", ""); cupsFreeOptions(num_settings, settings); diff -up cups-1.3.7/cgi-bin/cgi.h.CVE-2009-2820 cups-1.3.7/cgi-bin/cgi.h --- cups-1.3.7/cgi-bin/cgi.h.CVE-2009-2820 2007-07-11 22:46:42.000000000 +0100 +++ cups-1.3.7/cgi-bin/cgi.h 2009-11-11 16:36:49.971894403 +0000 @@ -54,6 +54,7 @@ typedef struct cgi_file_s /**** Uploade 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 -up cups-1.3.7/cgi-bin/classes.c.CVE-2009-2820 cups-1.3.7/cgi-bin/classes.c --- cups-1.3.7/cgi-bin/classes.c.CVE-2009-2820 2007-07-11 22:46:42.000000000 +0100 +++ cups-1.3.7/cgi-bin/classes.c 2009-11-11 16:36:49.972893850 +0000 @@ -69,6 +69,7 @@ main(int argc, /* I - Number of comm */ cgiSetVariable("SECTION", "classes"); + cgiSetVariable("REFRESH_PAGE", ""); /* * See if we are displaying a printer or all classes... diff -up cups-1.3.7/cgi-bin/help.c.CVE-2009-2820 cups-1.3.7/cgi-bin/help.c --- cups-1.3.7/cgi-bin/help.c.CVE-2009-2820 2007-08-22 23:26:39.000000000 +0100 +++ cups-1.3.7/cgi-bin/help.c 2009-11-11 16:36:49.972893850 +0000 @@ -63,6 +63,7 @@ main(int argc, /* I - Number of comm */ cgiSetVariable("SECTION", "help"); + cgiSetVariable("REFRESH_PAGE", ""); /* * Load the help index... @@ -102,7 +103,7 @@ main(int argc, /* I - Number of comm */ 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) { @@ -179,6 +180,12 @@ main(int argc, /* I - Number of comm 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 -up cups-1.3.7/cgi-bin/ipp-var.c.CVE-2009-2820 cups-1.3.7/cgi-bin/ipp-var.c --- cups-1.3.7/cgi-bin/ipp-var.c.CVE-2009-2820 2009-11-11 16:21:42.537769703 +0000 +++ cups-1.3.7/cgi-bin/ipp-var.c 2009-11-11 16:36:49.973894134 +0000 @@ -1214,7 +1214,9 @@ cgiShowJobs(http_t *http, /* I - Co 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 */ @@ -1259,10 +1261,13 @@ cgiShowJobs(http_t *http, /* I - Co * 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); @@ -1287,16 +1292,27 @@ cgiShowJobs(http_t *http, /* I - Co 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) { @@ -1319,11 +1335,10 @@ cgiShowJobs(http_t *http, /* I - Co 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)); @@ -1338,7 +1353,7 @@ cgiShowJobs(http_t *http, /* I - Co 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 -up cups-1.3.7/cgi-bin/jobs.c.CVE-2009-2820 cups-1.3.7/cgi-bin/jobs.c --- cups-1.3.7/cgi-bin/jobs.c.CVE-2009-2820 2008-01-22 01:41:31.000000000 +0000 +++ cups-1.3.7/cgi-bin/jobs.c 2009-11-11 16:36:49.974894113 +0000 @@ -57,6 +57,7 @@ main(int argc, /* I - Number of comm */ cgiSetVariable("SECTION", "jobs"); + cgiSetVariable("REFRESH_PAGE", ""); /* * Connect to the HTTP server... diff -up cups-1.3.7/cgi-bin/printers.c.CVE-2009-2820 cups-1.3.7/cgi-bin/printers.c --- cups-1.3.7/cgi-bin/printers.c.CVE-2009-2820 2008-01-22 01:41:31.000000000 +0000 +++ cups-1.3.7/cgi-bin/printers.c 2009-11-11 16:36:49.985894593 +0000 @@ -72,6 +72,7 @@ main(int argc, /* I - Number of comm */ cgiSetVariable("SECTION", "printers"); + cgiSetVariable("REFRESH_PAGE", ""); /* * See if we are displaying a printer or all printers... diff -up cups-1.3.7/cgi-bin/template.c.CVE-2009-2820 cups-1.3.7/cgi-bin/template.c --- cups-1.3.7/cgi-bin/template.c.CVE-2009-2820 2008-01-14 22:12:58.000000000 +0000 +++ cups-1.3.7/cgi-bin/template.c 2009-11-11 16:36:49.987893498 +0000 @@ -639,6 +639,8 @@ cgi_puts(const char *s, /* I - String fputs(">", out); else if (*s == '\"') fputs(""", out); + else if (*s == '\'') + fputs("'", out); else if (*s == '&') fputs("&", out); else @@ -659,7 +661,7 @@ cgi_puturi(const char *s, /* I - String { while (*s) { - if (strchr("%&+ <>#=", *s) || *s & 128) + if (strchr("%@&+ <>#=", *s) || *s < ' ' || *s & 128) fprintf(out, "%%%02X", *s & 255); else putc(*s, out); diff -up cups-1.3.7/cgi-bin/var.c.CVE-2009-2820 cups-1.3.7/cgi-bin/var.c --- cups-1.3.7/cgi-bin/var.c.CVE-2009-2820 2008-01-16 22:20:33.000000000 +0000 +++ cups-1.3.7/cgi-bin/var.c 2009-11-11 16:36:49.988894464 +0000 @@ -15,6 +15,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. @@ -135,6 +136,31 @@ cgiCheckVariables(const char *names) /* /* + * '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... */ @@ -154,7 +180,7 @@ cgiGetArray(const char *name, /* I - Na if (element < 0 || element >= var->nvalues) return (NULL); - return (var->values[element]); + return (_cupsStrAlloc(var->values[element])); } @@ -209,7 +235,7 @@ cgiGetVariable(const char *name) /* I - 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])); } @@ -341,9 +367,9 @@ cgiSetArray(const char *name, /* I - Na 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); } } @@ -388,7 +414,7 @@ cgiSetSize(const char *name, /* I - Nam { for (i = size; i < var->nvalues; i ++) if (var->values[i]) - free((void *)(var->values[i])); + _cupsStrFree((void *)(var->values[i])); } var->nvalues = size; @@ -421,9 +447,9 @@ cgiSetVariable(const char *name, /* I - { 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; } } @@ -470,10 +496,10 @@ cgi_add_variable(const char *name, /* I if ((var->values = calloc(element + 1, sizeof(char *))) == NULL) return; - var->name = strdup(name); + var->name = _cupsStrAlloc(name); var->nvalues = element + 1; var->avalues = element + 1; - var->values[element] = strdup(value); + var->values[element] = _cupsStrAlloc(value); form_count ++; }