PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.5
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.5
2.4.5 2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 All 69 releases
← All changes | app/Hooks/Handlers/EmailVerificationHandler.php +42 -2 2.2.0 → 2.4.5 View file →
@@ -8,10 +8,43 @@
8 8
9 9
10 10 class EmailVerificationHandler
11 11 {
12 + /**
13 + * Must match the "valid for 10 minutes" copy in the email below.
14 + */
15 + const CODE_TTL_SECONDS = 10 * MINUTE_IN_SECONDS;
16 +
12 17 public static function sendSignupEmailVerificationHtml($formData)
13 18 {
19 + $email = strtolower(trim($formData['email']));
20 +
21 + // The email bucket is the main throttle against mail-bombing an address. The IP
22 + // bucket is looser because offices and NATs share IPs.
23 + $ipKey = 'fs_signup_verify_ip_' . wp_hash(Helper::getIp());
24 + $emailKey = 'fs_signup_verify_email_' . wp_hash($email);
25 +
26 + /*
27 + * Site-wide hourly cap on signup verification mail, for attackers who rotate
28 + * both IP and address. Tripping it blocks signup for everyone, so keep it well
29 + * above organic traffic.
30 + *
31 + * @since v2.2.2
32 + * @param int $limit Signup verification emails allowed site-wide per hour.
33 + */
34 + $globalLimit = (int) apply_filters('fluent_support/signup_verification_hourly_limit', 100);
35 +
36 + // Check the global bucket last. Short-circuiting means only requests that pass
37 + // the IP and email gates count toward it, so one IP can't exhaust it.
38 + if (Helper::hitRateLimit($ipKey, 20)
39 + || Helper::hitRateLimit($emailKey, 5)
40 + || Helper::hitRateLimit('fs_signup_verify_global', $globalLimit, HOUR_IN_SECONDS)
41 + ) {
42 + wp_send_json([
43 + 'message' => __('Too many verification code requests. Please try again later.', 'fluent-support')
44 + ], 429);
45 + }
46 +
14 47 try {
15 48 $verifcationCode = str_pad(random_int(100123, 900987), 6, 0, STR_PAD_LEFT);
16 49 } catch (\Exception $e) {
17 50 $verifcationCode = str_pad(wp_rand(100123, 900987), 6, 0, STR_PAD_LEFT);
@@ -24,22 +57,29 @@
24 57
25 58 $data = array(
26 59 'login_hash' => $hash,
27 60 'status' => 'issued',
61 + 'email' => strtolower(trim($formData['email'])),
28 62 'ip_address' => Helper::getIp(),
29 63 'use_type' => 'signup_verification',
30 64 'used_count' => 0,
31 65 'two_fa_code_hash' => wp_hash_password($verifcationCode),
32 - 'valid_till' => gmdate('Y-m-d H:i:s', current_time('timestamp') + 10 * 60),
66 + 'valid_till' => gmdate('Y-m-d H:i:s', current_time('timestamp') + self::CODE_TTL_SECONDS),
33 67 'created_at' => current_time('mysql'),
34 68 'updated_at' => current_time('mysql')
35 69 );
36 70
37 - Meta::insert([
71 + $savedRecord = Meta::create([
38 72 'object_type' => 'fs_login_hashes',
39 73 'key' => $hash,
40 74 'value' => maybe_serialize($data)
41 75 ]);
76 +
77 + if (!$savedRecord || !$savedRecord->exists) {
78 + wp_send_json([
79 + 'message' => __('Unable to send verification code. Please try again later.', 'fluent-support')
80 + ], 500);
81 + }
42 82
43 83 // translators: %s is the site name
44 84 $mailSubject = apply_filters("fluent_support/signup_verification_mail_subject", sprintf(__('Your registration verification code for %s', 'fluent-support'), get_bloginfo('name')));
45 85