Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
update_hashes
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 3
56
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 configure
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3*
4* This file is part of the phpBB Forum Software package.
5*
6* @copyright (c) phpBB Limited <https://www.phpbb.com>
7* @license GNU General Public License, version 2 (GPL-2.0)
8*
9* For full copyright and license information, please see
10* the docs/CREDITS.txt file.
11*
12*/
13namespace phpbb\console\command\fixup;
14
15use Symfony\Component\Console\Command\Command as symfony_command;
16use Symfony\Component\Console\Input\InputInterface;
17use Symfony\Component\Console\Output\OutputInterface;
18use Symfony\Component\Console\Helper\ProgressBar;
19
20class update_hashes extends \phpbb\console\command\command
21{
22    /** @var \phpbb\config\config */
23    protected $config;
24
25    /** @var \phpbb\db\driver\driver_interface */
26    protected $db;
27
28    /** @var \phpbb\passwords\manager */
29    protected $passwords_manager;
30
31    /** @var string Default hashing type */
32    protected $default_type;
33
34    /**
35     * Update_hashes constructor
36     *
37     * @param \phpbb\config\config $config
38     * @param \phpbb\user $user
39     * @param \phpbb\db\driver\driver_interface $db
40     * @param \phpbb\passwords\manager $passwords_manager
41     * @param array $hashing_algorithms Hashing driver
42     *            service collection
43     * @param array $defaults Default password types
44     */
45    public function __construct(\phpbb\config\config $config, \phpbb\user $user,
46                                \phpbb\db\driver\driver_interface $db, \phpbb\passwords\manager $passwords_manager,
47                                $hashing_algorithms, $defaults)
48    {
49        $this->config = $config;
50        $this->db = $db;
51
52        $this->passwords_manager = $passwords_manager;
53
54        foreach ($defaults as $type)
55        {
56            if ($hashing_algorithms[$type]->is_supported())
57            {
58                $this->default_type = $type;
59                break;
60            }
61        }
62
63        parent::__construct($user);
64    }
65
66    /**
67     * {@inheritdoc}
68     */
69    protected function configure()
70    {
71        $this
72            ->setName('fixup:update-hashes')
73            ->setDescription($this->user->lang('CLI_DESCRIPTION_UPDATE_HASH_BCRYPT'))
74        ;
75    }
76
77    /**
78     * {@inheritdoc}
79     */
80    protected function execute(InputInterface $input, OutputInterface $output)
81    {
82        // Get count to be able to display progress
83        $sql = 'SELECT COUNT(user_id) AS count
84                FROM ' . USERS_TABLE . '
85                WHERE user_password ' . $this->db->sql_like_expression('$H$' . $this->db->get_any_char()) . '
86                    OR user_password ' . $this->db->sql_like_expression('$CP$' . $this->db->get_any_char());
87        $result = $this->db->sql_query($sql);
88        $total_update_passwords = $this->db->sql_fetchfield('count');
89        $this->db->sql_freeresult($result);
90
91        // Create progress bar
92        $progress_bar = new ProgressBar($output, $total_update_passwords);
93        $progress_bar->start();
94
95        $sql = 'SELECT user_id, user_password
96                FROM ' . USERS_TABLE . '
97                WHERE user_password ' . $this->db->sql_like_expression('$H$' . $this->db->get_any_char()) . '
98                    OR user_password ' . $this->db->sql_like_expression('$CP$' . $this->db->get_any_char());
99        $result = $this->db->sql_query($sql);
100
101        while ($row = $this->db->sql_fetchrow($result))
102        {
103            $old_hash = preg_replace('/^\$CP\$/', '', $row['user_password']);
104
105            // If stored hash type is unknown then it's md5 hash with no prefix
106            // First rehash it using $H$ as hash type identifier (salted_md5)
107            if (!$this->passwords_manager->detect_algorithm($old_hash))
108            {
109                $old_hash = $this->passwords_manager->hash($old_hash, '$H$');
110            }
111
112            $new_hash = $this->passwords_manager->hash($old_hash, [$this->default_type]);
113
114            $sql = 'UPDATE ' . USERS_TABLE . "
115                    SET user_password = '" . $this->db->sql_escape($new_hash) . "'
116                    WHERE user_id = " . (int) $row['user_id'];
117            $this->db->sql_query($sql);
118            $progress_bar->advance();
119        }
120
121        $this->config->set('update_hashes_last_cron', time());
122
123        $progress_bar->finish();
124
125        $output->writeln('<info>' . $this->user->lang('CLI_FIXUP_UPDATE_HASH_BCRYPT_SUCCESS') . '</info>');
126        return symfony_command::SUCCESS;
127    }
128}