PluginProbe
WebTotem Security / 2.4.13
WebTotem Security v2.4.13
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.13, at lib/login/Login.php

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