"Fossies" - the Fresh Open Source Software Archive 
Member "phpMyAdmin-5.1.0-all-languages/libraries/classes/TwoFactor.php" (24 Feb 2021, 6968 Bytes) of package /linux/www/phpMyAdmin-5.1.0-all-languages.zip:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the last
Fossies "Diffs" side-by-side code changes report for "TwoFactor.php":
5.0.4-english_vs_5.1.0-english.
1 <?php
2 /**
3 * Two authentication factor handling
4 */
5
6 declare(strict_types=1);
7
8 namespace PhpMyAdmin;
9
10 use PhpMyAdmin\Plugins\TwoFactor\Application;
11 use PhpMyAdmin\Plugins\TwoFactor\Invalid;
12 use PhpMyAdmin\Plugins\TwoFactor\Key;
13 use PhpMyAdmin\Plugins\TwoFactorPlugin;
14 use PragmaRX\Google2FAQRCode\Google2FA;
15 use Samyoul\U2F\U2FServer\U2FServer;
16 use function array_merge;
17 use function class_exists;
18 use function in_array;
19 use function ucfirst;
20
21 /**
22 * Two factor authentication wrapper class
23 */
24 class TwoFactor
25 {
26 /** @var string */
27 public $user;
28
29 /** @var array */
30 public $config;
31
32 /** @var bool */
33 protected $writable;
34
35 /** @var TwoFactorPlugin */
36 protected $backend;
37
38 /** @var array */
39 protected $available;
40
41 /** @var UserPreferences */
42 private $userPreferences;
43
44 /**
45 * Creates new TwoFactor object
46 *
47 * @param string $user User name
48 */
49 public function __construct($user)
50 {
51 global $dbi;
52
53 $dbi->initRelationParamsCache();
54
55 $this->userPreferences = new UserPreferences();
56 $this->user = $user;
57 $this->available = $this->getAvailableBackends();
58 $this->config = $this->readConfig();
59 $this->writable = ($this->config['type'] === 'db');
60 $this->backend = $this->getBackendForCurrentUser();
61 }
62
63 /**
64 * Reads the configuration
65 *
66 * @return array
67 */
68 public function readConfig()
69 {
70 $result = [];
71 $config = $this->userPreferences->load();
72 if (isset($config['config_data']['2fa'])) {
73 $result = $config['config_data']['2fa'];
74 }
75 $result['type'] = $config['type'];
76 if (! isset($result['backend'])) {
77 $result['backend'] = '';
78 }
79 if (! isset($result['settings'])) {
80 $result['settings'] = [];
81 }
82
83 return $result;
84 }
85
86 public function isWritable(): bool
87 {
88 return $this->writable;
89 }
90
91 public function getBackend(): TwoFactorPlugin
92 {
93 return $this->backend;
94 }
95
96 /**
97 * @return array
98 */
99 public function getAvailable(): array
100 {
101 return $this->available;
102 }
103
104 public function showSubmit(): bool
105 {
106 $backend = $this->backend;
107
108 return $backend::$showSubmit;
109 }
110
111 /**
112 * Returns list of available backends
113 *
114 * @return array
115 */
116 public function getAvailableBackends()
117 {
118 $result = [];
119 if ($GLOBALS['cfg']['DBG']['simple2fa']) {
120 $result[] = 'simple';
121 }
122 if (class_exists(Google2FA::class)) {
123 $result[] = 'application';
124 }
125 if (class_exists(U2FServer::class)) {
126 $result[] = 'key';
127 }
128
129 return $result;
130 }
131
132 /**
133 * Returns list of missing dependencies
134 *
135 * @return array
136 */
137 public function getMissingDeps()
138 {
139 $result = [];
140 if (! class_exists(Google2FA::class)) {
141 $result[] = [
142 'class' => Application::getName(),
143 'dep' => 'pragmarx/google2fa-qrcode',
144 ];
145 }
146 if (! class_exists('BaconQrCode\Renderer\Image\Png')) {
147 $result[] = [
148 'class' => Application::getName(),
149 'dep' => 'bacon/bacon-qr-code',
150 ];
151 }
152 if (! class_exists(U2FServer::class)) {
153 $result[] = [
154 'class' => Key::getName(),
155 'dep' => 'samyoul/u2f-php-server',
156 ];
157 }
158
159 return $result;
160 }
161
162 /**
163 * Returns class name for given name
164 *
165 * @param string $name Backend name
166 *
167 * @return string
168 */
169 public function getBackendClass($name)
170 {
171 $result = TwoFactorPlugin::class;
172 if (in_array($name, $this->available)) {
173 $result = 'PhpMyAdmin\\Plugins\\TwoFactor\\' . ucfirst($name);
174 } elseif (! empty($name)) {
175 $result = Invalid::class;
176 }
177
178 return $result;
179 }
180
181 /**
182 * Returns backend for current user
183 *
184 * @return TwoFactorPlugin
185 */
186 public function getBackendForCurrentUser()
187 {
188 $name = $this->getBackendClass($this->config['backend']);
189
190 return new $name($this);
191 }
192
193 /**
194 * Checks authentication, returns true on success
195 *
196 * @param bool $skip_session Skip session cache
197 *
198 * @return bool
199 */
200 public function check($skip_session = false)
201 {
202 if ($skip_session) {
203 return $this->backend->check();
204 }
205 if (empty($_SESSION['two_factor_check'])) {
206 $_SESSION['two_factor_check'] = $this->backend->check();
207 }
208
209 return $_SESSION['two_factor_check'];
210 }
211
212 /**
213 * Renders user interface to enter two-factor authentication
214 *
215 * @return string HTML code
216 */
217 public function render()
218 {
219 return $this->backend->getError() . $this->backend->render();
220 }
221
222 /**
223 * Renders user interface to configure two-factor authentication
224 *
225 * @return string HTML code
226 */
227 public function setup()
228 {
229 return $this->backend->getError() . $this->backend->setup();
230 }
231
232 /**
233 * Saves current configuration.
234 *
235 * @return true|Message
236 */
237 public function save()
238 {
239 return $this->userPreferences->persistOption('2fa', $this->config, null);
240 }
241
242 /**
243 * Changes two-factor authentication settings
244 *
245 * The object might stay in partially changed setup
246 * if configuration fails.
247 *
248 * @param string $name Backend name
249 *
250 * @return bool
251 */
252 public function configure($name)
253 {
254 $this->config = ['backend' => $name];
255 if ($name === '') {
256 $cls = $this->getBackendClass($name);
257 $this->config['settings'] = [];
258 $this->backend = new $cls($this);
259 } else {
260 if (! in_array($name, $this->available)) {
261 return false;
262 }
263 $cls = $this->getBackendClass($name);
264 $this->config['settings'] = [];
265 $this->backend = new $cls($this);
266 if (! $this->backend->configure()) {
267 return false;
268 }
269 }
270 $result = $this->save();
271 if ($result !== true) {
272 echo $result->getDisplay();
273 }
274
275 return true;
276 }
277
278 /**
279 * Returns array with all available backends
280 *
281 * @return array
282 */
283 public function getAllBackends()
284 {
285 $all = array_merge([''], $this->available);
286 $backends = [];
287 foreach ($all as $name) {
288 $cls = $this->getBackendClass($name);
289 $backends[] = [
290 'id' => $cls::$id,
291 'name' => $cls::getName(),
292 'description' => $cls::getDescription(),
293 ];
294 }
295
296 return $backends;
297 }
298 }