From 4a408843b0ef816daf70a472a02b78cd6073a4d5 Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <thomas@roundcube.net>
Date: Sun, 06 Mar 2016 08:31:07 -0500
Subject: [PATCH] Protect download urls against CSRF using unique request tokens (#1490642) Send X-Frame-Options headers with every HTTP response

---
 program/lib/Roundcube/rcube_output.php |   61 +++++++++++++++++-------------
 1 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/program/lib/Roundcube/rcube_output.php b/program/lib/Roundcube/rcube_output.php
index 4ef42f5..03ff4c1 100644
--- a/program/lib/Roundcube/rcube_output.php
+++ b/program/lib/Roundcube/rcube_output.php
@@ -1,18 +1,16 @@
 <?php
 
-/*
+/**
  +-----------------------------------------------------------------------+
- | program/include/rcube_output.php                                      |
- |                                                                       |
  | This file is part of the Roundcube PHP suite                          |
- | Copyright (C) 2005-2012 The Roundcube Dev Team                        |
+ | Copyright (C) 2005-2014 The Roundcube Dev Team                        |
  |                                                                       |
  | Licensed under the GNU General Public License version 3 or            |
  | any later version with exceptions for skins & plugins.                |
  | See the README file for a full license statement.                     |
+ |                                                                       |
  | CONTENTS:                                                             |
  |   Abstract class for output generation                                |
- |                                                                       |
  +-----------------------------------------------------------------------+
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
  | Author: Aleksander Machniak <alec@alec.pl>                            |
@@ -33,6 +31,7 @@
     protected $config;
     protected $charset = RCUBE_CHARSET;
     protected $env = array();
+    protected $skins = array();
 
 
     /**
@@ -45,19 +44,20 @@
         $this->browser = new rcube_browser();
     }
 
-
     /**
      * Magic getter
      */
     public function __get($var)
     {
-        // allow read-only access to $env
-        if ($var == 'env')
-            return $this->env;
+        // allow read-only access to some members
+        switch ($var) {
+            case 'env':     return $this->env;
+            case 'skins':   return $this->skins;
+            case 'charset': return $this->charset;
+        }
 
         return null;
     }
-
 
     /**
      * Setter for output charset.
@@ -70,7 +70,6 @@
         $this->charset = $charset;
     }
 
-
     /**
      * Getter for output charset
      *
@@ -80,7 +79,6 @@
     {
         return $this->charset;
     }
-
 
     /**
      * Set environment variable
@@ -92,7 +90,6 @@
     {
         $this->env[$name] = $value;
     }
-
 
     /**
      * Environment variable getter.
@@ -106,7 +103,6 @@
         return $this->env[$name];
     }
 
-
     /**
      * Delete all stored env variables and commands
      */
@@ -114,7 +110,6 @@
     {
         $this->env = array();
     }
-
 
     /**
      * Invoke display_message command
@@ -127,7 +122,6 @@
      */
     abstract function show_message($message, $type = 'notice', $vars = null, $override = true, $timeout = 0);
 
-
     /**
      * Redirect to a certain url.
      *
@@ -136,12 +130,10 @@
      */
     abstract function redirect($p = array(), $delay = 1);
 
-
     /**
      * Send output to the client.
      */
     abstract function send();
-
 
     /**
      * Send HTTP headers to prevent caching a page
@@ -155,16 +147,13 @@
         header("Expires: ".gmdate("D, d M Y H:i:s")." GMT");
         header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
 
-        // Request browser to disable DNS prefetching (CVE-2010-0464)
-        header("X-DNS-Prefetch-Control: off");
-
         // We need to set the following headers to make downloads work using IE in HTTPS mode.
         if ($this->browser->ie && rcube_utils::https_check()) {
             header('Pragma: private');
             header("Cache-Control: private, must-revalidate");
         }
         else {
-            header("Cache-Control: private, no-cache, must-revalidate, post-check=0, pre-check=0");
+            header("Cache-Control: private, no-cache, no-store, must-revalidate, post-check=0, pre-check=0");
             header("Pragma: no-cache");
         }
     }
@@ -176,14 +165,37 @@
      */
     public function future_expire_header($offset = 2600000)
     {
-        if (headers_sent())
+        if (headers_sent()) {
             return;
+        }
 
         header("Expires: " . gmdate("D, d M Y H:i:s", time()+$offset) . " GMT");
         header("Cache-Control: max-age=$offset");
         header("Pragma: ");
     }
 
+    /**
+     * Send browser compatibility/security/etc. headers
+     */
+    public function common_headers()
+    {
+        if (headers_sent()) {
+            return;
+        }
+
+        // Unlock IE compatibility mode
+        if ($this->browser->ie) {
+            header('X-UA-Compatible: IE=edge');
+        }
+
+        // Request browser to disable DNS prefetching (CVE-2010-0464)
+        header("X-DNS-Prefetch-Control: off");
+
+        // send CSRF and clickjacking protection headers
+        if ($xframe = $this->app->config->get('x_frame_options', 'sameorigin')) {
+            header('X-Frame-Options: ' . $xframe);
+        }
+    }
 
     /**
      * Show error page and terminate script execution
@@ -197,7 +209,6 @@
         fputs(STDERR, "Error $code: $message\n");
         exit(-1);
     }
-
 
     /**
      * Create an edit field for inclusion on a form
@@ -251,7 +262,6 @@
         return $out;
     }
 
-
     /**
      * Convert a variable into a javascript object notation
      *
@@ -267,5 +277,4 @@
         // that's why we have @ here
         return @json_encode($input);
     }
-
 }

--
Gitblit v1.9.1