summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL.txt21
-rw-r--r--includes/file.inc8
-rw-r--r--modules/upload.module78
-rw-r--r--modules/upload/upload.module78
4 files changed, 169 insertions, 16 deletions
diff --git a/INSTALL.txt b/INSTALL.txt
index fc2e5529a..dce0db9b3 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -68,8 +68,8 @@ INSTALLATION
The default configuration can be found in the
'sites/default/settings.php' file within your Drupal installation.
- Before you can run Drupal, you must set the database URL. Open the
- configuration file and edit the $db_url line to match the database
+ Before you can run Drupal, you must set the database URL. Open the
+ configuration file and edit the $db_url line to match the database
defined in the previous step:
$db_url = "mysql://username:password@localhost/databasename";
@@ -144,12 +144,17 @@ INSTALLATION
by the Drupal server process. You can change the name of this
subdirectory at "Administer > Settings > File system settings".
- SECURITY NOTICE: Certain Apache configurations can be vulnerable
- to a security exploit allowing arbitrary code execution. Drupal
- will attempt to automatically create a .htaccess file in your
+ SECURITY NOTICE: Certain Apache configurations can be vulnerable
+ to a security exploit allowing arbitrary code execution. Drupal
+ will attempt to automatically create a .htaccess file in your
"files" directory to protect you. If you already have a .htaccess
- file in that location, please add the following line:
- SetHandler This_is_a_Drupal_security_line_do_not_remove
+ file in that location, please add the following lines:
+
+ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
+ Options None
+ <IfModule mod_rewrite.c>
+ RewriteEngine off
+ </IfModule>
You can now launch your browser and point it to your Drupal site.
@@ -186,7 +191,7 @@ example, set some general settings for your site with "Administer >
Settings". Enable modules via "Administer > Modules". User permissions
can be set with "Administer > Users > Configure > Permissions".
-For more information on configuration options, read the
+For more information on configuration options, read the
instructions which accompany the different configuration settings and
consult the various help pages available in the administration panel.
diff --git a/includes/file.inc b/includes/file.inc
index 802df5656..7d23d4a7c 100644
--- a/includes/file.inc
+++ b/includes/file.inc
@@ -113,17 +113,17 @@ function file_check_directory(&$directory, $mode = 0, $form_item = NULL) {
}
if ((file_directory_path() == $directory || file_directory_temp() == $directory) && !is_file("$directory/.htaccess")) {
- if (($fp = fopen("$directory/.htaccess", 'w')) && fputs($fp, 'SetHandler This_is_a_Drupal_security_line_do_not_remove')) {
+ $htaccess_lines = "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\n<IfModule mod_rewrite.c>\n RewriteEngine off\n</IfModule>";
+ if (($fp = fopen("$directory/.htaccess", 'w')) && fputs($fp, $htaccess_lines)) {
fclose($fp);
}
else {
- $message = t("Security warning: Couldn't write .htaccess. Please create a .htaccess file in your %directory directory which contains the following line: <code>SetHandler This_is_a_Drupal_security_line_do_not_remove</code>", array('%directory' => $directory));
+ $message = t("Security warning: Couldn't write .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines: <code>%htaccess</code>", array('%directory' => theme('placeholder', $directory), '%htaccess' => '<br />'. str_replace("\n", '<br />', check_plain($htaccess_lines))));
form_set_error($form_item, $message);
- watchdog('file system', $message, WATCHDOG_ERROR);
+ watchdog('security', $message, WATCHDOG_ERROR);
}
}
-
return true;
}
diff --git a/modules/upload.module b/modules/upload.module
index ca01ac700..98cd8c2fc 100644
--- a/modules/upload.module
+++ b/modules/upload.module
@@ -253,9 +253,10 @@ function _upload_prepare(&$node) {
unset($_SESSION['file_current_upload']);
+ global $user;
+
// Save new file uploads to tmp dir.
if (($file = file_check_upload()) && user_access('upload files')) {
- global $user;
// Scale image uploads.
$file = _upload_image($file);
@@ -274,6 +275,11 @@ function _upload_prepare(&$node) {
// Attach file previews to node object.
if (is_array($_SESSION['file_previews']) && count($_SESSION['file_previews'])) {
foreach($_SESSION['file_previews'] as $fid => $file) {
+ if ($user->uid != 1) {
+ // Here something.php.pps becomes something.php_.pps
+ $file->filename = upload_munge_filename($file->filename, NULL, 0);
+ $file->description = $file->filename;
+ }
$node->files[$fid] = $file;
}
}
@@ -375,6 +381,11 @@ function _upload_validate(&$node) {
form_set_error('upload', t('The selected file %name can not be attached to this post, because the disk quota of %quota has been reached.', array('%name' => theme('placeholder', $file->filename), '%quota' => theme('placeholder', format_size($usersize)))));
$valid = FALSE;
}
+ elseif (strlen($node->files[$fid]->filename) > 255) {
+ form_set_error('upload', t('The selected file %name can not be attached to this post, because the filename is too long.', array('%name' => theme('placeholder', $munged_filename))));
+ $valid = FALSE;
+ }
+
if (!$valid) {
unset($node->files[$fid], $_SESSION['file_previews'][$fid]);
file_delete($file->filepath);
@@ -522,6 +533,66 @@ function upload_total_space_used() {
return db_result(db_query('SELECT SUM(filesize) FROM {files}'));
}
+/**
+ * Munge the filename as needed for security purposes.
+ *
+ * @param $filename
+ * The name of a file to modify.
+ * @param $extensions
+ * A space separated list of valid extensions. If this is blank, we'll use
+ * the admin-defined defaults for the user role from upload_extensions_$rid.
+ * @param $alerts
+ * Whether alerts (watchdog, drupal_set_message()) should be displayed.
+ * @return $filename
+ * The potentially modified $filename.
+ */
+function upload_munge_filename($filename, $extensions = NULL, $alerts = 1) {
+ global $user;
+
+ $original = $filename;
+
+ // Allow potentially insecure uploads for very savvy users and admin
+ if (!variable_get('allow_insecure_uploads', 0)) {
+
+ if (!isset($extensions)) {
+ $extensions = '';
+ foreach ($user->roles as $rid => $name) {
+ $extensions .= ' '. variable_get("upload_extensions_$rid", variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps'));
+ }
+
+ }
+
+ $whitelist = array_unique(explode(' ', trim($extensions)));
+
+ $filename_parts = explode('.', $filename);
+
+ $new_filename = array_shift($filename_parts); // Remove file basename.
+ $final_extension = array_pop($filename_parts); // Remove final extension.
+
+ foreach($filename_parts as $filename_part) {
+ $new_filename .= ".$filename_part";
+ if (!in_array($filename_part, $whitelist) && preg_match("/^[a-zA-Z]{2,5}\d?$/", $filename_part)) {
+ $new_filename .= '_';
+ }
+ }
+ $filename = "$new_filename.$final_extension";
+ }
+
+ if ($alerts && $original != $filename) {
+ $message = t('Your filename has been renamed to conform to site policy.');
+ drupal_set_message($message);
+ }
+
+ return $filename;
+}
+
+/**
+ * Undo the effect of upload_munge_filename().
+ */
+function upload_unmunge_filename($filename) {
+ return str_replace('_.', '.', $filename);
+}
+
function upload_save($node) {
if (!is_array($node->files)) {
return;
@@ -609,14 +680,17 @@ function upload_delete_revision($node) {
}
function _upload_form($node) {
+
$form['#theme'] = 'upload_form_new';
if (is_array($node->files) && count($node->files)) {
$form['files']['#theme'] = 'upload_form_current';
$form['files']['#tree'] = TRUE;
foreach ($node->files as $key => $file) {
- $description = "<small>". file_create_url((strpos($file->fid,'upload') === false ? $file->filepath : file_create_filename($file->filename, file_create_path()))) ."</small>";
+ $description = file_create_url((strpos($file->fid, 'upload') === false ? $file->filepath : file_create_filename($file->filename, file_create_path())));
+ $description = "<small>". check_plain($description) ."</small>";
$form['files'][$key]['description'] = array('#type' => 'textfield', '#default_value' => (strlen($file->description)) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => $description );
+
$form['files'][$key]['size'] = array('#type' => 'markup', '#value' => format_size($file->filesize));
$form['files'][$key]['remove'] = array('#type' => 'checkbox', '#default_value' => $file->remove);
$form['files'][$key]['list'] = array('#type' => 'checkbox', '#default_value' => $file->list);
diff --git a/modules/upload/upload.module b/modules/upload/upload.module
index ca01ac700..98cd8c2fc 100644
--- a/modules/upload/upload.module
+++ b/modules/upload/upload.module
@@ -253,9 +253,10 @@ function _upload_prepare(&$node) {
unset($_SESSION['file_current_upload']);
+ global $user;
+
// Save new file uploads to tmp dir.
if (($file = file_check_upload()) && user_access('upload files')) {
- global $user;
// Scale image uploads.
$file = _upload_image($file);
@@ -274,6 +275,11 @@ function _upload_prepare(&$node) {
// Attach file previews to node object.
if (is_array($_SESSION['file_previews']) && count($_SESSION['file_previews'])) {
foreach($_SESSION['file_previews'] as $fid => $file) {
+ if ($user->uid != 1) {
+ // Here something.php.pps becomes something.php_.pps
+ $file->filename = upload_munge_filename($file->filename, NULL, 0);
+ $file->description = $file->filename;
+ }
$node->files[$fid] = $file;
}
}
@@ -375,6 +381,11 @@ function _upload_validate(&$node) {
form_set_error('upload', t('The selected file %name can not be attached to this post, because the disk quota of %quota has been reached.', array('%name' => theme('placeholder', $file->filename), '%quota' => theme('placeholder', format_size($usersize)))));
$valid = FALSE;
}
+ elseif (strlen($node->files[$fid]->filename) > 255) {
+ form_set_error('upload', t('The selected file %name can not be attached to this post, because the filename is too long.', array('%name' => theme('placeholder', $munged_filename))));
+ $valid = FALSE;
+ }
+
if (!$valid) {
unset($node->files[$fid], $_SESSION['file_previews'][$fid]);
file_delete($file->filepath);
@@ -522,6 +533,66 @@ function upload_total_space_used() {
return db_result(db_query('SELECT SUM(filesize) FROM {files}'));
}
+/**
+ * Munge the filename as needed for security purposes.
+ *
+ * @param $filename
+ * The name of a file to modify.
+ * @param $extensions
+ * A space separated list of valid extensions. If this is blank, we'll use
+ * the admin-defined defaults for the user role from upload_extensions_$rid.
+ * @param $alerts
+ * Whether alerts (watchdog, drupal_set_message()) should be displayed.
+ * @return $filename
+ * The potentially modified $filename.
+ */
+function upload_munge_filename($filename, $extensions = NULL, $alerts = 1) {
+ global $user;
+
+ $original = $filename;
+
+ // Allow potentially insecure uploads for very savvy users and admin
+ if (!variable_get('allow_insecure_uploads', 0)) {
+
+ if (!isset($extensions)) {
+ $extensions = '';
+ foreach ($user->roles as $rid => $name) {
+ $extensions .= ' '. variable_get("upload_extensions_$rid", variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps'));
+ }
+
+ }
+
+ $whitelist = array_unique(explode(' ', trim($extensions)));
+
+ $filename_parts = explode('.', $filename);
+
+ $new_filename = array_shift($filename_parts); // Remove file basename.
+ $final_extension = array_pop($filename_parts); // Remove final extension.
+
+ foreach($filename_parts as $filename_part) {
+ $new_filename .= ".$filename_part";
+ if (!in_array($filename_part, $whitelist) && preg_match("/^[a-zA-Z]{2,5}\d?$/", $filename_part)) {
+ $new_filename .= '_';
+ }
+ }
+ $filename = "$new_filename.$final_extension";
+ }
+
+ if ($alerts && $original != $filename) {
+ $message = t('Your filename has been renamed to conform to site policy.');
+ drupal_set_message($message);
+ }
+
+ return $filename;
+}
+
+/**
+ * Undo the effect of upload_munge_filename().
+ */
+function upload_unmunge_filename($filename) {
+ return str_replace('_.', '.', $filename);
+}
+
function upload_save($node) {
if (!is_array($node->files)) {
return;
@@ -609,14 +680,17 @@ function upload_delete_revision($node) {
}
function _upload_form($node) {
+
$form['#theme'] = 'upload_form_new';
if (is_array($node->files) && count($node->files)) {
$form['files']['#theme'] = 'upload_form_current';
$form['files']['#tree'] = TRUE;
foreach ($node->files as $key => $file) {
- $description = "<small>". file_create_url((strpos($file->fid,'upload') === false ? $file->filepath : file_create_filename($file->filename, file_create_path()))) ."</small>";
+ $description = file_create_url((strpos($file->fid, 'upload') === false ? $file->filepath : file_create_filename($file->filename, file_create_path())));
+ $description = "<small>". check_plain($description) ."</small>";
$form['files'][$key]['description'] = array('#type' => 'textfield', '#default_value' => (strlen($file->description)) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => $description );
+
$form['files'][$key]['size'] = array('#type' => 'markup', '#value' => format_size($file->filesize));
$form['files'][$key]['remove'] = array('#type' => 'checkbox', '#default_value' => $file->remove);
$form['files'][$key]['list'] = array('#type' => 'checkbox', '#default_value' => $file->list);