/home/cp072267/public_html/dkrgroupholdings.com/wp-content/plugins/bbc/includes
Edit: /home/cp072267/public_html/dkrgroupholdings.com/wp-content/plugins/bbc/includes/class-bbc-auth.php (10338B)
409));
}
if (!function_exists('sodium_crypto_sign_verify_detached')) {
return new WP_Error('bbc_crypto_unavailable', 'Ed25519 verification is unavailable.', array('status' => 503));
}
$body = $request->get_json_params();
$site_id = isset($body['site_id']) ? sanitize_text_field($body['site_id']) : '';
$key_id = isset($body['key_id']) ? sanitize_text_field($body['key_id']) : '';
$public_key = isset($body['public_key']) ? sanitize_text_field($body['public_key']) : '';
$origin = isset($body['origin']) ? self::normalized_origin($body['origin']) : '';
$raw_key = self::base64url_decode($public_key);
if (!self::is_uuid($site_id) || !self::is_uuid($key_id) || $raw_key === false || strlen($raw_key) !== 32) {
return new WP_Error('bbc_invalid_enrollment', 'BBC enrollment data is invalid.', array('status' => 400));
}
if ($origin !== self::normalized_origin(home_url('/'))) {
return new WP_Error('bbc_origin_mismatch', 'BBC enrollment origin does not match this site.', array('status' => 400));
}
$identity = array(
'site_id' => $site_id,
'key_id' => $key_id,
'public_key' => $public_key,
'origin' => $origin,
'enrolled_at' => time(),
'update_base_url' => self::valid_update_url(isset($body['update_base_url']) ? $body['update_base_url'] : ''),
'update_public_key' => self::valid_public_key(isset($body['update_public_key']) ? $body['update_public_key'] : ''),
);
if (!add_option(BBC_OPTION_IDENTITY, $identity, '', false)) {
return new WP_Error('bbc_already_enrolled', 'BBC enrollment was locked by another request.', array('status' => 409));
}
return $identity;
}
public static function verify_command(WP_REST_Request $request)
{
$identity = get_option(BBC_OPTION_IDENTITY, false);
if (!is_array($identity)) {
return new WP_Error('bbc_not_enrolled', 'BBC is not enrolled.', array('status' => 403));
}
$raw_body = $request->get_body();
if (!is_string($raw_body) || strlen($raw_body) > self::MAX_BODY_BYTES) {
return new WP_Error('bbc_body_rejected', 'BBC command body is invalid.', array('status' => 413));
}
if (!self::consume_rate_limit()) {
return new WP_Error('bbc_rate_limited', 'BBC command rate exceeded.', array('status' => 429));
}
$body = json_decode($raw_body, true);
if (!is_array($body)) {
return new WP_Error('bbc_invalid_json', 'BBC command body is invalid.', array('status' => 400));
}
$command_id = isset($body['command_id']) ? (string) $body['command_id'] : '';
$site_id = isset($body['site_id']) ? (string) $body['site_id'] : '';
$origin = isset($body['origin']) ? self::normalized_origin($body['origin']) : '';
$expires_at = isset($body['expires_at']) ? intval($body['expires_at']) : 0;
$key_id = (string) $request->get_header('x-bbc-key-id');
$timestamp = intval($request->get_header('x-bbc-timestamp'));
$nonce = (string) $request->get_header('x-bbc-nonce');
$signature = self::base64url_decode($request->get_header('x-bbc-signature'));
$body_hash = hash('sha256', $raw_body);
$ledger = self::ledger();
$now = time();
if (!self::is_uuid($command_id) || !self::is_uuid($site_id) || !self::is_uuid($key_id) || !preg_match('/^[A-Za-z0-9_-]{22,}$/', $nonce)) {
return new WP_Error('bbc_bad_identity', 'BBC command identity is invalid.', array('status' => 403));
}
$verification_key = '';
if ($key_id === $identity['key_id']) {
$verification_key = $identity['public_key'];
} elseif (
isset($identity['previous_key_id'], $identity['previous_public_key'], $identity['previous_valid_until']) &&
$key_id === $identity['previous_key_id'] && intval($identity['previous_valid_until']) >= $now &&
isset($ledger[$command_id]) && hash_equals((string) $ledger[$command_id]['body_hash'], $body_hash)
) {
$verification_key = $identity['previous_public_key'];
}
if ($site_id !== $identity['site_id'] || $verification_key === '' || $origin !== $identity['origin']) {
return new WP_Error('bbc_identity_mismatch', 'BBC command identity does not match.', array('status' => 403));
}
if (abs($now - $timestamp) > self::MAX_CLOCK_SKEW || $expires_at < $now || $expires_at > $timestamp + self::MAX_CLOCK_SKEW) {
return new WP_Error('bbc_command_expired', 'BBC command timestamp is invalid.', array('status' => 403, 'server_time' => $now));
}
$canonical = "BBC1\nPOST\n/bbc/v1/command\n{$site_id}\n{$key_id}\n{$command_id}\n{$timestamp}\n{$expires_at}\n{$nonce}\n{$body_hash}";
$public_key = self::base64url_decode($verification_key);
if ($signature === false || $public_key === false || !sodium_crypto_sign_verify_detached($signature, $canonical, $public_key)) {
return new WP_Error('bbc_bad_signature', 'BBC command signature is invalid.', array('status' => 403));
}
if (isset($ledger[$command_id]) && hash_equals((string) $ledger[$command_id]['body_hash'], $body_hash)) {
$request->set_param('_bbc_cached_result', $ledger[$command_id]['result']);
return true;
}
foreach ($ledger as $entry) {
if (isset($entry['nonce']) && hash_equals((string) $entry['nonce'], $nonce)) {
return new WP_Error('bbc_replay', 'BBC command was already used.', array('status' => 409));
}
}
$request->set_param('_bbc_command_meta', array('body_hash' => $body_hash, 'nonce' => $nonce));
return true;
}
public static function record_result(WP_REST_Request $request, $result)
{
$body = $request->get_json_params();
$meta = $request->get_param('_bbc_command_meta');
if (!is_array($body) || !is_array($meta) || !isset($body['command_id'])) {
return;
}
$ledger = self::ledger();
$ledger[(string) $body['command_id']] = array(
'body_hash' => $meta['body_hash'],
'nonce' => $meta['nonce'],
'recorded_at' => time(),
'result' => $result,
);
uasort($ledger, function ($left, $right) {
return intval($right['recorded_at']) - intval($left['recorded_at']);
});
update_option(BBC_OPTION_COMMANDS, array_slice($ledger, 0, self::MAX_LEDGER_SIZE, true), false);
}
public static function rotate_key($key_id, $public_key)
{
$identity = get_option(BBC_OPTION_IDENTITY, false);
$raw_key = self::base64url_decode($public_key);
if (!is_array($identity) || !self::is_uuid($key_id) || $raw_key === false || strlen($raw_key) !== 32) {
return new WP_Error('bbc_invalid_key', 'BBC replacement key is invalid.', array('status' => 400));
}
$identity['previous_key_id'] = isset($identity['key_id']) ? $identity['key_id'] : '';
$identity['previous_public_key'] = isset($identity['public_key']) ? $identity['public_key'] : '';
$identity['previous_valid_until'] = time() + self::MAX_CLOCK_SKEW;
$identity['key_id'] = $key_id;
$identity['public_key'] = $public_key;
$identity['rotated_at'] = time();
update_option(BBC_OPTION_IDENTITY, $identity, false);
return true;
}
private static function ledger()
{
$ledger = get_option(BBC_OPTION_COMMANDS, array());
return is_array($ledger) ? $ledger : array();
}
private static function consume_rate_limit()
{
$minute = gmdate('YmdHi');
$ip = isset($_SERVER['REMOTE_ADDR']) ? (string) $_SERVER['REMOTE_ADDR'] : 'unknown';
$keys = array('bbc_rate_global_' . $minute => 60, 'bbc_rate_ip_' . hash('sha256', $ip) . '_' . $minute => 20);
foreach ($keys as $key => $limit) {
$count = intval(get_transient($key));
if ($count >= $limit) {
return false;
}
set_transient($key, $count + 1, 120);
}
return true;
}
private static function valid_update_url($value)
{
$value = esc_url_raw((string) $value, array('https'));
return strpos($value, 'https://') === 0 ? untrailingslashit($value) : '';
}
private static function valid_public_key($value)
{
$value = sanitize_text_field((string) $value);
$raw = self::base64url_decode($value);
return $raw !== false && strlen($raw) === 32 ? $value : '';
}
public static function is_uuid($value)
{
return is_string($value) && preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $value);
}
}