diff --git a/CHANGELOG b/CHANGELOG index 39be19cce..cd3974fb2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Support ALLOW-FROM in x_frame_options (#5122) - Allow to omit a subject when sending an email (#5068) - Warn about too many disclosed recipients in composed email [max_disclosed_recipients] (#5132) - identity_select: Support Received header (#5085) diff --git a/config/defaults.inc.php b/config/defaults.inc.php index 4207f0b28..9a8839975 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -468,7 +468,8 @@ $config['proxy_whitelist'] = array(); $config['referer_check'] = false; // X-Frame-Options HTTP header value sent to prevent from Clickjacking. -// Possible values: sameorigin|deny. Set to false in order to disable sending them +// Possible values: sameorigin|deny|allow-from . +// Set to false in order to disable sending the header. $config['x_frame_options'] = 'sameorigin'; // This key is used for encrypting purposes, like storing of imap password diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php index 9847f2713..583ee2eb2 100644 --- a/program/include/rcmail_output_html.php +++ b/program/include/rcmail_output_html.php @@ -529,8 +529,10 @@ EOF; // allow (legal) iframe content to be loaded $iframe = $this->framed || $this->env['framed']; - if (!headers_sent() && $iframe && $this->app->config->get('x_frame_options', 'sameorigin') === 'deny') { - header('X-Frame-Options: sameorigin', true); + if (!headers_sent() && $iframe && ($xopt = $this->app->config->get('x_frame_options', 'sameorigin'))) { + if (strtolower($xopt) != 'sameorigin') { + header('X-Frame-Options: sameorigin', true); + } } // call super method diff --git a/program/js/app.js b/program/js/app.js index 5cbff6e27..84ad638b7 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -174,11 +174,13 @@ function rcube_webmail() this.gui_objects[n] = rcube_find_object(this.gui_objects[n]); // clickjacking protection - if (this.env.x_frame_options) { + if (n = this.env.x_frame_options) { try { // bust frame if not allowed - if (this.env.x_frame_options == 'deny' && top.location.href != self.location.href) + if (n.toLowerCase() == 'deny' && top.location.href != self.location.href) top.location.href = self.location.href; + else if (/^allow-from[\s\t]+(.+)$/i.test(n) && RegExp.$1.indexOf(top.location.origin) != 0) + throw 1; else if (top.location.hostname != self.location.hostname) throw 1; } catch (e) {