Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Alexander_Naumov:SLE12
cups154
cups-1.5.4-CVE-2012-5519.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File cups-1.5.4-CVE-2012-5519.patch of Package cups154
--- doc/help/ref-cupsd-conf.html.in.orig 2012-01-30 22:40:21.000000000 +0100 +++ doc/help/ref-cupsd-conf.html.in 2014-02-05 14:13:23.000000000 +0100 @@ -917,6 +917,28 @@ ConfigFilePerm 0640 </BLOCKQUOTE> +<H2 CLASS="title"><A NAME="ConfigurationChangeRestriction">ConfigurationChangeRestriction</A></H2> + +<H3>Examples</H3> + +<PRE CLASS="command"> +ConfigurationChangeRestriction all +ConfigurationChangeRestriction root-only +ConfigurationChangeRestriction none +</PRE> + +<H3>Description</H3> + +<P>The <CODE>ConfigurationChangeRestriction</CODE> directive specifies +the degree of restriction for changes to cupsd.conf. Keywords dealing +with filenames, paths, and users are security-sensitive. Changes to +them via HTTP are forbidden by default (<CODE>all</CODE>). The value +<CODE>none</CODE> removes any restriction altogether (note that this +is unsafe). The value <CODE>root-only</CODE> allows only users +authorised as user "root" to adjust security-sensitive configuration +settings, but note that users adjusting settings using polkit (via +cups-pk-helper) are authenticated as user "root".</P> + <H2 CLASS="title"><A NAME="DataDir">DataDir</A></H2> --- man/cupsctl.man.orig 2011-01-11 04:04:04.000000000 +0100 +++ man/cupsctl.man 2014-02-05 14:15:23.000000000 +0100 @@ -90,7 +90,8 @@ Disable printer sharing: cupsctl --no-shared-printers .fi .LP -Enable printing using the file: pseudo-device: +Enable printing using the file: pseudo-device (note that this is +forbidden by default): .nf cupsctl FileDevice=Yes .fi --- man/cupsd.conf.man.in.orig 2011-05-18 23:33:35.000000000 +0200 +++ man/cupsd.conf.man.in 2014-02-05 14:16:58.000000000 +0100 @@ -238,6 +238,21 @@ ConfigFilePerm mode Specifies the permissions for all configuration files that the scheduler writes. .TP 5 +ConfigurationChangeRestriction all +.TP 5 +ConfigurationChangeRestriction root-only +.TP 5 +ConfigurationChangeRestriction none +.br +Specifies the degree of restriction for changes to cupsd.conf. +Keywords dealing with filenames, paths, and users are +security-sensitive. Changes to them via HTTP are forbidden by default +("all"). The value "none" removes any restriction altogether (note +that this is unsafe). The value "root-only" allows only users +authorised as user "root" to adjust security-sensitive configuration +settings, but note that users adjusting settings using polkit (via +cups-pk-helper) are authenticated as user "root". +.TP 5 DataDir path .br Specified the directory where data files can be found. --- scheduler/client.c.orig 2012-03-07 07:05:39.000000000 +0100 +++ scheduler/client.c 2014-02-05 14:32:49.000000000 +0100 @@ -1685,13 +1685,10 @@ cupsdReadClient(cupsd_client_t *con) /* * Validate the resource name... */ - if (strncmp(con->uri, "/admin/conf/", 12) || - strchr(con->uri + 12, '/') || - strlen(con->uri) == 12) + if (strcmp(con->uri, "/admin/conf/cupsd.conf")) { /* - * PUT can only be done to configuration files under - * /admin/conf... + * PUT can only be done to the cupsd.conf file... */ cupsdLogMessage(CUPSD_LOG_ERROR, @@ -3827,6 +3824,8 @@ install_conf_file(cupsd_client_t *con) / char buffer[16384]; /* Copy buffer */ ssize_t bytes; /* Number of bytes */ + if (!cupsdCheckConfigurationAllowed (con)) + return (HTTP_FORBIDDEN); /* * Open the request file... --- scheduler/conf.h.orig 2011-04-22 19:47:03.000000000 +0200 +++ scheduler/conf.h 2014-02-05 14:44:49.000000000 +0100 @@ -92,6 +92,18 @@ typedef struct /* + * Configuration change restriction (CVE-2012-5519) + */ + +typedef enum +{ + CUPSD_CONFRESTRICT_NONE, /* No checking of PUT cupsd.conf */ + CUPSD_CONFRESTRICT_ROOT, /* Only allow root to change all opts */ + CUPSD_CONFRESTRICT_ALL, /* Restricted keywords not to be changed */ +} cupsd_confrestrict_t; + + +/* * Globals... */ @@ -165,6 +177,8 @@ VAR int ClassifyOverride VALUE(0), /* Allow overrides? */ ConfigFilePerm VALUE(0640), /* Permissions for config files */ + ConfigurationChangeRestriction VALUE(CUPSD_CONFRESTRICT_ALL), + /* CVE-2012-5519 protection */ LogDebugHistory VALUE(200), /* Amount of automatic debug history */ FatalErrors VALUE(CUPSD_FATAL_CONFIG), @@ -291,6 +305,7 @@ __attribute__ ((__format__ (__printf__, extern int cupsdLogPage(cupsd_job_t *job, const char *page); extern int cupsdLogRequest(cupsd_client_t *con, http_status_t code); extern int cupsdReadConfiguration(void); +extern int cupsdCheckConfigurationAllowed(cupsd_client_t *con); extern int cupsdWriteErrorLog(int level, const char *message); --- scheduler/conf.c.orig 2011-11-16 16:28:11.000000000 +0100 +++ scheduler/conf.c 2014-02-05 15:03:28.000000000 +0100 @@ -3196,6 +3196,22 @@ read_configuration(cups_file_t *fp) /* I cupsdLogMessage(CUPSD_LOG_INFO, "Polling %s:%d", pollp->hostname, pollp->port); } + else if (!strcasecmp(line, "ConfigurationChangeRestriction") && value) + { + if (!strcasecmp(value, "none")) + ConfigurationChangeRestriction = CUPSD_CONFRESTRICT_NONE; + else if (!strcasecmp(value, "root-only")) + ConfigurationChangeRestriction = CUPSD_CONFRESTRICT_ROOT; + else if (!strcasecmp(value, "all")) + ConfigurationChangeRestriction = CUPSD_CONFRESTRICT_ALL; + else + { + cupsdLogMessage(CUPSD_LOG_WARN, + "Unknown restriction type %s on line %d.", + value, linenum); + return (0); + } + } else if (!_cups_strcasecmp(line, "DefaultAuthType") && value) { /* @@ -3657,6 +3673,250 @@ read_configuration(cups_file_t *fp) /* I } +static cups_array_t * +_cupsdGetBlacklistedConfLines(cups_file_t *fp) +{ + cups_array_t *conf; + int linenum; + char keyword[HTTP_MAX_BUFFER], + *temp, + *value; + const char **kw; + size_t len; + const char *blacklist[] = { + "ConfigurationChangeRestriction", + "AccessLog", + "BrowseLDAPCACertFile", + "CacheDir", + "ConfigFilePerm", + "DataDir", + "DocumentRoot", + "ErrorLog", + "FatalErrors", + "FileDevice", + "FontPath", + "Group", + "JobPrivateAccess", + "JobPrivateValues", + "LogFilePerm", + "PageLog", + "Printcap", + "PrintcapFormat", + "PrintcapGUI", + "RemoteRoot", + "RequestRoot", + "ServerBin", + "ServerCertificate", + "ServerKey", + "ServerRoot", + "StateDir", + "SubscriptionPrivateAccess", + "SubscriptionPrivateValues", + "SystemGroup", + "SystemGroupAuthKey", + "TempDir", + "User", + "WebInterface", + NULL + }; + + conf = cupsArrayNew (NULL, NULL); + + /* + * Loop through each line in the file... + */ + + linenum = 0; + + while (cupsFileGetConf(fp, keyword, sizeof(keyword), &value, &linenum)) + { + for (kw = blacklist; *kw; kw++) + if (!strcasecmp (keyword, *kw)) + break; + + if (*kw == NULL) + continue; + + /* + * Remember lines we might need to compare against, but only the + * last occurrence of each keyword, except for + * SystemGroup. SystemGroup is special because it is cumulative: + * each SystemGroup line adds groups to the list. For that reason, + * we remember multiple SystemGroup lines and don't care about the + * order... + */ + + len = strlen (keyword); + if (strcasecmp(keyword, "SystemGroup") != 0) + { + for (temp = (char *) cupsArrayFirst(conf); + temp; + temp = (char *) cupsArrayNext(conf)) + { + if (!strncasecmp (temp, keyword, len) && temp[len] == ' ') + { + cupsArrayRemove(conf, temp); + + /* + * There can only be one such line because we do this for each + * line containing a blacklisted keyword + */ + + break; + } + } + } + + len += (value ? strlen (value) : 0) + 2; + temp = malloc (len); + if (!temp) + goto fail; + + snprintf (temp, len, "%s %s", keyword, value ? value : ""); + cupsArrayAdd(conf, temp); + } + + return conf; + +fail: + for (temp = (char *) cupsArrayFirst(conf); + temp; + temp = (char *) cupsArrayNext(conf)) + free(temp); + cupsArrayDelete(conf); + return NULL; +} + + +/* + * 'cupsdCheckConfigurationAllowed()' - Check whether the new configuration + * file can be installed + */ + +int /* O - 1 if allowed, 0 otherwise */ +cupsdCheckConfigurationAllowed(cupsd_client_t *con) +{ + int status = 0; + cups_file_t *fp; + cups_array_t *oldconf, + *newconf = NULL; + char *oldline, + *newline; + + if (ConfigurationChangeRestriction == CUPSD_CONFRESTRICT_NONE) + /* + * Option checking disabled... + */ + return (1); + + if (ConfigurationChangeRestriction == CUPSD_CONFRESTRICT_ROOT && + !strcmp (con->username, "root")) + /* + * This is requested by root and our configuration tells us to + * accept it. + */ + return (1); + + /* + * First read the current cupsd.conf... + */ + + if ((fp = cupsFileOpen (ConfigurationFile, "r")) == NULL) + { + cupsdLogMessage(CUPSD_LOG_WARN, "Unable to open configuration file?!"); + return (0); + } + + oldconf = _cupsdGetBlacklistedConfLines(fp); + cupsFileClose(fp); + if (!oldconf) + return (0); + + /* + * Now take a look at the proposed new cupsd.conf... + */ + + if ((fp = cupsFileOpen(con->filename, "r")) == NULL) + { + cupsdLogMessage(CUPSD_LOG_WARN, "Unable to examine new config file"); + goto fail; + } + + newconf = _cupsdGetBlacklistedConfLines(fp); + cupsFileClose(fp); + if (!newconf) + goto fail; + + /* + * Now compare the blacklisted directives in each. + */ + + status = 1; + for (oldline = (char *) cupsArrayFirst(oldconf); + oldline; + oldline = (char *) cupsArrayNext(oldconf)) + { + for (newline = (char *) cupsArrayFirst(newconf); + newline; + newline = (char *) cupsArrayNext(newconf)) + if (!strcmp (oldline, newline)) + break; + + if (newline == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Attempt to remove or change '%s' denied", oldline); + status = 0; + break; + } + + cupsArrayRemove(newconf, newline); + free(newline); + } + + if (status) + { + /* + * All the original directives are still present. Have any been added? + */ + + newline = (char *) cupsArrayFirst(newconf); + if (newline != NULL) + { + char *p; + + cupsArrayRemove(newconf, newline); + + p = strchr (newline, ' '); + if (p) + *p = '\0'; + + cupsdLogMessage(CUPSD_LOG_ERROR, "Attempt to add '%s' directive denied", newline); + free(newline); + status = 0; + } + } + +fail: + for (oldline = (char *) cupsArrayFirst(oldconf); + oldline; + oldline = (char *) cupsArrayNext(oldconf)) + free(oldline); + cupsArrayDelete(oldconf); + + if (newconf) + { + for (newline = (char *) cupsArrayFirst(newconf); + newline; + newline = (char *) cupsArrayNext(newconf)) + free(newline); + cupsArrayDelete(newconf); + } + + return (status); +} + + /* * 'read_location()' - Read a <Location path> definition. */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor