Seb35 has submitted this change and it was merged. Change subject: Version 1.0 ......................................................................
Version 1.0 Previous version in git was 0.1, but version 0.2 was available on www.mediawiki.org/wiki/Extension:HSTS - no feature added since 0.2, but more comments, wrapped in a class - from 0.1 to 0.2: two news config parameters to permit to sysadmins to force HSTS to anons and/or to users Change-Id: I4d972e944a420cb78e48b1449dd9d8f554322bb4 --- M HSTS.php 1 file changed, 128 insertions(+), 51 deletions(-) Approvals: Seb35: Verified; Looks good to me, approved diff --git a/HSTS.php b/HSTS.php index a64096c..7c2df35 100644 --- a/HSTS.php +++ b/HSTS.php @@ -3,8 +3,8 @@ /** * Extension enabling the HSTS on a MediaWiki website on a per-user basis * - * Note if you intend to activate HSTS on the whole website, it will be more efficient and robust - * to add it directly in the server configuration + * Note that if you intend to activate HSTS on the whole website, it will be + * more efficient and robust to add it directly in the server configuration. * * @file * @ingroup Extensions @@ -12,65 +12,142 @@ * @licence WTFPL 2.0 * / -/* Options */ -$wgDefaultUserOptions['hsts'] = 0; // Default value of HSTS for anonymous visitors and newly created accounts -$wgHSTSMaxAge = 30*86400; // max-age parameter for HSTS; can be either: - // - a number (canonical number of seconds before expiration of HSTS); or - // - a date when HSTS will expire (e.g. just before certificate expiration). - // Note that in the second case the header is dynamical, so you may want to - // configure accordingly your cache servers for a consistent user experience, - // particularly given the authoritative HSTS header is the last sent, even if shorter. -$wgHSTSIncludeSubdomains = false; // includeSubDomains parameter for HSTS; boolean +/* Check if we are being called directly */ +if ( !defined( 'MEDIAWIKI' ) ) { + die( 'This file is an extension to MediaWiki and thus not a valid entry point.' ); +} -/* Register hooks */ +/** + * CONFIGURATION + * These variables may be overridden in LocalSettings.php after you include the + * extension file. + */ +/** + * Mandatory HSTS for anonymous users + */ +$wgHSTSForAnons = false; + +/** + * Mandatory HSTS for logged-in users + */ +$wgHSTSForUsers = false; + +/** + * HSTS parameter max-age (time-to-live of the default-HTTPS protection) + * + * This can be either: + * - a number (canonical number of seconds before expiration of HSTS) + * (e.g. 3600 for one hour), or + * - a date when HSTS will expire (e.g. just before certificate expiration) + * (e.g. "2014-09-24T00:00:00Z" in ISO 8601 format, see wfTimestamp for + * other date formats). + * + * Note that in the second case the header is dynamical, so you may want to + * configure accordingly your cache servers for a consistent user experience, + * particularly given the authoritative HSTS header is the last sent, even + * if shorter. + */ +$wgHSTSMaxAge = 30*86400; + +/** + * HSTS parameter includeSubDomains (whether to include the default-HTTPS + * protection for subdomains of the visited website) + */ +$wgHSTSIncludeSubdomains = false; + +/** + * Default value of HSTS preference for logged-in users + * (only useful if $wgHSTSForUsers is false) + * 0 = opt-out + * 1 = opt-in + */ +$wgDefaultUserOptions['hsts'] = 0; + + +/** REGISTRATION */ $wgExtensionCredits['other'][] = array( - 'path' => __FILE__, - 'name' => 'HSTS', - 'author' => 'Seb35', - 'version' => '0.2.0', - 'url' => 'https://www.mediawiki.org/wiki/Extension:HSTS', - 'descriptionmsg' => 'hsts-desc', + 'path' => __FILE__, + 'name' => 'HSTS', + 'author' => 'Seb35', + 'version' => '1.0.0', + 'url' => 'https://www.mediawiki.org/wiki/Extension:HSTS', + 'descriptionmsg' => 'hsts-desc', ); -$dir = dirname( __FILE__ ) . '/'; +$wgAutoloadClasses['HSTSExtension'] = __DIR__ . '/HSTS.php'; + $wgMessagesDirs['HSTS'] = __DIR__ . '/i18n'; -$wgExtensionMessagesFiles['HSTS'] = $dir . 'HSTS.i18n.php'; +$wgExtensionMessagesFiles['HSTS'] = __DIR__ . '/HSTS.i18n.php'; -$wgHooks['GetPreferences'][] = 'HSTSPreference'; -$wgHooks['BeforePageDisplay'][] = 'HSTSAddHeader'; +$wgHooks['GetPreferences'][] = 'HSTSExtension::preference'; +$wgHooks['BeforePageDisplay'][] = 'HSTSExtension::addHeader'; -/* Code */ +/* CODE */ +class HSTSExtension { -function HSTSPreference( $user, &$preferences ) { - $preferences['hsts'] = array( - 'type' => 'toggle', - 'label-message' => 'hsts-tog', - 'section' => 'personal/info', - ); - return true; + /** + * Add the HSTS preference + * + * @var User $user Current user + * @var array $preferences Description of the preferences + * @return true + */ + function preference( $user, &$preferences ) { + + global $wgHSTSForUsers; + + // If HSTS is mandatory, do not display the choice + if( $wgHSTSForUsers ) return true; + + // Add the checkbox in the 'basic informations' section + $preferences['hsts'] = array( + 'type' => 'toggle', + 'label-message' => 'hsts-tog', + 'section' => 'personal/info' + ); + + return true; + } + + /** + * Add the STS header + * + * @var Output $output Output object + * @return true + */ + function addHeader( $output ) { + + global $wgHSTSForAnons, $wgHSTSForUsers, $wgHSTSIncludeSubdomains, $wgHSTSMaxAge; + + // Check if the user will get STS header + if( $output->getRequest()->detectProtocol() != 'https' ) return true; + if( $output->getUser()->isAnon() && !$wgHSTSForAnons ) return true; + if( $output->getUser()->isLoggedIn() && !$wgHSTSForUsers && !$output->getUser()->getOption('hsts') ) return true; + + // Compute the max-age property + $maxage = 0; + if( is_int( $wgHSTSMaxAge ) ) $maxage = max( $wgHSTSMaxAge, 0 ); + else { + $maxage = wfTimestamp( TS_UNIX, $wgHSTSMaxAge ); + if( $maxage !== false ) $maxage -= wfTimestamp(); + else { + wfDebug( '[HSTS] Bad value of the parameter $wgHSTSMaxAge: must be an integer or a date.' ); + return true; + } + if( $maxage < 0 ) { + wfDebug( '[HSTS] Expired date; HSTS has been lost for all users, apart if externally added in the server configuration.' ); + return true; + } + } + + // Output the header + $output->getRequest()->response()->header( 'Strict-Transport-Security: max-age='.$maxage.($wgHSTSIncludeSubdomains?'; includeSubDomains':'') ); + wfDebug( '[HSTS] Strict-Transport-Security: max-age='.$maxage.($wgHSTSIncludeSubdomains?'; includeSubDomains':'') ); + + return true; + } } -function HSTSAddHeader( $output ) { - global $wgHSTSIncludeSubdomains, $wgHSTSMaxAge; - if( $output->getRequest()->detectProtocol() != 'https' || !$output->getUser()->getOption( 'hsts' ) ) return true; - $maxage = 0; - if( is_int( $wgHSTSMaxAge ) ) $maxage = max($wgHSTSMaxAge,0); - else { - $maxage = wfTimestamp( TS_UNIX, $wgHSTSMaxAge ); - if( $maxage !== false ) $maxage -= wfTimestamp(); - else { - wfDebug( '[HSTS] Bad value of the parameter $wgHSTSMaxAge: must be an integer or a date.' ); - return true; - } - if( $maxage < 0 ) { - wfDebug( '[HSTS] Expired date; HSTS has been lost for all users, apart if externally added in the server configuration.' ); - return true; - } - } - $output->getRequest()->response()->header( 'Strict-Transport-Security: max-age='.$maxage.($wgHSTSIncludeSubdomains?'; includeSubDomains':'') ); - wfDebug( '[HSTS] Strict-Transport-Security: max-age='.$maxage.($wgHSTSIncludeSubdomains?'; includeSubDomains':'') ); - return true; -} -- To view, visit https://gerrit.wikimedia.org/r/160022 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I4d972e944a420cb78e48b1449dd9d8f554322bb4 Gerrit-PatchSet: 3 Gerrit-Project: mediawiki/extensions/HSTS Gerrit-Branch: master Gerrit-Owner: Seb35 <seb35wikipe...@gmail.com> Gerrit-Reviewer: Seb35 <seb35wikipe...@gmail.com> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits