[Pkg-mediawiki-commits] r311 - in mediawiki/sid-sec/debian: . patches po

Thorsten Glaser tg at alioth.debian.org
Wed May 16 13:03:46 UTC 2012


Author: tg
Date: 2012-05-16 13:03:46 +0000 (Wed, 16 May 2012)
New Revision: 311

Added:
   mediawiki/sid-sec/debian/patches/CVE-2012-1581.patch
Modified:
   mediawiki/sid-sec/debian/changelog
   mediawiki/sid-sec/debian/patches/add_rss_guid.patch
   mediawiki/sid-sec/debian/patches/debian_specific_config.patch
   mediawiki/sid-sec/debian/patches/detect_invalid_titles.patch
   mediawiki/sid-sec/debian/patches/mimetypes.patch
   mediawiki/sid-sec/debian/patches/series
   mediawiki/sid-sec/debian/patches/texvc_location.patch
   mediawiki/sid-sec/debian/po/da.po
   mediawiki/sid-sec/debian/watch
Log:
add fix for the last remaining CVE in #666269 and some lintian cleanup

Modified: mediawiki/sid-sec/debian/changelog
===================================================================
--- mediawiki/sid-sec/debian/changelog	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/changelog	2012-05-16 13:03:46 UTC (rev 311)
@@ -1,13 +1,15 @@
-mediawiki (1:1.15.5-9) UNRELEASED; urgency=high
+mediawiki (1:1.15.5-9) unstable; urgency=high
 
