Index: branches/REL1_15/phase3/includes/specials/SpecialUserlogin.php |
— | — | @@ -69,7 +69,7 @@ |
70 | 70 | $this->mRemember = $request->getCheck( 'wpRemember' ); |
71 | 71 | $this->mLanguage = $request->getText( 'uselang' ); |
72 | 72 | $this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' ); |
73 | | - $this->mToken = $request->getVal( 'wpLoginToken' ); |
| 73 | + $this->mToken = ($this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' ); |
74 | 74 | |
75 | 75 | if ( $wgRedirectOnLogin ) { |
76 | 76 | $this->mReturnTo = $wgRedirectOnLogin; |
— | — | @@ -246,6 +246,25 @@ |
247 | 247 | return false; |
248 | 248 | } |
249 | 249 | |
| 250 | + # Request forgery checks. |
| 251 | + if ( !self::getCreateaccountToken() ) { |
| 252 | + self::setCreateaccountToken(); |
| 253 | + $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); |
| 254 | + return false; |
| 255 | + } |
| 256 | + |
| 257 | + # The user didn't pass a createaccount token |
| 258 | + if ( !$this->mToken ) { |
| 259 | + $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); |
| 260 | + return false; |
| 261 | + } |
| 262 | + |
| 263 | + # Validate the createaccount token |
| 264 | + if ( $this->mToken !== self::getCreateaccountToken() ) { |
| 265 | + $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); |
| 266 | + return false; |
| 267 | + } |
| 268 | + |
250 | 269 | # Check permissions |
251 | 270 | if ( !$wgUser->isAllowed( 'createaccount' ) ) { |
252 | 271 | $this->userNotPrivilegedMessage(); |
— | — | @@ -260,7 +279,7 @@ |
261 | 280 | $wgUser->inSorbsBlacklist( $ip ) ) |
262 | 281 | { |
263 | 282 | $this->mainLoginForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . htmlspecialchars( $ip ) . ')' ); |
264 | | - return; |
| 283 | + return false; |
265 | 284 | } |
266 | 285 | |
267 | 286 | # Now create a dummy user ($u) and check if it is valid |
— | — | @@ -336,6 +355,7 @@ |
337 | 356 | return false; |
338 | 357 | } |
339 | 358 | |
| 359 | + self::clearCreateaccountToken(); |
340 | 360 | return $this->initUser( $u, false ); |
341 | 361 | } |
342 | 362 | |
— | — | @@ -638,13 +658,26 @@ |
639 | 659 | return; |
640 | 660 | } |
641 | 661 | |
642 | | - # Check against blocked IPs |
643 | | - # fixme -- should we not? |
| 662 | + # Check against blocked IPs so blocked users can't flood admins |
| 663 | + # with password resets |
644 | 664 | if( $wgUser->isBlocked() ) { |
645 | 665 | $this->mainLoginForm( wfMsg( 'blocked-mailpassword' ) ); |
646 | 666 | return; |
647 | 667 | } |
648 | 668 | |
| 669 | + # If the user doesn't have a login token yet, set one. |
| 670 | + if ( !self::getLoginToken() ) { |
| 671 | + self::setLoginToken(); |
| 672 | + $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); |
| 673 | + return; |
| 674 | + } |
| 675 | + |
| 676 | + # If the user didn't pass a login token, tell them we need one |
| 677 | + if ( !$this->mToken ) { |
| 678 | + $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); |
| 679 | + return; |
| 680 | + } |
| 681 | + |
649 | 682 | # Check against the rate limiter |
650 | 683 | if( $wgUser->pingLimiter( 'mailpassword' ) ) { |
651 | 684 | $wgOut->rateLimited(); |
— | — | @@ -665,6 +698,12 @@ |
666 | 699 | return; |
667 | 700 | } |
668 | 701 | |
| 702 | + # Validate the login token |
| 703 | + if ( $this->mToken !== self::getLoginToken() ) { |
| 704 | + $this->mainLoginForm( wfMsg( 'sessionfailure' ) ); |
| 705 | + return; |
| 706 | + } |
| 707 | + |
669 | 708 | # Check against password throttle |
670 | 709 | if ( $u->isPasswordReminderThrottled() ) { |
671 | 710 | global $wgPasswordReminderResendTime; |
— | — | @@ -680,6 +719,7 @@ |
681 | 720 | $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) ); |
682 | 721 | } else { |
683 | 722 | $this->mainLoginForm( wfMsg( 'passwordsent', $u->getName() ), 'success' ); |
| 723 | + self::clearLoginToken(); |
684 | 724 | } |
685 | 725 | } |
686 | 726 | |
— | — | @@ -911,11 +951,18 @@ |
912 | 952 | $template->set( 'canremember', ( $wgCookieExpiration > 0 ) ); |
913 | 953 | $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember ); |
914 | 954 | |
915 | | - if ( !self::getLoginToken() ) { |
916 | | - self::setLoginToken(); |
| 955 | + if ( $this->mType == 'signup' ) { |
| 956 | + if ( !self::getCreateaccountToken() ) { |
| 957 | + self::setCreateaccountToken(); |
| 958 | + } |
| 959 | + $template->set( 'token', self::getCreateaccountToken() ); |
| 960 | + } else { |
| 961 | + if ( !self::getLoginToken() ) { |
| 962 | + self::setLoginToken(); |
| 963 | + } |
| 964 | + $template->set( 'token', self::getLoginToken() ); |
917 | 965 | } |
918 | | - $template->set( 'token', self::getLoginToken() ); |
919 | | - |
| 966 | + |
920 | 967 | # Prepare language selection links as needed |
921 | 968 | if( $wgLoginLanguageSelector ) { |
922 | 969 | $template->set( 'languages', $this->makeLanguageSelector() ); |
— | — | @@ -974,7 +1021,7 @@ |
975 | 1022 | } |
976 | 1023 | |
977 | 1024 | /** |
978 | | - * Generate a new login token and attach it to the current session |
| 1025 | + * Randomly generate a new login token and attach it to the current session |
979 | 1026 | */ |
980 | 1027 | public static function setLoginToken() { |
981 | 1028 | global $wgRequest; |
— | — | @@ -986,12 +1033,36 @@ |
987 | 1034 | /** |
988 | 1035 | * Remove any login token attached to the current session |
989 | 1036 | */ |
990 | | - public static function clearLoginToken() { |
| 1037 | + public static function clearLoginToken() { |
991 | 1038 | global $wgRequest; |
992 | 1039 | $wgRequest->setSessionData( 'wsLoginToken', null ); |
993 | 1040 | } |
994 | 1041 | |
995 | 1042 | /** |
| 1043 | + * Get the createaccount token from the current session |
| 1044 | + */ |
| 1045 | + public static function getCreateaccountToken() { |
| 1046 | + global $wgRequest; |
| 1047 | + return $wgRequest->getSessionData( 'wsCreateaccountToken' ); |
| 1048 | + } |
| 1049 | + |
| 1050 | + /** |
| 1051 | + * Randomly generate a new createaccount token and attach it to the current session |
| 1052 | + */ |
| 1053 | + public static function setCreateaccountToken() { |
| 1054 | + global $wgRequest; |
| 1055 | + $wgRequest->setSessionData( 'wsCreateaccountToken', User::generateToken() ); |
| 1056 | + } |
| 1057 | + |
| 1058 | + /** |
| 1059 | + * Remove any createaccount token attached to the current session |
| 1060 | + */ |
| 1061 | + public static function clearCreateaccountToken() { |
| 1062 | + global $wgRequest; |
| 1063 | + $wgRequest->setSessionData( 'wsCreateaccountToken', null ); |
| 1064 | + } |
| 1065 | + |
| 1066 | + /** |
996 | 1067 | * @private |
997 | 1068 | */ |
998 | 1069 | function cookieRedirectCheck( $type ) { |
Index: branches/REL1_15/phase3/includes/templates/Userlogin.php |
— | — | @@ -268,6 +268,7 @@ |
269 | 269 | </tr> |
270 | 270 | </table> |
271 | 271 | <?php if( @$this->haveData( 'uselang' ) ) { ?><input type="hidden" name="uselang" value="<?php $this->text( 'uselang' ); ?>" /><?php } ?> |
| 272 | +<?php if( @$this->haveData( 'token' ) ) { ?><input type="hidden" name="wpCreateaccountToken" value="<?php $this->text( 'token' ); ?>" /><?php } ?> |
272 | 273 | </form> |
273 | 274 | </div> |
274 | 275 | <div id="signupend"><?php $this->msgWiki( 'signupend' ); ?></div> |