Core support for disabling HTTPS based on GeoIP
authorTim Starling <tstarling@wikimedia.org>
Wed, 21 Aug 2013 01:39:45 +0000 (11:39 +1000)
committerTim Starling <tstarling@wikimedia.org>
Wed, 21 Aug 2013 03:43:46 +0000 (13:43 +1000)
* Introduce a hook allowing automatic redirects to HTTPS to be
  disabled on the basis of client IP address.
* Make User::requiresHTTPS() return false if the client IP is
  blacklisted as such.
* On login, make the "stick HTTPS" option default to false if the
  client IP address is blacklisted as such.
* Do not redirect anonymous requests to HTTPS.
* If $wgSecureLogin is enabled, link to the HTTPS login page *via*
  the HTTP redirect, so that there is no need to vary the cache of
  anonymous page view HTML on client IP address.

Change-Id: Iaa9dd2108431b8c35e05db4bfe78a629018a003c

docs/hooks.txt
includes/GlobalFunctions.php
includes/SkinTemplate.php
includes/User.php
includes/Wiki.php
includes/specials/SpecialUserlogin.php

index e776d4c..1b44d14 100644 (file)
@@ -758,6 +758,12 @@ $user: the user who did the block (not the one being blocked)
 $isbn: ISBN to show information for
 $output: OutputPage object in use
 
+'CanIPUseHTTPS': Determine whether the client at a given source IP is likely
+to be able to access the wiki via HTTPS.
+$ip: The IP address in human-readable form
+&$canDo: This reference should be set to false if the client may not be able 
+to use HTTPS
+
 'CanonicalNamespaces': For extensions adding their own namespaces or altering
 the defaults.
 Note that if you need to specify namespace protection or content model for
index be4ec3e..dd23538 100644 (file)
@@ -3967,3 +3967,16 @@ function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
        wfProfileOut( __METHOD__ );
        return $bad;
 }
+
+/**
+ * Determine whether the client at a given source IP is likely to be able to 
+ * access the wiki via HTTPS. 
+ *
+ * @param string $ip The IPv4/6 address in the normal human-readable form
+ * @return boolean
+ */
+function wfCanIPUseHTTPS( $ip ) {
+       $canDo = true;
+       wfRunHooks( 'CanIPUseHTTPS', array( $ip, &$canDo ) );
+       return !!$canDo;
+}
index 69e551e..bb31bdf 100644 (file)
@@ -693,18 +693,15 @@ class SkinTemplate extends Skin {
                                : 'login';
                        $is_signup = $request->getText( 'type' ) == 'signup';
 
-                       # anonlogin & login are the same
-                       $proto = $wgSecureLogin ? PROTO_HTTPS : null;
-
                        $login_id = $this->showIPinHeader() ? 'anonlogin' : 'login';
                        $login_url = array(
                                'text' => $this->msg( $loginlink )->text(),
-                               'href' => self::makeSpecialUrl( 'Userlogin', $returnto, $proto ),
+                               'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
                                'active' => $title->isSpecial( 'Userlogin' ) && ( $loginlink == 'nav-login-createaccount' || !$is_signup ),
                        );
                        $createaccount_url = array(
                                'text' => $this->msg( 'createaccount' )->text(),
-                               'href' => self::makeSpecialUrl( 'Userlogin', "$returnto&type=signup", $proto ),
+                               'href' => self::makeSpecialUrl( 'Userlogin', "$returnto&type=signup" ),
                                'active' => $title->isSpecial( 'Userlogin' ) && $is_signup,
                        );
 
index 2923026..25b35b3 100644 (file)
@@ -2612,6 +2612,9 @@ class User {
                } else {
                        $https = $this->getBoolOption( 'prefershttps' );
                        wfRunHooks( 'UserRequiresHTTPS', array( $this, &$https ) );
+                       if ( $https ) {
+                               $https = wfCanIPUseHTTPS( $this->getRequest()->getIP() );
+                       }
                        return $https;
                }
        }
index 55805ba..6ac9341 100644 (file)
@@ -510,7 +510,10 @@ class MediaWiki {
                        (
                                $request->getCookie( 'forceHTTPS' ) ||
                                // Avoid checking the user and groups unless it's enabled.
-                               $this->context->getUser()->requiresHTTPS()
+                               (
+                                       $this->context->getUser()->isLoggedIn()
+                                       && $this->context->getUser()->requiresHTTPS()
+                               )
                        ) &&
                        $request->detectProtocol() == 'http'
                ) {
index 2081dd9..2fb1da7 100644 (file)
@@ -178,7 +178,7 @@ class LoginForm extends SpecialPage {
                                'wpStickHTTPS' => $this->mStickHTTPS
                        );
                        $url = $title->getFullURL( $query, false, PROTO_HTTPS );
-                       if ( $wgSecureLogin ) {
+                       if ( $wgSecureLogin && wfCanIPUseHTTPS( $this->getRequest()->getIP() ) ) {
                                $this->getOutput()->redirect( $url );
                                return;
                        } else {
@@ -1125,7 +1125,11 @@ class LoginForm extends SpecialPage {
                }
 
                // Decide if we default stickHTTPS on
-               if ( $wgSecureLoginDefaultHTTPS && $this->mAction != 'submitlogin' && !$this->mLoginattempt ) {
+               if ( $wgSecureLoginDefaultHTTPS 
+                       && $this->mAction != 'submitlogin' 
+                       && !$this->mLoginattempt
+                       && wfCanIPUseHTTPS( $this->getRequest()->getIP() ) )
+               {       
                        $this->mStickHTTPS = true;
                }