jenkins-bot has submitted this change and it was merged.

Change subject: Redirect to correct protocol in SUL2
......................................................................


Redirect to correct protocol in SUL2

Handles situations where:
* The wiki has wgSecureLogin enabled, but the user opts-out of SSL
* The user logs in over http

bug: 50334
Change-Id: I69de057244422c403cde50b9d1755e1dd55e1258
---
M CentralAuthHooks.php
M CentralAuthUser.php
M specials/SpecialCentralAutoLogin.php
M specials/SpecialCentralLogin.php
4 files changed, 97 insertions(+), 49 deletions(-)

Approvals:
  Anomie: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/CentralAuthHooks.php b/CentralAuthHooks.php
index 9f6bbab..2e40bfa 100644
--- a/CentralAuthHooks.php
+++ b/CentralAuthHooks.php
@@ -379,7 +379,7 @@
         * @return bool
         */
        protected static function doCentralLoginRedirect( User $user, 
CentralAuthUser $centralUser, &$inject_html ) {
-               global $wgCentralAuthLoginWiki, $wgMemc;
+               global $wgCentralAuthLoginWiki, $wgMemc, $wgSecureLogin;
 
                $context = RequestContext::getMain();
                $request = $context->getRequest();
@@ -404,6 +404,12 @@
                                $returnToQuery = '';
                        }
 
+                       // Determine the final protocol of page, after login
+                       $finalProto = $request->detectProtocol();
+                       if ( $wgSecureLogin ) {
+                               $finalProto = $request->getCheck( 
'wpStickHTTPS' ) ? 'https' : 'http';
+                       }
+
                        // When POSTs triggered from Special:CentralLogin/start 
are sent back to
                        // this wiki, the token will be checked to see if it 
was signed with this.
                        // This is needed as Special:CentralLogin/start only 
takes a token argument
@@ -415,7 +421,8 @@
                                'remember'      => $request->getCheck( 
'wpRemember' ),
                                'returnTo'      => $returnTo,
                                'returnToQuery' => $returnToQuery,
-                               'stickHTTPS'    => $request->getCheck( 
'wpStickHTTPS' )
+                               'stickHTTPS'    => $request->getCheck( 
'wpStickHTTPS' ),
+                               'finalProto'    => $finalProto
                        );
 
                        // Create a new token to pass to 
Special:CentralLogin/start (central wiki)
@@ -425,7 +432,9 @@
                                'secret'        => $secret,
                                'name'          => $centralUser->getName(),
                                'guid'          => $centralUser->getId(),
-                               'wikiId'        => wfWikiId()
+                               'wikiId'        => wfWikiId(),
+                               'finalProto'    => $finalProto,
+                               'currentProto'  => $request->detectProtocol()
                        );
                        $wgMemc->set( $key, $data, 60 );
 
diff --git a/CentralAuthUser.php b/CentralAuthUser.php
index 6d5e374..33821ab 100644
--- a/CentralAuthUser.php
+++ b/CentralAuthUser.php
@@ -1970,9 +1970,13 @@
         * @param  $name
         * @param  $value
         * @param  $exp
+        * @param bool $secure
+        *  true: Force setting the secure attribute when setting the cookie
+        *  false: Force NOT setting the secure attribute when setting the 
cookie
+        *  null (default): Use the default ($wgCookieSecure) to set the secure 
attribute
         * @return void
         */
-       static function setCookie( $name, $value, $exp = -1 ) {
+       static function setCookie( $name, $value, $exp = -1, $secure = null ) {
                global $wgCentralAuthCookiePrefix, $wgCentralAuthCookieDomain, 
$wgCookieSecure,
                        $wgCookieExpiration, $wgCookieHttpOnly;
 
@@ -1991,12 +1995,19 @@
                        // Relative expiry
                        $exp += time();
                }
+
+               // Set the cookie encryption requirements
+               $secureCookie = $secure;
+               if ( is_null( $secure ) ) {
+                       $secureCookie = $wgCookieSecure;
+               }
+
                setcookie( $wgCentralAuthCookiePrefix . $name,
                        $value,
                        $exp,
                        '/',
                        $wgCentralAuthCookieDomain,
-                       $wgCookieSecure,
+                       $secureCookie,
                        $wgCookieHttpOnly );
        }
 
@@ -2022,9 +2033,13 @@
         *
         * @param $remember Bool|User
         * @param $refreshId Bool|string
+        * @param bool $secure
+        *  true: Force setting the secure attribute when setting the cookie
+        *  false: Force NOT setting the secure attribute when setting the 
cookie
+        *  null (default): Use the default ($wgCookieSecure) to set the secure 
attribute
         * @return string Session ID
         */
