1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/
namespace MediaWiki\Session;
use MediaWiki\Request\WebRequest;
use MediaWiki\User\LoggedOutEditToken;
/**
* Stores and matches CSRF tokens belonging to a given session user.
* @since 1.37
* @package MediaWiki\Session
*/
class CsrfTokenSet {
/**
* @var string default name for the form field to place the token in.
*/
public const DEFAULT_FIELD_NAME = 'wpEditToken';
private WebRequest $request;
/**
* @param WebRequest $request
*/
public function __construct( WebRequest $request ) {
$this->request = $request;
}
/**
* Initialize (if necessary) and return a current user CSRF token
* value which can be used in edit forms to show that the user's
* login credentials aren't being hijacked with a foreign form
* submission.
*
* The $salt for 'edit' and 'csrf' tokens is the default (empty string).
*
* @param string|string[] $salt Optional function-specific data for hashing
* @return Token
* @since 1.37
*/
public function getToken( $salt = '' ): Token {
$session = $this->request->getSession();
if ( !$session->getUser()->isRegistered() ) {
return new LoggedOutEditToken();
}
return $session->getToken( $salt );
}
/**
* Check if a request contains a value named $valueName with the token value
* stored in the session.
*
* @param string $fieldName
* @param string|string[] $salt
* @return bool
* @since 1.37
* @see self::matchCSRFToken
*/
public function matchTokenField(
string $fieldName = self::DEFAULT_FIELD_NAME,
$salt = ''
): bool {
return $this->matchToken( $this->request->getVal( $fieldName ), $salt );
}
/**
* Check if a value matches with the token value stored in the session.
* A match should confirm that the form was submitted from the user's own
* login session, not a form submission from a third-party site.
*
* @param string|null $value
* @param string|string[] $salt
* @return bool
* @since 1.37
*/
public function matchToken(
?string $value,
$salt = ''
): bool {
if ( !$value ) {
return false;
}
$session = $this->request->getSession();
// It's expensive to generate a new registered user token, so take a shortcut.
// Anon tokens are cheap and all the same, so we can afford to generate one just to match.
if ( $session->getUser()->isRegistered() && !$session->hasToken() ) {
return false;
}
return $this->getToken( $salt )->match( $value );
}
}
|