diff -up cups-2.2.4/man/cupsd.conf.man.in.privilege-escalation cups-2.2.4/man/cupsd.conf.man.in
--- cups-2.2.4/man/cupsd.conf.man.in.privilege-escalation 2017-06-30 17:44:38.000000000 +0200
+++ cups-2.2.4/man/cupsd.conf.man.in 2018-07-23 14:57:44.562873692 +0200
@@ -377,10 +377,6 @@ The following percent sequences are reco
.fi
The default is the empty string, which disables page logging.
The string "%p %u %j %T %P %C %{job-billing} %{job-originating-host-name} %{job-name} %{media} %{sides}" creates a page log with the standard items.
-.\"#PassEnv
-.TP 5
-\fBPassEnv \fIvariable \fR[ ... \fIvariable \fR]
-Passes the specified environment variable(s) to child processes.
.\"#Policy
.TP 5
\fB<Policy \fIname\fB> \fR... \fB</Policy>\fR
@@ -466,10 +462,6 @@ Specifies what information is included i
command.
"Full" reports "CUPS 2.0.0 (UNAME) IPP/2.0".
The default is "Minimal".
-.\"#SetEnv
-.TP 5
-\fBSetEnv \fIvariable value\fR
-Set the specified environment variable to be passed to child processes.
.\"#SSLListen
.TP 5
\fBSSLListen \fIipv4-address\fB:\fIport\fR
diff -up cups-2.2.4/man/cups-files.conf.man.in.privilege-escalation cups-2.2.4/man/cups-files.conf.man.in
--- cups-2.2.4/man/cups-files.conf.man.in.privilege-escalation 2018-07-23 14:19:08.661479271 +0200
+++ cups-2.2.4/man/cups-files.conf.man.in 2018-07-23 14:53:55.198731082 +0200
@@ -159,6 +159,11 @@ The server name may be included in filen
.fi
The default is "/var/log/cups/page_log".
+.\"#PassEnv
+.TP 5
+\fBPassEnv \fIvariable \fR[ ... \fIvariable \fR]
+Passes the specified environment variable(s) to child processes.
+Note: the standard CUPS filter and backend environment variables cannot be overridden using this directive.
.\"#RemoteRoot
.TP 5
\fBRemoteRoot \fIusername\fR
@@ -193,6 +198,11 @@ macOS uses its keychain database to stor
\fBServerRoot \fIdirectory\fR
Specifies the directory containing the server configuration files.
The default is "/etc/cups".
+.\"#SetEnv
+.TP 5
+\fBSetEnv \fIvariable value\fR
+Set the specified environment variable to be passed to child processes.
+Note: the standard CUPS filter and backend environment variables cannot be overridden using this directive.
.\"#SyncOnClose
.TP 5
\fBSyncOnClose Yes\fR
diff -up cups-2.2.4/scheduler/conf.c.privilege-escalation cups-2.2.4/scheduler/conf.c
--- cups-2.2.4/scheduler/conf.c.privilege-escalation 2018-07-23 14:19:08.695478342 +0200
+++ cups-2.2.4/scheduler/conf.c 2018-07-23 14:19:08.713477851 +0200
@@ -2956,13 +2956,10 @@ read_cupsd_conf(cups_file_t *fp) /* I -
/* Line from file */
temp[HTTP_MAX_BUFFER],
/* Temporary buffer for value */
- *value, /* Pointer to value */
- *valueptr; /* Pointer into value */
+ *value; /* Pointer to value */
int valuelen; /* Length of value */
http_addrlist_t *addrlist, /* Address list */
*addr; /* Current address */
- cups_file_t *incfile; /* Include file */
- char incname[1024]; /* Include filename */
/*
@@ -2977,28 +2974,7 @@ read_cupsd_conf(cups_file_t *fp) /* I -
* Decode the directive...
*/
- if (!_cups_strcasecmp(line, "Include") && value)
- {
- /*
- * Include filename
- */
-
- if (value[0] == '/')
- strlcpy(incname, value, sizeof(incname));
- else
- snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value);
-
- if ((incfile = cupsFileOpen(incname, "rb")) == NULL)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to include config file \"%s\" - %s",
- incname, strerror(errno));
- else
- {
- read_cupsd_conf(incfile);
- cupsFileClose(incfile);
- }
- }
- else if (!_cups_strcasecmp(line, "<Location") && value)
+ if (!_cups_strcasecmp(line, "<Location") && value)
{
/*
* <Location path>
@@ -3376,31 +3352,6 @@ read_cupsd_conf(cups_file_t *fp) /* I -
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d of %s.",
value, linenum, ConfigurationFile);
}
- else if (!_cups_strcasecmp(line, "PassEnv") && value)
- {
- /*
- * PassEnv variable [... variable]
- */
-
- for (; *value;)
- {
- for (valuelen = 0; value[valuelen]; valuelen ++)
- if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
- break;
-
- if (value[valuelen])
- {
- value[valuelen] = '\0';
- valuelen ++;
- }
-
- cupsdSetEnv(value, NULL);
-
- for (value += valuelen; *value; value ++)
- if (!_cups_isspace(*value) || *value != ',')
- break;
- }
- }
else if (!_cups_strcasecmp(line, "ServerAlias") && value)
{
/*
@@ -3429,30 +3380,6 @@ read_cupsd_conf(cups_file_t *fp) /* I -
break;
}
}
- else if (!_cups_strcasecmp(line, "SetEnv") && value)
- {
- /*
- * SetEnv variable value
- */
-
- for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
-
- if (*valueptr)
- {
- /*
- * Found a value...
- */
-
- while (isspace(*valueptr & 255))
- *valueptr++ = '\0';
-
- cupsdSetEnv(value, valueptr);
- }
- else
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Missing value for SetEnv directive on line %d of %s.",
- linenum, ConfigurationFile);
- }
else if (!_cups_strcasecmp(line, "AccessLog") ||
!_cups_strcasecmp(line, "CacheDir") ||
!_cups_strcasecmp(line, "ConfigFilePerm") ||
@@ -3466,6 +3393,7 @@ read_cupsd_conf(cups_file_t *fp) /* I -
!_cups_strcasecmp(line, "LogFilePerm") ||
!_cups_strcasecmp(line, "LPDConfigFile") ||
!_cups_strcasecmp(line, "PageLog") ||
+ !_cups_strcasecmp(line, "PassEnv") ||
!_cups_strcasecmp(line, "Printcap") ||
!_cups_strcasecmp(line, "PrintcapFormat") ||
!_cups_strcasecmp(line, "RemoteRoot") ||
@@ -3475,6 +3403,7 @@ read_cupsd_conf(cups_file_t *fp) /* I -
!_cups_strcasecmp(line, "ServerKey") ||
!_cups_strcasecmp(line, "ServerKeychain") ||
!_cups_strcasecmp(line, "ServerRoot") ||
+ !_cups_strcasecmp(line, "SetEnv") ||
!_cups_strcasecmp(line, "SMBConfigFile") ||
!_cups_strcasecmp(line, "StateDir") ||
!_cups_strcasecmp(line, "SystemGroup") ||
@@ -3504,10 +3433,49 @@ read_cupsd_conf(cups_file_t *fp) /* I -
static int /* O - 1 on success, 0 on failure */
read_cups_files_conf(cups_file_t *fp) /* I - File to read from */
{
- int linenum; /* Current line number */
+ int i, /* Looping var */
+ linenum; /* Current line number */
char line[HTTP_MAX_BUFFER], /* Line from file */
*value; /* Value from line */
struct group *group; /* Group */
+ static const char * const prohibited_env[] =
+ { /* Prohibited environment variables */
+ "APPLE_LANGUAGE",
+ "AUTH_DOMAIN",
+ "AUTH_INFO_REQUIRED",
+ "AUTH_NEGOTIATE",
+ "AUTH_PASSWORD",
+ "AUTH_UID",
+ "AUTH_USERNAME",
+ "CHARSET",
+ "CLASS",
+ "CLASSIFICATION",
+ "CONTENT_TYPE",
+ "CUPS_CACHEDIR",
+ "CUPS_DATADIR",
+ "CUPS_DOCROOT",
+ "CUPS_FILETYPE",
+ "CUPS_FONTPATH",
+ "CUPS_MAX_MESSAGE",
+ "CUPS_REQUESTROOT",
+ "CUPS_SERVERBIN",
+ "CUPS_SERVERROOT",
+ "CUPS_STATEDIR",
+ "DEVICE_URI",
+ "FINAL_CONTENT_TYPE",
+ "HOME",
+ "LANG",
+ "PPD",
+ "PRINTER",
+ "PRINTER_INFO",
+ "PRINTER_LOCATION",
+ "PRINTER_STATE_REASONS",
+ "RIP_CACHE",
+ "SERVER_ADMIN",
+ "SOFTWARE",
+ "TMPDIR",
+ "USER"
+ };
/*
@@ -3545,6 +3513,47 @@ read_cups_files_conf(cups_file_t *fp) /*
}
}
}
+ else if (!_cups_strcasecmp(line, "PassEnv") && value)
+ {
+ /*
+ * PassEnv variable [... variable]
+ */
+
+ int valuelen; /* Length of variable name */
+
+ for (; *value;)
+ {
+ for (valuelen = 0; value[valuelen]; valuelen ++)
+ if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
+ break;
+
+ if (value[valuelen])
+ {
+ value[valuelen] = '\0';
+ valuelen ++;
+ }
+
+ for (i = 0; i < (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])); i ++)
+ {
+ if (!strcmp(value, prohibited_env[i]))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Environment variable \"%s\" cannot be passed through on line %d of %s.", value, linenum, CupsFilesFile);
+
+ if (FatalErrors & CUPSD_FATAL_CONFIG)
+ return (0);
+ else
+ break;
+ }
+ }
+
+ if (i >= (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])))
+ cupsdSetEnv(value, NULL);
+
+ for (value += valuelen; *value; value ++)
+ if (!_cups_isspace(*value) || *value != ',')
+ break;
+ }
+ }
else if (!_cups_strcasecmp(line, "PrintcapFormat") && value)
{
/*
@@ -3590,6 +3599,46 @@ read_cups_files_conf(cups_file_t *fp) /*
return (0);
}
}
+ else if (!_cups_strcasecmp(line, "SetEnv") && value)
+ {
+ /*
+ * SetEnv variable value
+ */
+
+ char *valueptr; /* Pointer to environment variable value */
+
+ for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+ if (*valueptr)
+ {
+ /*
+ * Found a value...
+ */
+
+ while (isspace(*valueptr & 255))
+ *valueptr++ = '\0';
+
+ for (i = 0; i < (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])); i ++)
+ {
+ if (!strcmp(value, prohibited_env[i]))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Environment variable \"%s\" cannot be set on line %d of %s.", value, linenum, CupsFilesFile);
+
+ if (FatalErrors & CUPSD_FATAL_CONFIG)
+ return (0);
+ else
+ break;
+ }
+ }
+
+ if (i >= (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])))
+ cupsdSetEnv(value, valueptr);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Missing value for SetEnv directive on line %d of %s.",
+ linenum, ConfigurationFile);
+ }
else if (!_cups_strcasecmp(line, "SystemGroup") && value)
{
/*
diff -up cups-2.2.4/scheduler/job.c.privilege-escalation cups-2.2.4/scheduler/job.c
--- cups-2.2.4/scheduler/job.c.privilege-escalation 2018-07-23 14:19:08.698478261 +0200
+++ cups-2.2.4/scheduler/job.c 2018-07-23 14:19:08.715477797 +0200
@@ -4981,6 +4981,18 @@ start_job(cupsd_job_t *job, /* I -
job->profile = cupsdCreateProfile(job->id, 0);
job->bprofile = cupsdCreateProfile(job->id, 1);
+#ifdef HAVE_SANDBOX_H
+ if ((!job->profile || !job->bprofile) && UseSandboxing && Sandboxing != CUPSD_SANDBOXING_OFF)
+ {
+ /*
+ * Failure to create the sandbox profile means something really bad has
+ * happened and we need to shutdown immediately.
+ */
+
+ return;
+ }
+#endif /* HAVE_SANDBOX_H */
+
/*
* Create the status pipes and buffer...
*/
diff -up cups-2.2.4/scheduler/process.c.privilege-escalation cups-2.2.4/scheduler/process.c
--- cups-2.2.4/scheduler/process.c.privilege-escalation 2017-06-30 17:44:38.000000000 +0200
+++ cups-2.2.4/scheduler/process.c 2018-07-23 14:19:08.715477797 +0200
@@ -99,9 +99,13 @@ cupsdCreateProfile(int job_id, /* I - J
if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL)
{
+ /*
+ * This should never happen, and is fatal when sandboxing is enabled.
+ */
+
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking);
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s",
- strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_EMERG, "Unable to create security profile: %s", strerror(errno));
+ kill(getpid(), SIGTERM);
return (NULL);
}
@@ -198,10 +202,8 @@ cupsdCreateProfile(int job_id, /* I - J
" #\"^%s/\"" /* TempDir/... */
" #\"^%s$\"" /* CacheDir */
" #\"^%s/\"" /* CacheDir/... */
- " #\"^%s$\"" /* StateDir */
- " #\"^%s/\"" /* StateDir/... */
"))\n",
- temp, temp, cache, cache, state, state);
+ temp, temp, cache, cache);
/* Read common folders */
cupsFilePrintf(fp,
"(allow file-read-data file-read-metadata\n"
@@ -243,8 +245,10 @@ cupsdCreateProfile(int job_id, /* I - J
" #\"^%s/\"" /* ServerBin/... */
" #\"^%s$\"" /* ServerRoot */
" #\"^%s/\"" /* ServerRoot/... */
+ " #\"^%s$\"" /* StateDir */
+ " #\"^%s/\"" /* StateDir/... */
"))\n",
- request, request, bin, bin, root, root);
+ request, request, bin, bin, root, root, state, state);
if (Sandboxing == CUPSD_SANDBOXING_RELAXED)
{
/* Limited write access to /Library/Printers/... */
diff -up cups-2.2.4/scheduler/server.c.privilege-escalation cups-2.2.4/scheduler/server.c
--- cups-2.2.4/scheduler/server.c.privilege-escalation 2017-06-30 17:44:38.000000000 +0200
+++ cups-2.2.4/scheduler/server.c 2018-07-23 14:19:08.715477797 +0200
@@ -38,16 +38,28 @@ void
cupsdStartServer(void)
{
/*
- * Start color management (as needed)...
+ * Create the default security profile...
*/
- cupsdStartColor();
+ DefaultProfile = cupsdCreateProfile(0, 1);
+
+#ifdef HAVE_SANDBOX_H
+ if (!DefaultProfile && UseSandboxing && Sandboxing != CUPSD_SANDBOXING_OFF)
+ {
+ /*
+ * Failure to create the sandbox profile means something really bad has
+ * happened and we need to shutdown immediately.
+ */
+
+ return;
+ }
+#endif /* HAVE_SANDBOX_H */
/*
- * Create the default security profile...
+ * Start color management (as needed)...
*/
- DefaultProfile = cupsdCreateProfile(0, 1);
+ cupsdStartColor();
/*
* Startup all the networking stuff...
diff -up cups-2.2.4/test/run-stp-tests.sh.privilege-escalation cups-2.2.4/test/run-stp-tests.sh
--- cups-2.2.4/test/run-stp-tests.sh.privilege-escalation 2017-06-30 17:44:38.000000000 +0200
+++ cups-2.2.4/test/run-stp-tests.sh 2018-07-23 14:19:08.715477797 +0200
@@ -490,11 +490,6 @@ StrictConformance Yes
Browsing Off
Listen localhost:$port
Listen $BASE/sock
-PassEnv DYLD_LIBRARY_PATH
-PassEnv LD_LIBRARY_PATH
-PassEnv LD_PRELOAD
-PassEnv LOCALEDIR
-PassEnv SHLIB_PATH
MaxSubscriptions 3
MaxLogSize 0
AccessLogLevel actions
@@ -530,6 +525,12 @@ TempDir $BASE/spool/temp
AccessLog $BASE/log/access_log
ErrorLog $BASE/log/error_log
PageLog $BASE/log/page_log
+
+PassEnv DYLD_LIBRARY_PATH
+PassEnv LD_LIBRARY_PATH
+PassEnv LD_PRELOAD
+PassEnv LOCALEDIR
+PassEnv SHLIB_PATH
EOF
if test $ssltype != 0 -a `uname` = Darwin; then