X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FBlock.php;h=66b9ff02d5ac60de90d5a050046f2a029b9e5650;hb=660446b78eb8318f0030750b4f955f847eb99a80;hp=792bcd9320329f8236827d9998ef1cead69e25cc;hpb=f9e21f91e459c40fed6d8f2e76cccbce07e2ba1b;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Block.php b/includes/Block.php index 792bcd9320..66b9ff02d5 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -765,8 +765,10 @@ class Block { return false; } + // Avoid PHP 7.1 warning of passing $this by reference + $block = $this; # Allow hooks to cancel the autoblock. - if ( !Hooks::run( 'AbortAutoblock', [ $autoblockIP, &$this ] ) ) { + if ( !Hooks::run( 'AbortAutoblock', [ $autoblockIP, &$block ] ) ) { wfDebug( "Autoblock aborted by hook.\n" ); return false; } @@ -1446,8 +1448,7 @@ class Block { /** * Set the 'BlockID' cookie to this block's ID and expiry time. The cookie's expiry will be - * the same as the block's, unless it's greater than $wgCookieExpiration in which case - * $wgCookieExpiration will be used instead (defaults to 30 days). + * the same as the block's, to a maximum of 24 hours. * * An empty value can also be set, in order to retain the cookie but remove the block ID * (e.g. as used in User::getBlockedStatus). @@ -1457,18 +1458,64 @@ class Block { */ public function setCookie( WebResponse $response, $setEmpty = false ) { // Calculate the default expiry time. - $config = RequestContext::getMain()->getConfig(); - $defaultExpiry = wfTimestamp() + $config->get( 'CookieExpiration' ); + $maxExpiryTime = wfTimestamp( TS_MW, wfTimestamp() + ( 24 * 60 * 60 ) ); // Use the Block's expiry time only if it's less than the default. - $expiry = wfTimestamp( TS_UNIX, $this->getExpiry() ); - if ( $expiry > $defaultExpiry ) { - // The *default* default expiry is 30 days. - $expiry = $defaultExpiry; + $expiryTime = $this->getExpiry(); + if ( $expiryTime === 'infinity' || $expiryTime > $maxExpiryTime ) { + $expiryTime = $maxExpiryTime; + } + + // Set the cookie. Reformat the MediaWiki datetime as a Unix timestamp for the cookie. + $cookieValue = $setEmpty ? '' : $this->getCookieValue(); + $expiryValue = DateTime::createFromFormat( 'YmdHis', $expiryTime )->format( 'U' ); + $cookieOptions = [ 'httpOnly' => false ]; + $response->setCookie( 'BlockID', $cookieValue, $expiryValue, $cookieOptions ); + } + + /** + * Get the BlockID cookie's value for this block. This is usually the block ID concatenated + * with an HMAC in order to avoid spoofing (T152951), but if wgSecretKey is not set will just + * be the block ID. + * @return string The block ID, probably concatenated with "!" and the HMAC. + */ + public function getCookieValue() { + $config = RequestContext::getMain()->getConfig(); + $id = $this->getId(); + $secretKey = $config->get( 'SecretKey' ); + if ( !$secretKey ) { + // If there's no secret key, don't append a HMAC. + return $id; } + $hmac = MWCryptHash::hmac( $id, $secretKey, false ); + $cookieValue = $id . '!' . $hmac; + return $cookieValue; + } - $cookieValue = $setEmpty ? '' : $this->getId(); - $response->setCookie( 'BlockID', $cookieValue, $expiry ); + /** + * Get the stored ID from the 'BlockID' cookie. The cookie's value is usually a combination of + * the ID and a HMAC (see Block::setCookie), but will sometimes only be the ID. + * @param string $cookieValue The string in which to find the ID. + * @return integer|null The block ID, or null if the HMAC is present and invalid. + */ + public static function getIdFromCookieValue( $cookieValue ) { + // Extract the ID prefix from the cookie value (may be the whole value, if no bang found). + $bangPos = strpos( $cookieValue, '!' ); + $id = ( $bangPos === false ) ? $cookieValue : substr( $cookieValue, 0, $bangPos ); + // Get the site-wide secret key. + $config = RequestContext::getMain()->getConfig(); + $secretKey = $config->get( 'SecretKey' ); + if ( !$secretKey ) { + // If there's no secret key, just use the ID as given. + return $id; + } + $storedHmac = substr( $cookieValue, $bangPos + 1 ); + $calculatedHmac = MWCryptHash::hmac( $id, $secretKey, false ); + if ( $calculatedHmac === $storedHmac ) { + return $id; + } else { + return null; + } } /**