165 lines
4.4 KiB
Diff
165 lines
4.4 KiB
Diff
|
--- scheduler/client.c.orig 2014-09-02 11:26:57.000000000 +0200
|
||
|
+++ scheduler/client.c 2014-09-02 12:35:05.000000000 +0200
|
||
|
@@ -3672,51 +3672,72 @@ get_file(cupsd_client_t *con, /* I - C
|
||
|
if ((ptr = strchr(filename, '?')) != NULL)
|
||
|
*ptr = '\0';
|
||
|
|
||
|
/*
|
||
|
* Grab the status for this language; if there isn't a language-specific file
|
||
|
* then fallback to the default one...
|
||
|
*/
|
||
|
|
||
|
- if ((status = stat(filename, filestats)) != 0 && language[0] &&
|
||
|
+ if ((status = lstat(filename, filestats)) != 0 && language[0] &&
|
||
|
strncmp(con->uri, "/icons/", 7) &&
|
||
|
strncmp(con->uri, "/ppd/", 5) &&
|
||
|
strncmp(con->uri, "/rss/", 5) &&
|
||
|
strncmp(con->uri, "/admin/conf/", 12) &&
|
||
|
strncmp(con->uri, "/admin/log/", 11))
|
||
|
{
|
||
|
/*
|
||
|
* Drop the country code...
|
||
|
*/
|
||
|
|
||
|
language[3] = '\0';
|
||
|
snprintf(filename, len, "%s%s%s", DocumentRoot, language, con->uri);
|
||
|
|
||
|
if ((ptr = strchr(filename, '?')) != NULL)
|
||
|
*ptr = '\0';
|
||
|
|
||
|
- if ((status = stat(filename, filestats)) != 0)
|
||
|
+ if ((status = lstat(filename, filestats)) != 0)
|
||
|
{
|
||
|
/*
|
||
|
* Drop the language prefix and try the root directory...
|
||
|
*/
|
||
|
|
||
|
language[0] = '\0';
|
||
|
snprintf(filename, len, "%s%s", DocumentRoot, con->uri);
|
||
|
|
||
|
if ((ptr = strchr(filename, '?')) != NULL)
|
||
|
*ptr = '\0';
|
||
|
|
||
|
- status = stat(filename, filestats);
|
||
|
+ status = lstat(filename, filestats);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * If we're found a directory, get the index.html file instead...
|
||
|
+ * If we've found a symlink, 404 the sucker to avoid disclosing information.
|
||
|
+ */
|
||
|
+
|
||
|
+ if (!status && S_ISLNK(filestats->st_mode))
|
||
|
+ {
|
||
|
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Symlinks such as \"%s\" are not allowed.", con->http.fd, filename);
|
||
|
+ return (NULL);
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Similarly, if the file/directory does not have world read permissions, do
|
||
|
+ * not allow access...
|
||
|
+ */
|
||
|
+
|
||
|
+ if (!status && !(filestats->st_mode & S_IROTH))
|
||
|
+ {
|
||
|
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Files/directories such as \"%s\" must be world-readable.", con->http.fd, filename);
|
||
|
+ return (NULL);
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * If we've found a directory, get the index.html file instead...
|
||
|
*/
|
||
|
|
||
|
if (!status && S_ISDIR(filestats->st_mode))
|
||
|
{
|
||
|
/*
|
||
|
* Make sure the URI ends with a slash...
|
||
|
*/
|
||
|
|
||
|
@@ -3749,58 +3770,79 @@ get_file(cupsd_client_t *con, /* I - C
|
||
|
|
||
|
if ((ptr = strchr(filename, '?')) != NULL)
|
||
|
*ptr = '\0';
|
||
|
|
||
|
ptr = filename + strlen(filename);
|
||
|
plen = len - (ptr - filename);
|
||
|
|
||
|
strlcpy(ptr, "index.html", plen);
|
||
|
- status = stat(filename, filestats);
|
||
|
+ status = lstat(filename, filestats);
|
||
|
|
||
|
#ifdef HAVE_JAVA
|
||
|
if (status)
|
||
|
{
|
||
|
strlcpy(ptr, "index.class", plen);
|
||
|
- status = stat(filename, filestats);
|
||
|
+ status = lstat(filename, filestats);
|
||
|
}
|
||
|
#endif /* HAVE_JAVA */
|
||
|
|
||
|
#ifdef HAVE_PERL
|
||
|
if (status)
|
||
|
{
|
||
|
strlcpy(ptr, "index.pl", plen);
|
||
|
- status = stat(filename, filestats);
|
||
|
+ status = lstat(filename, filestats);
|
||
|
}
|
||
|
#endif /* HAVE_PERL */
|
||
|
|
||
|
#ifdef HAVE_PHP
|
||
|
if (status)
|
||
|
{
|
||
|
strlcpy(ptr, "index.php", plen);
|
||
|
- status = stat(filename, filestats);
|
||
|
+ status = lstat(filename, filestats);
|
||
|
}
|
||
|
#endif /* HAVE_PHP */
|
||
|
|
||
|
#ifdef HAVE_PYTHON
|
||
|
if (status)
|
||
|
{
|
||
|
strlcpy(ptr, "index.pyc", plen);
|
||
|
- status = stat(filename, filestats);
|
||
|
+ status = lstat(filename, filestats);
|
||
|
}
|
||
|
|
||
|
if (status)
|
||
|
{
|
||
|
strlcpy(ptr, "index.py", plen);
|
||
|
status = stat(filename, filestats);
|
||
|
}
|
||
|
#endif /* HAVE_PYTHON */
|
||
|
|
||
|
}
|
||
|
while (status && language[0]);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * If we've found a symlink, 404 the sucker to avoid disclosing information.
|
||
|
+ */
|
||
|
+
|
||
|
+ if (!status && S_ISLNK(filestats->st_mode))
|
||
|
+ {
|
||
|
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Symlinks such as \"%s\" are not allowed.", con->http.fd, filename);
|
||
|
+ return (NULL);
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Similarly, if the file/directory does not have world read permissions, do
|
||
|
+ * not allow access...
|
||
|
+ */
|
||
|
+
|
||
|
+ if (!status && !(filestats->st_mode & S_IROTH))
|
||
|
+ {
|
||
|
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Files/directories such as \"%s\" must be world-readable.", con->http.fd, filename);
|
||
|
+ return (NULL);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
cupsdLogMessage(CUPSD_LOG_DEBUG2,
|
||
|
"get_file(con=%p(%d), filestats=%p, filename=%p, len=%d) = "
|
||
|
"%s", con, con->http.fd, filestats, filename, len,
|
||
|
status ? "(null)" : filename);
|
||
|
|
||
|
if (status)
|