PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 261011
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v261011
261011 261001 260927 260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 All 192 releases
← All changes | src/includes/classes/register-access.inc.php +56 -2 260814 → 261011 View file →
@@ -28,8 +28,62 @@
28 28 */
29 29 class c_ws_plugin__s2member_register_access
30 30 {
31 31 /**
32 + * Encrypts and authenticates a registration link or cookie value.
33 + *
34 + * @package s2Member\Registrations
35 + * @since 261006
36 + *
37 + * @param string $string Value to encrypt.
38 + * @param string $purpose Registration context: `link` or the cookie field name.
39 + * @return string Authenticated encrypted token, or an empty string for an empty value.
40 + */
41 + public static function encrypt_token($string, $purpose)
42 + {
43 + $string = is_scalar($string) ? (string)$string : '';
44 + if($string === '' || !is_string($purpose) || $purpose === '')
45 + return '';
46 +
47 + $encrypted = c_ws_plugin__s2member_utils_encryption::encrypt($string);
48 + if($encrypted === '')
49 + return '';
50 + $payload = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode($encrypted);
51 + //261006.0428 Authenticate even older-runtime encryption; use a separate WordPress salt because legacy ciphertext can expose its encryption key.
52 + $signature = hash_hmac('sha256', 's2member:registration:v1:'.$purpose.':'.$payload, wp_salt('auth'));
53 + return 's2reg1.'.$payload.'.'.$signature;
54 + }
55 +
56 + /**
57 + * Verifies a registration token before decrypting it.
58 + *
59 + * @package s2Member\Registrations
60 + * @since 261006
61 + *
62 + * @param string $token Encrypted registration token.
63 + * @param string $purpose Expected registration context: `link` or the cookie field name.
64 + * @return string Verified plaintext, or an empty string for an invalid token.
65 + */
66 + public static function decrypt_token($token, $purpose)
67 + {
68 + if(!is_string($token) || $token === '' || !is_string($purpose) || $purpose === '')
69 + return '';
70 +
71 + if(strpos($token, 's2reg1.') === 0)
72 + {
73 + $parts = explode('.', $token);
74 + if(count($parts) !== 3 || $parts[1] === '' || !preg_match('/^[a-f0-9]{64}$/D', $parts[2]))
75 + return '';
76 + $signature = hash_hmac('sha256', 's2member:registration:v1:'.$purpose.':'.$parts[1], wp_salt('auth'));
77 + if(!hash_equals($signature, $parts[2]))
78 + return '';
79 + return c_ws_plugin__s2member_utils_encryption::decrypt(c_ws_plugin__s2member_utils_strings::base64_url_safe_decode($parts[1]));
80 + }
81 + //261006.0428 Existing authenticated Defuse registrations remain valid; unsigned legacy registrations must never reach the fallback decryptor.
82 + return c_ws_plugin__s2member_utils_defuse::decrypt($token);
83 + }
84 +
85 + /**
32 86 * Generates Registration Access Links.
33 87 *
34 88 * @package s2Member\Registrations
35 89 * @since 3.5
@@ -49,9 +103,9 @@
49 103 unset($__refs, $__v);
50 104
51 105 if($subscr_gateway && is_string($subscr_gateway) && $subscr_id && is_string($subscr_id) && $custom && is_string($custom) && $item_number && (is_string($item_number) || is_numeric($item_number)))
52 106 {
53 - $register = c_ws_plugin__s2member_utils_encryption::encrypt('subscr_gateway_subscr_id_custom_item_number_time:.:|:.:'.$subscr_gateway.':.:|:.:'.$subscr_id.':.:|:.:'.$custom.':.:|:.:'.$item_number.':.:|:.:'.strtotime('now'));
107 + $register = self::encrypt_token('subscr_gateway_subscr_id_custom_item_number_time:.:|:.:'.$subscr_gateway.':.:|:.:'.$subscr_id.':.:|:.:'.$custom.':.:|:.:'.$item_number.':.:|:.:'.strtotime('now'), 'link');
54 108
55 109 $register_link = home_url('/?s2member_register='.urlencode($register)); // Generate long URL/link.
56 110 $now = strtotime('now');
57 111 $register_link_exp_time = apply_filters('ws_plugin__s2member_register_link_exp_time', '2 days', get_defined_vars());
@@ -112,9 +166,9 @@
112 166
113 167 do_action('ws_plugin__s2member_before_reg_cookies_ok', get_defined_vars());
114 168
115 169 if(isset ($_COOKIE['s2member_subscr_gateway'], $_COOKIE['s2member_subscr_id'], $_COOKIE['s2member_custom'], $_COOKIE['s2member_item_number']))
116 - if(($subscr_gateway = c_ws_plugin__s2member_utils_encryption::decrypt((string)$_COOKIE['s2member_subscr_gateway'])) && ($subscr_id = c_ws_plugin__s2member_utils_encryption::decrypt((string)$_COOKIE['s2member_subscr_id'])) && preg_match('/^'.preg_quote(preg_replace('/\:([0-9]+)$/', '', $_SERVER['HTTP_HOST']), '/').'/i', ($custom = c_ws_plugin__s2member_utils_encryption::decrypt((string)$_COOKIE['s2member_custom']))) && preg_match($GLOBALS['WS_PLUGIN__']['s2member']['c']['membership_item_number_w_level_regex'], ($item_number = c_ws_plugin__s2member_utils_encryption::decrypt((string)$_COOKIE['s2member_item_number']))) && !$wpdb->get_var("SELECT `user_id` FROM `".$wpdb->usermeta."` WHERE `meta_key` = '".$wpdb->prefix."s2member_subscr_id' AND `meta_value` = '".esc_sql($subscr_id)."' LIMIT 1"))
170 + if(($subscr_gateway = self::decrypt_token((string)$_COOKIE['s2member_subscr_gateway'], 'subscr_gateway')) && ($subscr_id = self::decrypt_token((string)$_COOKIE['s2member_subscr_id'], 'subscr_id')) && preg_match('/^'.preg_quote(preg_replace('/\:([0-9]+)$/', '', $_SERVER['HTTP_HOST']), '/').'/i', ($custom = self::decrypt_token((string)$_COOKIE['s2member_custom'], 'custom'))) && preg_match($GLOBALS['WS_PLUGIN__']['s2member']['c']['membership_item_number_w_level_regex'], ($item_number = self::decrypt_token((string)$_COOKIE['s2member_item_number'], 'item_number'))) && !$wpdb->get_var("SELECT `user_id` FROM `".$wpdb->usermeta."` WHERE `meta_key` = '".$wpdb->prefix."s2member_subscr_id' AND `meta_value` = '".esc_sql($subscr_id)."' LIMIT 1"))
117 171 $reg_cookies_ok = $reg_cookies = array('subscr_gateway' => $subscr_gateway, 'subscr_id' => $subscr_id, 'custom' => $custom, 'item_number' => $item_number);
118 172
119 173 return apply_filters('ws_plugin__s2member_reg_cookies_ok', !empty($reg_cookies_ok) && !empty($reg_cookies) ? $reg_cookies : FALSE, get_defined_vars());
120 174 }