diff --git a/include/class.config.php b/include/class.config.php index 32f5ca702feb2855e52d437ea8d4bbb625354ded..0f046d345ec939b647f68242be329730832b4267 100644 --- a/include/class.config.php +++ b/include/class.config.php @@ -429,6 +429,10 @@ class OsticketConfig extends Config { return $this->get('enable_richtext'); } + function getAllowIframes() { + return str_replace(array(', ', ','), array(' ', ' '), $this->get('allow_iframes')) ?: 'self'; + } + function isAvatarsEnabled() { return $this->get('enable_avatars'); } @@ -1121,6 +1125,7 @@ class OsticketConfig extends Config { $f['helpdesk_title']=array('type'=>'string', 'required'=>1, 'error'=>__('Helpdesk title is required')); $f['default_dept_id']=array('type'=>'int', 'required'=>1, 'error'=>__('Default Department is required')); $f['autolock_minutes']=array('type'=>'int', 'required'=>1, 'error'=>__('Enter lock time in minutes')); + $f['allow_iframes']=array('type'=>'cs-domain', 'required'=>0, 'error'=>__('Enter comma separated list of domains')); //Date & Time Options $f['time_format']=array('type'=>'string', 'required'=>1, 'error'=>__('Time format is required')); $f['date_format']=array('type'=>'string', 'required'=>1, 'error'=>__('Date format is required')); @@ -1179,6 +1184,7 @@ class OsticketConfig extends Config { 'enable_avatars' => isset($vars['enable_avatars']) ? 1 : 0, 'enable_richtext' => isset($vars['enable_richtext']) ? 1 : 0, 'files_req_auth' => isset($vars['files_req_auth']) ? 1 : 0, + 'allow_iframes' => Format::sanitize($vars['allow_iframes']), )); } diff --git a/include/class.validator.php b/include/class.validator.php index 14be7ccaf005423bf34c395aa375c04227e9671e..388d00ac929ccdc45a78325cae549329db761280 100644 --- a/include/class.validator.php +++ b/include/class.validator.php @@ -123,6 +123,14 @@ class Validator { if(!is_numeric($this->input[$k]) || (strlen($this->input[$k])!=5)) $this->errors[$k]=$field['error']; break; + case 'cs-domain': // Comma separated list of domains + if($values=explode(',', $this->input[$k])) + foreach($values as $v) + if(!preg_match_all( + '/^(https?:\/\/)?((\*\.|\w+\.)?[\w-]+(\.[a-zA-Z]+)?(:([0-9]+|\*))?)+$/', + ltrim($v))) + $this->errors[$k]=$field['error']; + break; default://If param type is not set...or handle..error out... $this->errors[$k]=$field['error'].' '.__('(type not set)'); endswitch; diff --git a/include/client/header.inc.php b/include/client/header.inc.php index 0d66f67537f3b8ac5c7e8cd2336281ad5bcdf82e..8c248b158d2631a577b1bbe4835961fd26228893 100644 --- a/include/client/header.inc.php +++ b/include/client/header.inc.php @@ -6,7 +6,7 @@ $signin_url = ROOT_PATH . "login.php" $signout_url = ROOT_PATH . "logout.php?auth=".$ost->getLinkToken(); header("Content-Type: text/html; charset=UTF-8"); -header("X-Frame-Options: SAMEORIGIN"); +header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';"); if (($lang = Internationalization::getCurrentLanguage())) { $langs = array_unique(array($lang, $cfg->getPrimaryLanguage())); $langs = Internationalization::rfc1766($langs); diff --git a/include/i18n/en_US/help/tips/settings.system.yaml b/include/i18n/en_US/help/tips/settings.system.yaml index 28b069775ba6e2a8b8eafc4c93ae94fc96a002e6..56e39e2bf7481257be419dd20ef45b4bf246ef6b 100644 --- a/include/i18n/en_US/help/tips/settings.system.yaml +++ b/include/i18n/en_US/help/tips/settings.system.yaml @@ -93,6 +93,20 @@ collision_avoidance: <br><br> Enter <span class="doc-desc-opt">0</span> to disable the lockout feature. +allow_iframes: + title: Allow iFrames + content: > + Enter comma separated list of domains for the system to be framed + in. If left empty, the system will default to 'self'. This accepts + domain wildcards, HTTP/HTTPS URL scheme, and port numbers. + <br><br> + <b>Example:</b> + <br> + https://domain.tld, sub.domain.tld:443, http://*.domain.tld + links: + - title: Syntax Information (host-source) + href: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors#Sources" + # Date and time options date_time_options: title: Date & Time Options diff --git a/include/staff/header.inc.php b/include/staff/header.inc.php index ebd31bfb05bb1fa216cdd4a60d12cee1fd8c6247..4de7ccd8fadec4164008912e31e336aba89988ba 100644 --- a/include/staff/header.inc.php +++ b/include/staff/header.inc.php @@ -1,6 +1,6 @@ <?php header("Content-Type: text/html; charset=UTF-8"); -header("X-Frame-Options: SAMEORIGIN"); +header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';"); $title = ($ost && ($title=$ost->getPageTitle())) ? $title : ('osTicket :: '.__('Staff Control Panel')); diff --git a/include/staff/login.header.php b/include/staff/login.header.php index 2a4fcdbb6d234d0ffa434b838afcc065ec808e38..e1b1b3a5a242a32e50690713beda7615eae3a039 100644 --- a/include/staff/login.header.php +++ b/include/staff/login.header.php @@ -1,6 +1,6 @@ <?php defined('OSTSCPINC') or die('Invalid path'); -header("X-Frame-Options: SAMEORIGIN"); +header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';"); ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> diff --git a/include/staff/settings-system.inc.php b/include/staff/settings-system.inc.php index 22502ed5e54dde3ae77d17c0c8aa15f4c7204b4b..37370df97eb22f4c450c41815ce13e2e08baef69 100644 --- a/include/staff/settings-system.inc.php +++ b/include/staff/settings-system.inc.php @@ -131,6 +131,13 @@ $gmtime = Misc::gmtime(); <i class="help-tip icon-question-sign" href="#enable_richtext"></i> </td> </tr> + <tr> + <td><?php echo __('Allow iFrames'); ?>:</td> + <td><input type="text" size="40" name="allow_iframes" value="<?php echo $config['allow_iframes']; ?>"> + <font class="error"> <?php echo $errors['allow_iframes']; ?></font> + <i class="help-tip icon-question-sign" href="#allow_iframes"></i> + </td> + </tr> <tr> <th colspan="2"> <em><b><?php echo __('Date and Time Options'); ?></b> diff --git a/setup/inc/header.inc.php b/setup/inc/header.inc.php index 57ceade2e12bad159d811881d8f8eea2022c22f7..0bfc0ec85edaa6b44a650a92ca7d00ff3b8d140d 100644 --- a/setup/inc/header.inc.php +++ b/setup/inc/header.inc.php @@ -1,4 +1,6 @@ -<?php header("X-Frame-Options: SAMEORIGIN"); ?> +<?php +header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';"); +?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html <?php