MediaWiki  REL1_24
wrapOldPasswords.php
Go to the documentation of this file.
00001 <?php
00023 require_once __DIR__ . '/Maintenance.php';
00024 
00032 class WrapOldPasswords extends Maintenance {
00033     public function __construct() {
00034         parent::__construct();
00035         $this->mDescription = "Wrap all passwords of a certain type in a new layered type";
00036         $this->addOption( 'type',
00037             'Password type to wrap passwords in (must inherit LayeredParameterizedPassword)', true, true );
00038         $this->addOption( 'verbose', 'Enables verbose output', false, false, 'v' );
00039         $this->setBatchSize( 100 );
00040     }
00041 
00042     public function execute() {
00043         global $wgAuth;
00044 
00045         if ( !$wgAuth->allowSetLocalPassword() ) {
00046             $this->error( '$wgAuth does not allow local passwords. Aborting.', true );
00047         }
00048 
00049         $passwordFactory = new PasswordFactory();
00050         $passwordFactory->init( RequestContext::getMain()->getConfig() );
00051 
00052         $typeInfo = $passwordFactory->getTypes();
00053         $layeredType = $this->getOption( 'type' );
00054 
00055         // Check that type exists and is a layered type
00056         if ( !isset( $typeInfo[$layeredType] ) ) {
00057             $this->error( 'Undefined password type', true );
00058         }
00059 
00060         $passObj = $passwordFactory->newFromType( $layeredType );
00061         if ( !$passObj instanceof LayeredParameterizedPassword ) {
00062             $this->error( 'Layered parameterized password type must be used.', true );
00063         }
00064 
00065         // Extract the first layer type
00066         $typeConfig = $typeInfo[$layeredType];
00067         $firstType = $typeConfig['types'][0];
00068 
00069         // Get a list of password types that are applicable
00070         $dbw = $this->getDB( DB_MASTER );
00071         $typeCond = 'user_password' . $dbw->buildLike( ":$firstType:", $dbw->anyString() );
00072 
00073         $minUserId = 0;
00074         do {
00075             $dbw->begin();
00076 
00077             $res = $dbw->select( 'user',
00078                 array( 'user_id', 'user_name', 'user_password' ),
00079                 array(
00080                     'user_id > ' . $dbw->addQuotes( $minUserId ),
00081                     $typeCond
00082                 ),
00083                 __METHOD__,
00084                 array(
00085                     'ORDER BY' => 'user_id',
00086                     'LIMIT' => $this->mBatchSize,
00087                     'LOCK IN SHARE MODE',
00088                 )
00089             );
00090 
00092             $updateUsers = array();
00093             foreach ( $res as $row ) {
00094                 if ( $this->hasOption( 'verbose' ) ) {
00095                     $this->output( "Updating password for user {$row->user_name} ({$row->user_id}).\n" );
00096                 }
00097 
00098                 $user = User::newFromId( $row->user_id );
00100                 $password = $passwordFactory->newFromCiphertext( $row->user_password );
00102                 $layeredPassword = $passwordFactory->newFromType( $layeredType );
00103                 $layeredPassword->partialCrypt( $password );
00104 
00105                 $updateUsers[] = $user;
00106                 $dbw->update( 'user',
00107                     array( 'user_password' => $layeredPassword->toString() ),
00108                     array( 'user_id' => $row->user_id ),
00109                     __METHOD__
00110                 );
00111 
00112                 $minUserId = $row->user_id;
00113             }
00114 
00115             $dbw->commit();
00116 
00117             // Clear memcached so old passwords are wiped out
00118             foreach ( $updateUsers as $user ) {
00119                 $user->clearSharedCache();
00120             }
00121         } while ( $res->numRows() );
00122     }
00123 }
00124 
00125 $maintClass = "WrapOldPasswords";
00126 require_once RUN_MAINTENANCE_IF_MAIN;