+  * Team upload.
   * Address MW security release 1.18.1-1 (Closes: #666269)
     - CVE-2012-1578 MW#34212: doesn’t affect 1.15
     - CVE-2012-1579 MW#34907: doesn’t affect 1.15
     - CVE-2012-1580 MW#35317: doesn’t affect 1.15
-    - CVE-2012-1581 MW#35078: (can’t access bugreport)
+    - CVE-2012-1581 MW#35078: fix backported
     - CVE-2012-1582 MW#35315: fix backported
+  * Apply some lintian cleanup
 
- -- Thorsten Glaser <tg at mirbsd.de>  Fri, 30 Mar 2012 10:41:58 +0200
+ -- Thorsten Glaser <tg at mirbsd.de>  Wed, 16 May 2012 15:01:06 +0200
 
 mediawiki (1:1.15.5-8) unstable; urgency=low
 

Added: mediawiki/sid-sec/debian/patches/CVE-2012-1581.patch
===================================================================
--- mediawiki/sid-sec/debian/patches/CVE-2012-1581.patch	                        (rev 0)
+++ mediawiki/sid-sec/debian/patches/CVE-2012-1581.patch	2012-05-16 13:03:46 UTC (rev 311)
@@ -0,0 +1,745 @@
+Description: Add a better PRNG class; use it in some places
+ Original commitdiffs (squashed into one patch):
+ - 298741089078574ed352552cdf6ae4c91e4c7aad
+ - 0a1d98cb1e292d0fbb0adf134617c1aafdce2e0f
+ - 96c81c1b5be52b903aa1cd9c95e51c864c2db920
+ - 4645fef5428387a8ea27572342c6385f5be210cf
+ - 51d2acffb2cab8309ad75232ece80b3939f1ccba
+ Tim Starling said I would need all of those.
+Origin: Mediawiki git
+Bug: https://bugzilla.wikimedia.org/show_bug.cgi?id=35078
+
+Index: mediawiki-1.15.5/includes/AutoLoader.php
+===================================================================
+--- mediawiki-1.15.5.orig/includes/AutoLoader.php	2009-05-01 08:24:09.000000000 +0200
++++ mediawiki-1.15.5/includes/AutoLoader.php	2012-05-16 14:59:43.000000000 +0200
+@@ -125,6 +125,7 @@
+ 	'memcached' => 'includes/memcached-client.php',
+ 	'MessageCache' => 'includes/MessageCache.php',
+ 	'MimeMagic' => 'includes/MimeMagic.php',
++	'MWCryptRand' => 'includes/CryptRand.php',
+ 	'MWException' => 'includes/Exception.php',
+ 	'MWNamespace' => 'includes/Namespace.php',
+ 	'MySQLSearchResultSet' => 'includes/SearchMySQL.php',
+Index: mediawiki-1.15.5/includes/CryptRand.php
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ mediawiki-1.15.5/includes/CryptRand.php	2012-05-16 14:59:43.000000000 +0200
+@@ -0,0 +1,468 @@
++<?php
++/**
++ * A cryptographic random generator class used for generating secret keys
++ *
++ * This is based in part on Drupal code as well as what we used in our own code
++ * prior to introduction of this class.
++ *
++ * @author Daniel Friesen
++ * @file
++ */
++
++class MWCryptRand {
++
++	/**
++	 * Minimum number of iterations we want to make in our drift calculations.
++	 */
++	const MIN_ITERATIONS = 1000;
++
++	/**
++	 * Number of milliseconds we want to spend generating each separate byte
++	 * of the final generated bytes.
++	 * This is used in combination with the hash length to determine the duration
++	 * we should spend doing drift calculations.
++	 */
++	const MSEC_PER_BYTE = 0.5;
++
++	/**
++	 * Singleton instance for public use
++	 */
++	protected static $singleton = null;
++
++	/**
++	 * The hash algorithm being used
++	 */
++	protected $algo = null;
++
++	/**
++	 * The number of bytes outputted by the hash algorithm
++	 */
++	protected $hashLength = null;
++
++	/**
++	 * A boolean indicating whether the previous random generation was done using
++	 * cryptographically strong random number generator or not.
++	 */
++	protected $strong = null;
++
++	/**
++	 * Initialize an initial random state based off of whatever we can find
++	 */
++	protected function initialRandomState() {
++		// $_SERVER contains a variety of unstable user and system specific information
++		// It'll vary a little with each page, and vary even more with separate users
++		// It'll also vary slightly across different machines
++		$state = serialize( $_SERVER );
++
++		// To try and vary the system information of the state a bit more
++		// by including the system's hostname into the state
++		$state .= wfHostname();
++
++		// Try to gather a little entropy from the different php rand sources
++		$state .= rand() . uniqid( mt_rand(), true );
++
++		// Include some information about the filesystem's current state in the random state
++		$files = array();
++		// We know this file is here so grab some info about ourself
++		$files[] = __FILE__;
++		// The config file is likely the most often edited file we know should be around
++		// so if the constant with it's location is defined include it's stat info into the state
++		if ( defined( 'MW_CONFIG_FILE' ) ) {
++			$files[] = MW_CONFIG_FILE;
++		}
++		foreach ( $files as $file ) {
++			wfSuppressWarnings();
++			$stat = stat( $file );
++			wfRestoreWarnings();
++			if ( $stat ) {
++				// stat() duplicates data into numeric and string keys so kill off all the numeric ones
++				foreach ( $stat as $k => $v ) {
++					if ( is_numeric( $k ) ) {
++						unset( $k );
++					}
++				}
++				// The absolute filename itself will differ from install to install so don't leave it out
++				$state .= realpath( $file );
++				$state .= implode( '', $stat );
++			} else {
++				// The fact that the file isn't there is worth at least a
++				// minuscule amount of entropy.
++				$state .= '0';
++			}
++		}
++
++		// Try and make this a little more unstable by including the varying process
++		// id of the php process we are running inside of if we are able to access it
++		if ( function_exists( 'getmypid' ) ) {
++			$state .= getmypid();
++		}
++
++		// If available try to increase the instability of the data by throwing in
++		// the precise amount of memory that we happen to be using at the moment.
++		if ( function_exists( 'memory_get_usage' ) ) {
++			$state .= memory_get_usage( true );
++		}
++
++		// It's mostly worthless but throw the wiki's id into the data for a little more variance
++		$state .= wfWikiID();
++
++		// If we have a secret key or proxy key set then throw it into the state as well
++		global $wgSecretKey, $wgProxyKey;
++		if ( $wgSecretKey ) {
++			$state .= $wgSecretKey;
++		} elseif ( $wgProxyKey ) {
++			$state .= $wgProxyKey;
++		}
++
++		return $state;
++	}
++
++	/**
++	 * Randomly hash data while mixing in clock drift data for randomness
++	 *
++	 * @param $data string The data to randomly hash.
++	 * @return String The hashed bytes
++	 * @author Tim Starling
++	 */
++	protected function driftHash( $data ) {
++		// Minimum number of iterations (to avoid slow operations causing the loop to gather little entropy)
++		$minIterations = self::MIN_ITERATIONS;
++		// Duration of time to spend doing calculations (in seconds)
++		$duration = ( self::MSEC_PER_BYTE / 1000 ) * $this->hashLength();
++		// Create a buffer to use to trigger memory operations
++		$bufLength = 10000000;
++		$buffer = str_repeat( ' ', $bufLength );
++		$bufPos = 0;
++
++		// Iterate for $duration seconds or at least $minIerations number of iterations
++		$iterations = 0;
++		$startTime = microtime( true );
++		$currentTime = $startTime;
++		while ( $iterations < $minIterations || $currentTime - $startTime < $duration ) {
++			// Trigger some memory writing to trigger some bus activity
++			// This may create variance in the time between iterations
++			$bufPos = ( $bufPos + 13 ) % $bufLength;
++			$buffer[$bufPos] = ' ';
++			// Add the drift between this iteration and the last in as entropy
++			$nextTime = microtime( true );
++			$delta = (int)( ( $nextTime - $currentTime ) * 1000000 );
++			$data .= $delta;
++			// Every 100 iterations hash the data and entropy
++			if ( $iterations % 100 === 0 ) {
++				$data = sha1( $data );
++			}
++			$currentTime = $nextTime;
++			$iterations++;
++		}
++		$timeTaken = $currentTime - $startTime;
++		$data = $this->hash( $data );
++
++		wfDebug( __METHOD__ . ": Clock drift calculation " .
++			"(time-taken=" . ( $timeTaken * 1000 ) . "ms, " .
++			"iterations=$iterations, " .
++			"time-per-iteration=" . ( $timeTaken / $iterations * 1e6 ) . "us)\n" );
++		return $data;
++	}
++
++	/**
++	 * Return a rolling random state initially build using data from unstable sources
++	 * @return string A new weak random state
++	 */
++	protected function randomState() {
++		static $state = null;
++		if ( is_null( $state ) ) {
++			// Initialize the state with whatever unstable data we can find
++			// It's important that this data is hashed right afterwards to prevent
++			// it from being leaked into the output stream
++			$state = $this->hash( $this->initialRandomState() );
++		}
++		// Generate a new random state based on the initial random state or previous
++		// random state by combining it with clock drift
++		$state = $this->driftHash( $state );
++		return $state;
++	}
++
++	/**
++	 * Decide on the best acceptable hash algorithm we have available for hash()
++	 * @throws MWException
++	 * @return String A hash algorithm
++	 */
++	protected function hashAlgo() {
++		if ( !is_null( $this->algo ) ) {
++			return $this->algo;
++		}
++
++		$algos = hash_algos();
++		$preference = array( 'whirlpool', 'sha256', 'sha1', 'md5' );
++
++		foreach ( $preference as $algorithm ) {
++			if ( in_array( $algorithm, $algos ) ) {
++				$this->algo = $algorithm;
++				wfDebug( __METHOD__ . ": Using the {$this->algo} hash algorithm.\n" );
++				return $this->algo;
++			}
++		}
++
++		// We only reach here if no acceptable hash is found in the list, this should
++		// be a technical impossibility since most of php's hash list is fixed and
++		// some of the ones we list are available as their own native functions
++		// But since we already require at least 5.2 and hash() was default in
++		// 5.1.2 we don't bother falling back to methods like sha1 and md5.
++		throw new MWException( "Could not find an acceptable hashing function in hash_algos()" );
++	}
++
++	/**
++	 * Return the byte-length output of the hash algorithm we are
++	 * using in self::hash and self::hmac.
++	 *
++	 * @return int Number of bytes the hash outputs
++	 */
++	protected function hashLength() {
++		if ( is_null( $this->hashLength ) ) {
++			$this->hashLength = strlen( $this->hash( '' ) );
++		}
++		return $this->hashLength;
++	}
++
++	/**
++	 * Generate an acceptably unstable one-way-hash of some text
++	 * making use of the best hash algorithm that we have available.
++	 *
++	 * @param $data string
++	 * @return String A raw hash of the data
++	 */
++	protected function hash( $data ) {
++		return hash( $this->hashAlgo(), $data, true );
++	}
++
++	/**
++	 * Generate an acceptably unstable one-way-hmac of some text
++	 * making use of the best hash algorithm that we have available.
++	 *
++	 * @param $data string
++	 * @param $key string
++	 * @return String A raw hash of the data
++	 */
++	protected function hmac( $data, $key ) {
++		return hash_hmac( $this->hashAlgo(), $data, $key, true );
++	}
++
++	/**
++	 * @see self::wasStrong()
++	 */
++	public function realWasStrong() {
++		if ( is_null( $this->strong ) ) {
++			throw new MWException( __METHOD__ . ' called before generation of random data' );
++		}
++		return $this->strong;
++	}
++
++	/**
++	 * @see self::generate()
++	 */
++	public function realGenerate( $bytes, $forceStrong = false ) {
++		wfProfileIn( __METHOD__ );
++
++		wfDebug( __METHOD__ . ": Generating cryptographic random bytes for " . wfGetAllCallers( 5 ) . "\n" );
++
++		$bytes = floor( $bytes );
++		static $buffer = '';
++		if ( is_null( $this->strong ) ) {
++			// Set strength to false initially until we know what source data is coming from
++			$this->strong = true;
++		}
++
++		if ( strlen( $buffer ) < $bytes ) {
++			// If available make use of mcrypt_create_iv URANDOM source to generate randomness
++			// On unix-like systems this reads from /dev/urandom but does it without any buffering
++			// and bypasses openbasdir restrictions so it's preferable to reading directly
++			// On Windows starting in PHP 5.3.0 Windows' native CryptGenRandom is used to generate
++			// entropy so this is also preferable to just trying to read urandom because it may work
++			// on Windows systems as well.
++			if ( function_exists( 'mcrypt_create_iv' ) ) {
++				wfProfileIn( __METHOD__ . '-mcrypt' );
++				$rem = $bytes - strlen( $buffer );
++				$iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
++				if ( $iv === false ) {
++					wfDebug( __METHOD__ . ": mcrypt_create_iv returned false.\n" );
++				} else {
++					$buffer .= $iv;
++					wfDebug( __METHOD__ . ": mcrypt_create_iv generated " . strlen( $iv ) . " bytes of randomness.\n" );
++				}
++				wfProfileOut( __METHOD__ . '-mcrypt' );
++			}
++		}
++
++		if ( strlen( $buffer ) < $bytes ) {
++			// If available make use of openssl's random_pesudo_bytes method to attempt to generate randomness.
++			// However don't do this on Windows with PHP < 5.3.4 due to a bug:
++			// http://stackoverflow.com/questions/1940168/openssl-random-pseudo-bytes-is-slow-php
++			if ( function_exists( 'openssl_random_pseudo_bytes' )
++				&& ( !wfIsWindows() || version_compare( PHP_VERSION, '5.3.4', '>=' ) )
++			) {
++				wfProfileIn( __METHOD__ . '-openssl' );
++				$rem = $bytes - strlen( $buffer );
++				$openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
++				if ( $openssl_bytes === false ) {
++					wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes returned false.\n" );
++				} else {
++					$buffer .= $openssl_bytes;
++					wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes generated " . strlen( $openssl_bytes ) . " bytes of " . ( $openssl_strong ? "strong" : "weak" ) . " randomness.\n" );
++				}
++				if ( strlen( $buffer ) >= $bytes ) {
++					// openssl tells us if the random source was strong, if some of our data was generated
++					// using it use it's say on whether the randomness is strong
++					$this->strong = !!$openssl_strong;
++				}
++				wfProfileOut( __METHOD__ . '-openssl' );
++			}
++		}
++
++		// Only read from urandom if we can control the buffer size or were passed forceStrong
++		if ( strlen( $buffer ) < $bytes && ( function_exists( 'stream_set_read_buffer' ) || $forceStrong ) ) {
++			wfProfileIn( __METHOD__ . '-fopen-urandom' );
++			$rem = $bytes - strlen( $buffer );
++			if ( !function_exists( 'stream_set_read_buffer' ) && $forceStrong ) {
++				wfDebug( __METHOD__ . ": Was forced to read from /dev/urandom without control over the buffer size.\n" );
++			}
++			// /dev/urandom is generally considered the best possible commonly
++			// available random source, and is available on most *nix systems.
++			wfSuppressWarnings();
++			$urandom = fopen( "/dev/urandom", "rb" );
++			wfRestoreWarnings();
++
++			// Attempt to read all our random data from urandom
++			// php's fread always does buffered reads based on the stream's chunk_size
++			// so in reality it will usually read more than the amount of data we're
++			// asked for and not storing that risks depleting the system's random pool.
++			// If stream_set_read_buffer is available set the chunk_size to the amount
++			// of data we need. Otherwise read 8k, php's default chunk_size.
++			if ( $urandom ) {
++				// php's default chunk_size is 8k
++				$chunk_size = 1024 * 8;
++				if ( function_exists( 'stream_set_read_buffer' ) ) {
++					// If possible set the chunk_size to the amount of data we need
++					stream_set_read_buffer( $urandom, $rem );
++					$chunk_size = $rem;
++				}
++				$random_bytes = fread( $urandom, max( $chunk_size, $rem ) );
++				$buffer .= $random_bytes;
++				fclose( $urandom );
++				wfDebug( __METHOD__ . ": /dev/urandom generated " . strlen( $random_bytes ) . " bytes of randomness.\n" );
++				if ( strlen( $buffer ) >= $bytes ) {
++					// urandom is always strong, set to true if all our data was generated using it
++					$this->strong = true;
++				}
++			} else {
++				wfDebug( __METHOD__ . ": /dev/urandom could not be opened.\n" );
++			}
++			wfProfileOut( __METHOD__ . '-fopen-urandom' );
++		}
++
++		// If we cannot use or generate enough data from a secure source
++		// use this loop to generate a good set of pseudo random data.
++		// This works by initializing a random state using a pile of unstable data
++		// and continually shoving it through a hash along with a variable salt.
++		// We hash the random state with more salt to avoid the state from leaking
++		// out and being used to predict the /randomness/ that follows.
++		if ( strlen( $buffer ) < $bytes ) {
++			wfDebug( __METHOD__ . ": Falling back to using a pseudo random state to generate randomness.\n" );
++		}
++		while ( strlen( $buffer ) < $bytes ) {
++			wfProfileIn( __METHOD__ . '-fallback' );
++			$buffer .= $this->hmac( $this->randomState(), mt_rand() );
++			// This code is never really cryptographically strong, if we use it
++			// at all, then set strong to false.
++			$this->strong = false;
++			wfProfileOut( __METHOD__ . '-fallback' );
++		}
++
++		// Once the buffer has been filled up with enough random data to fulfill
++		// the request shift off enough data to handle the request and leave the
++		// unused portion left inside the buffer for the next request for random data
++		$generated = substr( $buffer, 0, $bytes );
++		$buffer = substr( $buffer, $bytes );
++
++		wfDebug( __METHOD__ . ": " . strlen( $buffer ) . " bytes of randomness leftover in the buffer.\n" );
++
++		wfProfileOut( __METHOD__ );
++		return $generated;
++	}
++
++	/**
++	 * @see self::generateHex()
++	 */
++	public function realGenerateHex( $chars, $forceStrong = false ) {
++		// hex strings are 2x the length of raw binary so we divide the length in half
++		// odd numbers will result in a .5 that leads the generate() being 1 character
++		// short, so we use ceil() to ensure that we always have enough bytes
++		$bytes = ceil( $chars / 2 );
++		// Generate the data and then convert it to a hex string
++		$hex = bin2hex( $this->generate( $bytes, $forceStrong ) );
++		// A bit of paranoia here, the caller asked for a specific length of string
++		// here, and it's possible (eg when given an odd number) that we may actually
++		// have at least 1 char more than they asked for. Just in case they made this
++		// call intending to insert it into a database that does truncation we don't
++		// want to give them too much and end up with their database and their live
++		// code having two different values because part of what we gave them is truncated
++		// hence, we strip out any run of characters longer than what we were asked for.
++		return substr( $hex, 0, $chars );
++	}
++
++	/** Publicly exposed static methods **/
++
++	/**
++	 * Return a singleton instance of MWCryptRand
++	 * @return MWCryptRand
++	 */
++	protected static function singleton() {
++		if ( is_null( self::$singleton ) ) {
++			self::$singleton = new self;
++		}
++		return self::$singleton;
++	}
++
++	/**
++	 * Return a boolean indicating whether or not the source used for cryptographic
++	 * random bytes generation in the previously run generate* call
++	 * was cryptographically strong.
++	 *
++	 * @return bool Returns true if the source was strong, false if not.
++	 */
++	public static function wasStrong() {
++		return self::singleton()->realWasStrong();
++	}
++
++	/**
++	 * Generate a run of (ideally) cryptographically random data and return
++	 * it in raw binary form.
++	 * You can use MWCryptRand::wasStrong() if you wish to know if the source used
++	 * was cryptographically strong.
++	 *
++	 * @param $bytes int the number of bytes of random data to generate
++	 * @param $forceStrong bool Pass true if you want generate to prefer cryptographically
++	 *                          strong sources of entropy even if reading from them may steal
++	 *                          more entropy from the system than optimal.
++	 * @return String Raw binary random data
++	 */
++	public static function generate( $bytes, $forceStrong = false ) {
++		return self::singleton()->realGenerate( $bytes, $forceStrong );
++	}
++
++	/**
++	 * Generate a run of (ideally) cryptographically random data and return
++	 * it in hexadecimal string format.
++	 * You can use MWCryptRand::wasStrong() if you wish to know if the source used
++	 * was cryptographically strong.
++	 *
++	 * @param $chars int the number of hex chars of random data to generate
++	 * @param $forceStrong bool Pass true if you want generate to prefer cryptographically
++	 *                          strong sources of entropy even if reading from them may steal
++	 *                          more entropy from the system than optimal.
++	 * @return String Hexadecimal random data
++	 */
++	public static function generateHex( $chars, $forceStrong = false ) {
++		return self::singleton()->realGenerateHex( $chars, $forceStrong );
++	}
++
++}
+Index: mediawiki-1.15.5/includes/GlobalFunctions.php
+===================================================================
+--- mediawiki-1.15.5.orig/includes/GlobalFunctions.php	2012-05-16 14:59:43.000000000 +0200
++++ mediawiki-1.15.5/includes/GlobalFunctions.php	2012-05-16 14:59:43.000000000 +0200
+@@ -2650,6 +2650,33 @@
+ }
+ 
+ /**
++ * Override session_id before session startup if php's built-in
++ * session generation code is not secure.
++ */
++function wfFixSessionID() {
++	// If the cookie or session id is already set we already have a session and should abort
++	if ( isset( $_COOKIE[ session_name() ] ) || session_id() ) {
++		return;
++	}
++
++	// PHP's built-in session entropy is enabled if:
++	// - entropy_file is set or you're on Windows with php 5.3.3+
++	// - AND entropy_length is > 0
++	// We treat it as disabled if it doesn't have an entropy length of at least 32
++	$entropyEnabled = (
++			( wfIsWindows() && version_compare( PHP_VERSION, '5.3.3', '>=' ) )
++			|| ini_get( 'session.entropy_file' )
++		)
++		&& intval( ini_get( 'session.entropy_length' ) ) >= 32;
++
++	// If built-in entropy is not enabled or not sufficient override php's built in session id generation code
++	if ( !$entropyEnabled ) {
++		wfDebug( __METHOD__ . ": PHP's built in entropy is disabled or not sufficient, overriding session id generation using our cryptrand source.\n" );
++		session_id( MWCryptRand::generateHex( 32 ) );
++	}
++}
++
++/**
+  * Initialise php session
+  */
+ function wfSetupSession() {
+Index: mediawiki-1.15.5/includes/User.php
+===================================================================
+--- mediawiki-1.15.5.orig/includes/User.php	2012-05-16 14:59:43.000000000 +0200
++++ mediawiki-1.15.5/includes/User.php	2012-05-16 14:59:43.000000000 +0200
+@@ -733,23 +733,20 @@
+ 	}
+ 
+ 	/**
+-	 * Return a random password. Sourced from mt_rand, so it's not particularly secure.
+-	 * @todo hash random numbers to improve security, like generateToken()
++	 * Return a random password.
+ 	 *
+ 	 * @return \string New random password
+ 	 */
+ 	static function randomPassword() {
+ 		global $wgMinimalPasswordLength;
+-		$pwchars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz';
+-		$l = strlen( $pwchars ) - 1;
+-
+-		$pwlength = max( 7, $wgMinimalPasswordLength );
+-		$digit = mt_rand(0, $pwlength - 1);
+-		$np = '';
+-		for ( $i = 0; $i < $pwlength; $i++ ) {
+-			$np .= $i == $digit ? chr( mt_rand(48, 57) ) : $pwchars{ mt_rand(0, $l)};
+-		}
+-		return $np;
++		// Decide the final password length based on our min password length, stopping at a minimum of 10 chars
++		$length = max( 10, $wgMinimalPasswordLength );
++		// Multiply by 1.25 to get the number of hex characters we need
++		$length = $length * 1.25;
++		// Generate random hex chars
++		$hex = MWCryptRand::generateHex( $length );
++		// Convert from base 16 to base 32 to get a proper password like string
++		return wfBaseConvert( $hex, 16, 32 );
+ 	}
+ 
+ 	/**
+@@ -778,7 +775,7 @@
+ 			$this->mTouched = '0'; # Allow any pages to be cached
+ 		}
+ 
+-		$this->setToken(); # Random
++		$this->mToken = null; // Don't run cryptographic functions till we need a token
+ 		$this->mEmailAuthenticated = null;
+ 		$this->mEmailToken = '';
+ 		$this->mEmailTokenExpires = null;
+@@ -847,14 +844,15 @@
+ 		$this->mId = $sId;
+ 		if ( !$this->loadFromId() ) {
+ 			# Not a valid ID, loadFromId has switched the object to anon for us
++			$this->loadDefaults();
+ 			return false;
+ 		}
+ 
+-		if ( isset( $_SESSION['wsToken'] ) ) {
+-			$passwordCorrect = $_SESSION['wsToken'] == $this->mToken;
++		if ( isset( $_SESSION['wsToken'] ) && $_SESSION['wsToken'] ) {
++			$passwordCorrect = $this->getToken( false ) === $_SESSION['wsToken'];
+ 			$from = 'session';
+ 		} else if ( isset( $_COOKIE["{$wgCookiePrefix}Token"] ) ) {
+-			$passwordCorrect = $this->mToken == $_COOKIE["{$wgCookiePrefix}Token"];
++			$passwordCorrect = $this->getToken( false ) === $_COOKIE["{$wgCookiePrefix}Token"];
+ 			$from = 'cookie';
+ 		} else {
+ 			# No session or persistent login cookie
+@@ -930,6 +928,9 @@
+ 		$this->decodeOptions( $row->user_options );
+ 		$this->mTouched = wfTimestamp(TS_MW,$row->user_touched);
+ 		$this->mToken = $row->user_token;
++		if ( $this->mToken == '' ) {
++			$this->mToken = null;
++		}
+ 		$this->mEmailAuthenticated = wfTimestampOrNull( TS_MW, $row->user_email_authenticated );
+ 		$this->mEmailToken = $row->user_email_token;
+ 		$this->mEmailTokenExpires = wfTimestampOrNull( TS_MW, $row->user_email_token_expires );
+@@ -1739,10 +1740,14 @@
+ 	
+ 	/**
+ 	 * Get the user's current token.
++	 * @param $forceCreation Force the generation of a new token if the user doesn't have one (default=true for backwards compatibility)
+ 	 * @return \string Token
+ 	 */
+-	function getToken() {
++	function getToken( $forceCreation = true ) {
+ 		$this->load();
++		if ( !$this->mToken && $forceCreation ) {
++			$this->setToken();
++		}
+ 		return $this->mToken;
+ 	}
+ 	
+@@ -1757,14 +1762,7 @@
+ 		global $wgSecretKey, $wgProxyKey;
+ 		$this->load();
+ 		if ( !$token ) {
+-			if ( $wgSecretKey ) {
+-				$key = $wgSecretKey;
+-			} elseif ( $wgProxyKey ) {
+-				$key = $wgProxyKey;
+-			} else {
+-				$key = microtime();
+-			}
+-			$this->mToken = md5( $key . mt_rand( 0, 0x7fffffff ) . wfWikiID() . $this->mId );
++			$this->mToken = MWCryptRand::generateHex( USER_TOKEN_LENGTH );
+ 		} else {
+ 			$this->mToken = $token;
+ 		}
+@@ -2347,6 +2345,14 @@
+ 	function setCookies() {
+ 		$this->load();
+ 		if ( 0 == $this->mId ) return;
++		if ( !$this->mToken ) {
++			// When token is empty or NULL generate a new one and then save it to the database
++			// This allows a wiki to re-secure itself after a leak of it's user table or $wgSecretKey
++			// Simply by setting every cell in the user_token column to NULL and letting them be
++			// regenerated as users log back into the wiki.
++			$this->setToken();
++			$this->saveSettings();
++		}
+ 		$session = array( 
+ 			'wsUserID' => $this->mId,
+ 			'wsToken' => $this->mToken,
+@@ -2426,7 +2432,7 @@
+ 		 		'user_email_authenticated' => $dbw->timestampOrNull( $this->mEmailAuthenticated ),
+ 				'user_options' => $this->encodeOptions(),
+ 				'user_touched' => $dbw->timestamp($this->mTouched),
+-				'user_token' => $this->mToken,
++				'user_token' => strval( $this->mToken ),
+ 				'user_email_token' => $this->mEmailToken,
+ 				'user_email_token_expires' => $dbw->timestampOrNull( $this->mEmailTokenExpires ),
+ 			), array( /* WHERE */
+@@ -2488,7 +2494,7 @@
+ 			'user_email_authenticated' => $dbw->timestampOrNull( $user->mEmailAuthenticated ),
+ 			'user_real_name' => $user->mRealName,
+ 			'user_options' => $user->encodeOptions(),
+-			'user_token' => $user->mToken,
++			'user_token' => strval( $user->mToken ),
+ 			'user_registration' => $dbw->timestamp( $user->mRegistration ),
+ 			'user_editcount' => 0,
+ 		);
+@@ -2522,7 +2528,7 @@
+ 				'user_email_authenticated' => $dbw->timestampOrNull( $this->mEmailAuthenticated ),
+ 				'user_real_name' => $this->mRealName,
+ 				'user_options' => $this->encodeOptions(),
+-				'user_token' => $this->mToken,
++				'user_token' => strval( $this->mToken ),
+ 				'user_registration' => $dbw->timestamp( $this->mRegistration ),
+ 				'user_editcount' => 0,
+ 			), __METHOD__
+@@ -2772,7 +2778,7 @@
+ 			return EDIT_TOKEN_SUFFIX;
+ 		} else {
+ 			if( !isset( $_SESSION['wsEditToken'] ) ) {
+-				$token = self::generateToken();
++				$token = MWCryptRand::generateHex( 32 );
+ 				$_SESSION['wsEditToken'] = $token;
+ 			} else {
+ 				$token = $_SESSION['wsEditToken'];
+@@ -2791,8 +2797,7 @@
+ 	 * @return \string The new random token
+ 	 */
+ 	public static function generateToken( $salt = '' ) {
+-		$token = dechex( mt_rand() ) . dechex( mt_rand() );
+-		return md5( $token . $salt );
++		return MWCryptRand::generateHex( 32 );
+ 	}
+ 
+ 	/**
+@@ -2885,7 +2890,7 @@
+ 		$now = time();
+ 		$expires = $now + 7 * 24 * 60 * 60;
+ 		$expiration = wfTimestamp( TS_MW, $expires );
+-		$token = self::generateToken( $this->mId . $this->mEmail . $expires );
++		$token = MWCryptRand::generateHex( 32 );
+ 		$hash = md5( $token );
+ 		$this->load();
+ 		$this->mEmailToken = $hash;
+@@ -3327,7 +3332,7 @@
+ 		
+ 		if( $wgPasswordSalt ) {
+ 			if ( $salt === false ) {
+-				$salt = substr( wfGenerateToken(), 0, 8 );
++				$salt = MWCryptRand::generateHex( 8 );
+ 			}
+ 			return ':B:' . $salt . ':' . md5( $salt . '-' . md5( $password ) );
+ 		} else {
+Index: mediawiki-1.15.5/includes/specials/SpecialUserlogin.php
+===================================================================
+--- mediawiki-1.15.5.orig/includes/specials/SpecialUserlogin.php	2010-05-28 09:02:34.000000000 +0200
++++ mediawiki-1.15.5/includes/specials/SpecialUserlogin.php	2012-05-16 14:59:44.000000000 +0200
+@@ -1025,9 +1025,9 @@
+ 	 */
+ 	public static function setLoginToken() {
+ 		global $wgRequest;
+-		// Use User::generateToken() instead of $user->editToken()
++		// Generate a token directly instead of using $user->editToken()
+ 		// because the latter reuses $_SESSION['wsEditToken']
+-		$wgRequest->setSessionData( 'wsLoginToken', User::generateToken() );
++		$wgRequest->setSessionData( 'wsLoginToken', MWCryptRand::generateHex( 32 ) );
+ 	}
+ 	
+ 	/**
+@@ -1051,7 +1051,7 @@
+ 	 */
+ 	public static function setCreateaccountToken() {
+ 		global $wgRequest;
+-		$wgRequest->setSessionData( 'wsCreateaccountToken', User::generateToken() );
++		$wgRequest->setSessionData( 'wsCreateaccountToken', MWCryptRand::generateHex( 32 ) );
+ 	}
+ 	
+ 	/**

Modified: mediawiki/sid-sec/debian/patches/add_rss_guid.patch
===================================================================
--- mediawiki/sid-sec/debian/patches/add_rss_guid.patch	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/patches/add_rss_guid.patch	2012-05-16 13:03:46 UTC (rev 311)
@@ -1,3 +1,5 @@
+# DP: add unique IDs to RSS output
+
 Index: mediawiki-1.15.2/includes/Feed.php
 ===================================================================
 --- mediawiki-1.15.2.orig/includes/Feed.php	2008-11-18 18:11:14.000000000 -0600

Modified: mediawiki/sid-sec/debian/patches/debian_specific_config.patch
===================================================================
--- mediawiki/sid-sec/debian/patches/debian_specific_config.patch	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/patches/debian_specific_config.patch	2012-05-16 13:03:46 UTC (rev 311)
@@ -1,3 +1,6 @@
+# DP: use debian-specific system-wide installation path
+# DP: and include mediawiki-extensions provided configuration
+
 --- mediawiki-1.15.4.orig/config/index.php
 +++ mediawiki-1.15.4/config/index.php
 @@ -28,7 +28,6 @@

Modified: mediawiki/sid-sec/debian/patches/detect_invalid_titles.patch
===================================================================
--- mediawiki/sid-sec/debian/patches/detect_invalid_titles.patch	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/patches/detect_invalid_titles.patch	2012-05-16 13:03:46 UTC (rev 311)
@@ -1,3 +1,5 @@
+# DP: detect invalid titles and mark them as such
+
 Index: mediawiki-1.15.2/includes/specials/SpecialMostlinked.php
 ===================================================================
 --- mediawiki-1.15.2.orig/includes/specials/SpecialMostlinked.php	2008-07-17 20:31:18.000000000 -0500

Modified: mediawiki/sid-sec/debian/patches/mimetypes.patch
===================================================================
--- mediawiki/sid-sec/debian/patches/mimetypes.patch	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/patches/mimetypes.patch	2012-05-16 13:03:46 UTC (rev 311)
@@ -1,3 +1,5 @@
+# DP: use system-wide MIME types information
+
 Index: mediawiki-1.15.2/includes/DefaultSettings.php
 ===================================================================
 --- mediawiki-1.15.2.orig/includes/DefaultSettings.php	2010-03-15 12:01:58.000000000 -0500

Modified: mediawiki/sid-sec/debian/patches/series
===================================================================
--- mediawiki/sid-sec/debian/patches/series	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/patches/series	2012-05-16 13:03:46 UTC (rev 311)
@@ -20,3 +20,4 @@
 fix-blacklist.patch
 php54.patch
 CVE-2012-1582.patch
+CVE-2012-1581.patch

Modified: mediawiki/sid-sec/debian/patches/texvc_location.patch
===================================================================
--- mediawiki/sid-sec/debian/patches/texvc_location.patch	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/patches/texvc_location.patch	2012-05-16 13:03:46 UTC (rev 311)
@@ -1,3 +1,5 @@
+# DP: texvc is installed system-wide
+
 Index: mediawiki-1.15.2/includes/DefaultSettings.php
 ===================================================================
 --- mediawiki-1.15.2.orig/includes/DefaultSettings.php	2010-03-08 16:52:50.000000000 -0600

Modified: mediawiki/sid-sec/debian/po/da.po
===================================================================
--- mediawiki/sid-sec/debian/po/da.po	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/po/da.po	2012-05-16 13:03:46 UTC (rev 311)
@@ -11,6 +11,7 @@
 "PO-Revision-Date: 2011-05-24 18:30+01:00\n"
 "Last-Translator: Joe Hansen <joedalton2 at yahoo.dk>\n"
 "Language-Team: Danish <debian-l10n-danish at lists.debian.org>\n"
+"Language: da\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"

Modified: mediawiki/sid-sec/debian/watch
===================================================================
--- mediawiki/sid-sec/debian/watch	2012-03-30 08:43:27 UTC (rev 310)
+++ mediawiki/sid-sec/debian/watch	2012-05-16 13:03:46 UTC (rev 311)
@@ -1,11 +1,2 @@
-# Example watch control file for uscan
-# Rename this file to "watch" and then you can run the "uscan" command
-# to check for upstream updates and more.
-# See uscan(1) for format
-
-# Compulsory line, this is a version 3 file
 version=3
-
-# Uncomment to examine a Webserver directory
 http://www.mediawiki.org/wiki/Download http://download.wikimedia.org/mediawiki/.*/mediawiki-(.*).tar.gz
-




More information about the Pkg-mediawiki-commits mailing list