Translated using Weblate (Estonian)
[phpmyadmin.git] / libraries / classes / TwoFactor.php
blobafdee353b57a3a586320d36b681ca8fbd6a1028b
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Two authentication factor handling
6 * @package PhpMyAdmin
7 */
8 declare(strict_types=1);
10 namespace PhpMyAdmin;
12 use PhpMyAdmin\Message;
13 use PhpMyAdmin\Plugins\TwoFactor\Application;
14 use PhpMyAdmin\Plugins\TwoFactor\Invalid;
15 use PhpMyAdmin\Plugins\TwoFactor\Key;
16 use PhpMyAdmin\Plugins\TwoFactorPlugin;
17 use PhpMyAdmin\UserPreferences;
18 use PragmaRX\Google2FAQRCode\Google2FA;
19 use Samyoul\U2F\U2FServer\U2FServer;
21 /**
22 * Two factor authentication wrapper class
24 * @package PhpMyAdmin
26 class TwoFactor
28 /**
29 * @var string
31 public $user;
33 /**
34 * @var array
36 public $config;
38 /**
39 * @var boolean
41 protected $_writable;
43 /**
44 * @var TwoFactorPlugin
46 protected $_backend;
48 /**
49 * @var array
51 protected $_available;
53 /**
54 * @var UserPreferences
56 private $userPreferences;
58 /**
59 * Creates new TwoFactor object
61 * @param string $user User name
63 public function __construct($user)
65 $this->userPreferences = new UserPreferences();
66 $this->user = $user;
67 $this->_available = $this->getAvailable();
68 $this->config = $this->readConfig();
69 $this->_writable = ($this->config['type'] == 'db');
70 $this->_backend = $this->getBackend();
73 /**
74 * Reads the configuration
76 * @return array
78 public function readConfig()
80 $result = [];
81 $config = $this->userPreferences->load();
82 if (isset($config['config_data']['2fa'])) {
83 $result = $config['config_data']['2fa'];
85 $result['type'] = $config['type'];
86 if (! isset($result['backend'])) {
87 $result['backend'] = '';
89 if (! isset($result['settings'])) {
90 $result['settings'] = [];
92 return $result;
95 /**
96 * Get any property of this class
98 * @param string $property name of the property
100 * @return mixed|void if property exist, value of the relevant property
102 public function __get($property)
104 switch ($property) {
105 case 'backend':
106 return $this->_backend;
107 case 'available':
108 return $this->_available;
109 case 'writable':
110 return $this->_writable;
111 case 'showSubmit':
112 $backend = $this->_backend;
113 return $backend::$showSubmit;
118 * Returns list of available backends
120 * @return array
122 public function getAvailable()
124 $result = [];
125 if ($GLOBALS['cfg']['DBG']['simple2fa']) {
126 $result[] = 'simple';
128 if (class_exists(Google2FA::class)) {
129 $result[] = 'application';
131 if (class_exists(U2FServer::class)) {
132 $result[] = 'key';
134 return $result;
138 * Returns list of missing dependencies
140 * @return array
142 public function getMissingDeps()
144 $result = [];
145 if (! class_exists(Google2FA::class)) {
146 $result[] = [
147 'class' => Application::getName(),
148 'dep' => 'pragmarx/google2fa-qrcode',
151 if (! class_exists('BaconQrCode\Renderer\Image\Png')) {
152 $result[] = [
153 'class' => Application::getName(),
154 'dep' => 'bacon/bacon-qr-code',
157 if (! class_exists(U2FServer::class)) {
158 $result[] = [
159 'class' => Key::getName(),
160 'dep' => 'samyoul/u2f-php-server',
163 return $result;
167 * Returns class name for given name
169 * @param string $name Backend name
171 * @return string
173 public function getBackendClass($name)
175 $result = TwoFactorPlugin::class;
176 if (in_array($name, $this->_available)) {
177 $result = 'PhpMyAdmin\\Plugins\\TwoFactor\\' . ucfirst($name);
178 } elseif (! empty($name)) {
179 $result = Invalid::class;
181 return $result;
185 * Returns backend for current user
187 * @return TwoFactorPlugin
189 public function getBackend()
191 $name = $this->getBackendClass($this->config['backend']);
192 return new $name($this);
196 * Checks authentication, returns true on success
198 * @param boolean $skip_session Skip session cache
200 * @return boolean
202 public function check($skip_session = false)
204 if ($skip_session) {
205 return $this->_backend->check();
207 if (empty($_SESSION['two_factor_check'])) {
208 $_SESSION['two_factor_check'] = $this->_backend->check();
210 return $_SESSION['two_factor_check'];
214 * Renders user interface to enter two-factor authentication
216 * @return string HTML code
218 public function render()
220 return $this->_backend->getError() . $this->_backend->render();
224 * Renders user interface to configure two-factor authentication
226 * @return string HTML code
228 public function setup()
230 return $this->_backend->getError() . $this->_backend->setup();
234 * Saves current configuration.
236 * @return true|Message
238 public function save()
240 return $this->userPreferences->persistOption('2fa', $this->config, null);
244 * Changes two-factor authentication settings
246 * The object might stay in partialy changed setup
247 * if configuration fails.
249 * @param string $name Backend name
251 * @return boolean
253 public function configure($name)
255 $this->config = [
256 'backend' => $name,
258 if ($name === '') {
259 $cls = $this->getBackendClass($name);
260 $this->config['settings'] = [];
261 $this->_backend = new $cls($this);
262 } else {
263 if (! in_array($name, $this->_available)) {
264 return false;
266 $cls = $this->getBackendClass($name);
267 $this->config['settings'] = [];
268 $this->_backend = new $cls($this);
269 if (! $this->_backend->configure()) {
270 return false;
273 $result = $this->save();
274 if ($result !== true) {
275 $result->display();
277 return true;
281 * Returns array with all available backends
283 * @return array
285 public function getAllBackends()
287 $all = array_merge([''], $this->available);
288 $backends = [];
289 foreach ($all as $name) {
290 $cls = $this->getBackendClass($name);
291 $backends[] = [
292 'id' => $cls::$id,
293 'name' => $cls::getName(),
294 'description' => $cls::getDescription(),
297 return $backends;