-       function setGlobalCookies( $remember = false, $refreshId = false ) {
+       function setGlobalCookies( $remember = false, $refreshId = false, 
$secure = null ) {
                if ( $remember instanceof User ) {
                        // Older code passed a user object here. Be kind and do 
what they meant to do.
                        $remember = $remember->getOption( 'rememberpassword' );
@@ -2032,18 +2047,18 @@
 
                $session = array();
                $session['user'] = $this->mName;
-               self::setCookie( 'User', $this->mName );
+               self::setCookie( 'User', $this->mName, -1, $secure );
                $session['token'] = $this->getAuthToken();
                $session['expiry'] = time() + 86400;
                $session['auto-create-blacklist'] = array();
 
                if ( $remember ) {
-                       self::setCookie( 'Token', $this->getAuthToken() );
+                       self::setCookie( 'Token', $this->getAuthToken(), -1, 
$secure );
                } else {
                        $this->clearCookie( 'Token' );
                }
 
-               return self::setSession( $session, $refreshId );
+               return self::setSession( $session, $refreshId, $secure );
        }
 
        /**
@@ -2363,16 +2378,20 @@
         *
         * @param $data Array
         * @param $refreshId Bool|String
+        * @param bool $secure
+        *  true: Force setting the secure attribute when setting the cookie
+        *  false: Force NOT setting the secure attribute when setting the 
cookie
+        *  null (default): Use the default ($wgCookieSecure) to set the secure 
attribute
         * @return string Session ID
         */
-       static function setSession( $data, $refreshId = false ) {
+       static function setSession( $data, $refreshId = false, $secure = null ) 
{
                global $wgCentralAuthCookies, $wgCentralAuthCookiePrefix, 
$wgMemc;
                if ( !$wgCentralAuthCookies ) {
                        return null;
                }
                if ( $refreshId || !isset( $_COOKIE[$wgCentralAuthCookiePrefix 
. 'Session'] ) ) {
                        $id = is_string( $refreshId ) ? $refreshId : 
MWCryptRand::generateHex( 32 );
-                       self::setCookie( 'Session', $id, 0 );
+                       self::setCookie( 'Session', $id, 0, $secure );
                } else {
                        $id =  $_COOKIE[$wgCentralAuthCookiePrefix . 'Session'];
                }
diff --git a/specials/SpecialCentralAutoLogin.php 
b/specials/SpecialCentralAutoLogin.php
index 5e86505..7e61f03 100644
--- a/specials/SpecialCentralAutoLogin.php
+++ b/specials/SpecialCentralAutoLogin.php
@@ -138,10 +138,14 @@
                                return;
                        }
 
+                       // Notify the attached wiki if cookies need to be 
insecure
+                       $centralSession = $centralUser->getSession();
+
                        // Write info for session creation into memc
                        $memcData += array(
                                'userName' => $centralUser->getName(),
                                'token' => $centralUser->getAuthToken(),
+                               'cookieProto' => $centralSession['finalProto'],
                        );
                        $wgMemc->set( $key, $memcData, 60 );
 
@@ -208,8 +212,13 @@
                                $_SESSION = $tmp;
                        }
 
-                       // Set central cookies too
-                       $centralUser->setGlobalCookies( false );
+                       // Set central cookies too, with a refreshed sessionid. 
Also, check if we
+                       // need to override the default cookie security policy
+                       $secureCookie = null;
+                       if ( $memcData['cookieProto'] == 'http' ) {
+                               $secureCookie = false;
+                       }
+                       $centralUser->setGlobalCookies( false, true, 
$secureCookie );
 
                        // Now, figure out how to report this back to the user.
 
diff --git a/specials/SpecialCentralLogin.php b/specials/SpecialCentralLogin.php
index 370fccd..8fb04f3 100644
--- a/specials/SpecialCentralLogin.php
+++ b/specials/SpecialCentralLogin.php
@@ -75,14 +75,21 @@
                // Delete the temporary token
                $wgMemc->delete( $key );
 
+               // Determine if we can use the default cookie security, or if 
we need
+               // to override it to insecure
+               $secureCookie = null;
+               if ( $info['finalProto'] == 'http' ) {
+                       $secureCookie = false;
+               }
+
                // Start an unusable placeholder session stub and send a cookie.
                // The cookie will not be usable until the session is unstubbed.
                // Note: the "remember me" token must be dealt with later 
(security).
                $newSessionId = CentralAuthUser::setSession( array(
                        'pending_name' => $centralUser->getName(),
                        'pending_guid' => $centralUser->getId()
-               ) );
-               CentralAuthUser::setCookie( 'User', $centralUser->getName() );
+               ), true, $secureCookie );
+               CentralAuthUser::setCookie( 'User', $centralUser->getName(), 
-1, $secureCookie );
 
                // Create a new token to pass to Special:CentralLogin/complete 
(local wiki).
                $token = MWCryptRand::generateHex( 32 );
@@ -96,9 +103,13 @@
                $wiki = WikiMap::getWiki( $info['wikiId'] );
                // Use WikiReference::getFullUrl(), returns a protocol-relative 
URL if needed
                $url = $wiki->getFullUrl( 'Special:CentralLogin/complete' );
