File: /www/wwwroot/q.autos58.cn/wp-content/plugins/link-manager/includes/class-lm-security.php
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class LM_Security {
/**
* Verify HMAC-SHA256 signature from the X-LM-Signature header.
*
* @param WP_REST_Request $request
* @return bool
*/
public static function verify_hmac( $request ) {
$signature = $request->get_header( 'X-LM-Signature' );
if ( empty( $signature ) ) {
return false;
}
$secret = get_option( 'lm_hmac_secret', '' );
if ( empty( $secret ) ) {
return false;
}
$body = $request->get_body();
$expected = hash_hmac( 'sha256', $body, $secret );
return hash_equals( $expected, $signature );
}
/**
* Check if the given IP is in the allowed list.
*
* @param string $ip
* @return bool
*/
public static function check_ip_whitelist( $ip ) {
$allowed = get_option( 'lm_allowed_ips', '' );
if ( empty( $allowed ) ) {
return true;
}
$list = array_map( 'trim', explode( ',', $allowed ) );
$list = array_filter( $list );
if ( empty( $list ) ) {
return true;
}
return in_array( $ip, $list, true );
}
/**
* Simple transient-based rate limiting.
*
* @param string $key
* @param int $max_requests
* @param int $window Time window in seconds.
* @return bool True if within limit, false if exceeded.
*/
public static function rate_limit( $key, $max_requests = 60, $window = 60 ) {
$transient_key = 'lm_rate_' . md5( $key );
$data = get_transient( $transient_key );
if ( false === $data ) {
set_transient( $transient_key, array( 'count' => 1, 'start' => time() ), $window );
return true;
}
if ( $data['count'] >= $max_requests ) {
return false;
}
$data['count']++;
$remaining = $window - ( time() - $data['start'] );
if ( $remaining > 0 ) {
set_transient( $transient_key, $data, $remaining );
}
return true;
}
/**
* Combined request verification: rate limit + HMAC + IP whitelist.
*
* @param WP_REST_Request $request
* @return true|WP_Error
*/
public static function verify_request( $request ) {
$ip = $request->get_header( 'X-Forwarded-For' );
if ( empty( $ip ) ) {
$ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
if ( ! self::rate_limit( $ip ) ) {
return new WP_Error(
'rate_limit_exceeded',
'Rate limit exceeded. Try again later.',
array( 'status' => 429 )
);
}
if ( ! self::verify_hmac( $request ) ) {
return new WP_Error(
'invalid_signature',
'Invalid HMAC signature.',
array( 'status' => 403 )
);
}
if ( ! self::check_ip_whitelist( $ip ) ) {
return new WP_Error(
'ip_not_allowed',
'IP address not in whitelist.',
array( 'status' => 403 )
);
}
return true;
}
}