PluginProbe
WebTotem Security / 2.4.14
WebTotem Security v2.4.14
3.0.2 3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 All 110 releases
wt-security / lib / login / Login.php

Login.php in WebTotem Security 2.4.14, at lib/login/Login.php

234 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('WEBTOTEM_INIT') || WEBTOTEM_INIT !== true) {
3 if (!headers_sent()) {
4 header('HTTP/1.1 403 Forbidden');
5 }
6 die("Protected By WebTotem!");
7 }
8
9 require_once 'Captcha.php';
10 require_once 'BFProtection.php';
11 require_once 'GoogleAuthenticator.php';
12
13 /**
14 * WebTotem Login class for Wordpress.
15 */
16 class WebTotemLogin {
17
18 const RECOVERY_CODE_SIZE = 8;
19 const RECOVERY_CODE_COUNT = 5;
20
21 /**
22 * Generates a new set of recovery codes and saves them to $user if provided.
23 *
24 * @param int $count
25 * @return array
26 */
27 public static function generate_recovery_codes($count = self::RECOVERY_CODE_COUNT) {
28 $codes = array();
29 for ($i = 0; $i < $count; $i++) {
30 $codes[] = self::random_bytes(self::RECOVERY_CODE_SIZE);
31 }
32
33 return $codes;
34 }
35
36 /**
37 * Save user's 2fa data.
38 *
39 * @param int $user_id
40 * User ID.
41 *
42 * @return bool
43 * Returns TRUE after save settings.
44 */
45 public static function saveData( int $user_id, $codes, $secret ) {
46
47 $data = json_decode(WebTotemOption::getOption('two_factor_data'), true) ?: [];
48 $data[$user_id]['recovery'] = $codes;
49 $data[$user_id]['secret'] = $secret;
50 WebTotemOption::setOptions(['two_factor_data' => json_encode($data)]);
51
52 return TRUE;
53 }
54
55 /**
56 * Delete user's 2fa data.
57 *
58 * @param int $user_id
59 * User ID.
60 *
61 * @return bool
62 * Returns TRUE after save settings.
63 */
64 public static function delete( int $user_id ) {
65 $data = json_decode(WebTotemOption::getOption('two_factor_data'), true) ?: [];
66
67 if(isset($data[$user_id])) {
68 unset($data[$user_id]);
69 }
70 WebTotemOption::setOptions(['two_factor_data' => json_encode($data)]);
71
72 return TRUE;
73 }
74
75 /**
76 * Get user's 2fa data.
77 *
78 * @param int $user_id
79 * User ID.
80 *
81 * @return mixed
82 * Returns saved data by option name.
83 */
84 public static function getData($user_id) {
85
86 $data = json_decode(WebTotemOption::getOption('two_factor_data'), true) ?: [];
87
88 if(array_key_exists($user_id, $data)){
89 return $data[$user_id];
90 }
91
92 return false;
93 }
94
95 /**
96 * has user 2FA activated.
97 *
98 * @param WP_User $user
99 * User.
100 *
101 * @return bool
102 */
103 public static function hasUser2faActivated($user){
104 if(self::getData($user->ID)){
105 return true;
106 } else {
107 return false;
108 }
109 }
110
111
112 /**
113 * Check 2FA code by user.
114 *
115 * @param WP_User $user
116 * User.
117 *
118 * @return bool
119 */
120 public static function check2faCode($user, $code){
121 $data = self::getData($user->ID);
122 $g = new GoogleAuthenticator();
123 $code = trim($code);
124
125 if(strlen($code) === 6 and $g->checkCode($data['secret'], $code)) {
126 return true;
127 } else if (strlen($code) >= 16) {
128 $code = str_replace(' ', '', $code);
129 $recovery = explode(',', $data['recovery']);
130 $is_verify = false;
131 foreach ($recovery as $key => $recoveryCode){
132 if($recoveryCode === $code){
133 $is_verify = true;
134 break;
135 }
136 }
137 if($is_verify){
138 // Delete this code from the database.
139 unset($recovery[$key]);
140 $recovery = implode(',', $recovery);
141 self::saveData($user->ID, $recovery, $data['secret']);
142
143 return true;
144 }
145 }
146
147 return false;
148 }
149
150 /**
151 * Get recovery data.
152 *
153 * @param WP_User $user
154 * User.
155 *
156 * @return array
157 * Returns saved data by option name.
158 */
159 public static function getRecoveryData( $user ){
160 $recovery = self::generate_recovery_codes();
161
162 $fileContents = sprintf(__('Two-Factor Authentication Recovery Codes. %s (%s)', 'wtotem'), home_url(), $user->user_login) . "\r\n";
163 $fileContents .= "\r\n" . __('Each line is a single recovery code, with optional spaces for readability. Your recovery codes are:', 'wtotem') . "\r\n\r\n";
164 $recoveryBlocks = [];
165 foreach ($recovery as $c) {
166 $hex = bin2hex( $c );
167 $blocks = str_split( $hex, 4 );
168 $blocks = implode( ' ', $blocks );
169 $fileContents .= $blocks . "\r\n";
170 $recoveryBlocks[] = $blocks;
171 }
172
173 $fileContents = str_replace("\n", "\\n", str_replace("\r", "\\r", addslashes($fileContents)));
174
175 return [
176 'fileName' => WEBTOTEM_SITE_DOMAIN . '_' . $user->user_login . '_recovery_codes.txt',
177 'fileContents' => $fileContents,
178 'recovery' => implode(',', array_map(function($c) { return bin2hex($c); }, $recovery)),
179 'blocks' => $recoveryBlocks,
180 ];
181
182 }
183
184 /**
185 * @throws Exception
186 */
187 public static function random_bytes($length) {
188 $length = (int) $length;
189 if (function_exists('random_bytes')) {
190 $rand = random_bytes($length);
191 if (is_string($rand)) {
192 return $rand;
193 }
194 }
195
196 $return = '';
197 for ($i = 0; $i < $length; $i++) {
198 $return .= chr(mt_rand(0, 255));
199 }
200 return $return;
201 }
202
203 /**
204 * Get two factor authenticator data.
205 *
206 * @return array
207 * Returns google authenticator data.
208 */
209 public static function getTwoFactorData() {
210
211 $user = wp_get_current_user();
212
213 if($data = self::getData($user->ID)) {
214
215 return [
216 'isActivated' => true,
217 'recovery' => explode(',', $data['recovery']),
218 ];
219 }
220
221 $data = self::getRecoveryData($user);
222 $g = new GoogleAuthenticator();
223
224 $host = WebTotemOption::getMainHost();
225 $data['secret'] = $g->generateSecret();
226 $data['qr_url'] = $g->getURL( $user->user_login, $host['name'], $data['secret'] );
227
228 $data['isActivated'] = false;
229
230 return $data;
231
232 }
233
234 }