+               // Ensure $url really is proto relative, and prepend the 
protocol of the original
+               // login. If the local wiki is using wgSecureLogin, it will be 
https.
+               $url = strstr( $url, '//' );
+               $url = $info['currentProto'] . ':' . $url;
 
                if ( $wgCentralAuthSilentLogin ) {
-                       $this->getOutput()->redirect( // expands to 
PROTO_CURRENT
+                       $this->getOutput()->redirect( // expands to 
PROTO_CURRENT if $url doesn't have protocol
                                wfAppendQuery( $url, array( 'token' => $token ) 
)
                        );
                } else {
@@ -170,7 +181,20 @@
                // Fully initialize the stub central user session and send the 
domain cookie.
                // This lets User::loadFromSession to initialize the User 
object from the local
                // session now that the global session is complete.
-               $centralUser->setGlobalCookies( $_SESSION[$skey]['remember'], 
$info['sessionId'] );
+               // Without $wgSecureLogin, we should be on the correct protocol 
now, and we use the
+               // default cookie security. With $wgSecureLogin, we use the 
stickHTTPS checkbox.
+               $secureCookie = null;
+               if ( $wgSecureLogin && !$attempt['stickHTTPS'] ) {
+                       $secureCookie = false;
+               }
+               $centralUser->setGlobalCookies( $_SESSION[$skey]['remember'], 
$info['sessionId'], $secureCookie );
+
+               //Add to the session the target protocol of the login, so 
autologin can use it
+               $centralSessionKey = CentralAuthUser::memcKey( 'session', 
$info['sessionId'] );
+               $centralSession = $wgMemc->get( $centralSessionKey );
+               $centralSession['finalProto'] = $attempt['finalProto'];
+               $wgMemc->set( $centralSessionKey, $centralSession, 86400 );
+
                // Remove the "current login attempt" information
                $request->setSessionData( $skey, null );
 
@@ -180,40 +204,27 @@
                // which is needed or the personal links will be wrong.
                $this->getContext()->setUser( $user );
 
-               if ( $wgSecureLogin
-                       && WebRequest::detectProtocol() === 'https' && 
!$attempt['stickHTTPS'] )
-               {
-                       // The user wants an HTTP redirect link (as well as 
other links) and
-                       // this is on HTTPS, so send a redirect to the success 
page in HTTP.
-                       $query = array(
-                               'returnto'      => $attempt['returnTo'],
-                               'returntoquery' => $attempt['returnToQuery']
-                       );
-                       $url = $this->getFullTitle()->getFullUrl( $query, 
false, PROTO_HTTP );
-                       $this->getOutput()->redirect( $url );
+               if ( $wgCentralAuthSilentLogin ) {
+                       // Mark the session to include the edge login imgs on 
the next pageview
+                       $request->setSessionData( 'CentralAuthDoEdgeLogin', 
true );
+
+                       // Show the login success page
+                       $form = new LoginForm( new FauxRequest() );
+                       $form->showReturnToPage( 'successredirect',
+                               $attempt['returnTo'], 
$attempt['returnToQuery'], $attempt['stickHTTPS'] );
+                       $this->getOutput()->setPageTitle( $this->msg( 
'centralloginsuccesful' ) );
                } else {
-                       if ( $wgCentralAuthSilentLogin ) {
-                               // Mark the session to include the edge login 
imgs on the next pageview
-                               $request->setSessionData( 
'CentralAuthDoEdgeLogin', true );
+                       // Show the login success page
+                       $form = new LoginForm( new FauxRequest() );
+                       $form->showReturnToPage( 'success',
+                               $attempt['returnTo'], 
$attempt['returnToQuery'], $attempt['stickHTTPS'] );
+                       $this->getOutput()->setPageTitle( $this->msg( 
'centralloginsuccesful' ) );
 
-                               // Show the login success page
-                               $form = new LoginForm( new FauxRequest() );
-                               $form->showReturnToPage( 'successredirect',
-                                       $attempt['returnTo'], 
$attempt['returnToQuery'], $attempt['stickHTTPS'] );
-                               $this->getOutput()->setPageTitle( $this->msg( 
'centralloginsuccesful' ) );
-                       } else {
-                               // Show the login success page
-                               $form = new LoginForm( new FauxRequest() );
-                               $form->showReturnToPage( 'success',
-                                       $attempt['returnTo'], 
$attempt['returnToQuery'], $attempt['stickHTTPS'] );
-                               $this->getOutput()->setPageTitle( $this->msg( 
'centralloginsuccesful' ) );
-
-                               // Show HTML to trigger cross-domain cookies.
-                               // This will trigger filling in the "remember 
me" token cookie on the
-                               // central wiki, which can only be done once 
authorization is completed.
-                               $this->getOutput()->addHtml(
-                                       
CentralAuthHooks::getDomainAutoLoginHtml( $user, $centralUser ) );
-                       }
+                       // Show HTML to trigger cross-domain cookies.
+                       // This will trigger filling in the "remember me" token 
cookie on the
+                       // central wiki, which can only be done once 
authorization is completed.
+                       $this->getOutput()->addHtml(
+                               CentralAuthHooks::getDomainAutoLoginHtml( 
$user, $centralUser ) );
                }
        }
 

-- 
To view, visit https://gerrit.wikimedia.org/r/72657
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I69de057244422c403cde50b9d1755e1dd55e1258
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/CentralAuth
Gerrit-Branch: master
Gerrit-Owner: CSteipp <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: CSteipp <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to