286 lines
11 KiB
PHP
Executable File
286 lines
11 KiB
PHP
Executable File
<?php
|
|
|
|
|
|
use Firebase\JWT\JWT;
|
|
use Firebase\JWT\Key;
|
|
use Firebase\JWT\ExpiredException;
|
|
use Firebase\JWT\SignatureInvalidException;
|
|
use Firebase\JWT\BeforeValidException;
|
|
|
|
define("MB", 1048576);
|
|
|
|
|
|
|
|
// ═══════════════════════════════════════════════════════════════
|
|
// authenticateJWT — دالة التحقق من التوكن
|
|
// ───────────────────────────────────────────────────────────────
|
|
// استبدل الدالة الموجودة في functions.php بهذه
|
|
// ───────────────────────────────────────────────────────────────
|
|
// طبقات التحقق بالترتيب:
|
|
// 1. وجود الـ JWT في Authorization header
|
|
// 2. صحة التوقيع وعدم انتهاء الصلاحية
|
|
// 3. صحة الـ Issuer
|
|
// 4. مطابقة بصمة الجهاز (X-Device-FP header)
|
|
// 5. مطابقة الـ HMAC — للـ wallet فقط (X-HMAC-Auth header)
|
|
// ───────────────────────────────────────────────────────────────
|
|
// جميع العمليات في الذاكرة — لا استعلامات DB
|
|
// ═══════════════════════════════════════════════════════════════
|
|
|
|
function authenticateJWT(bool $isReg = false): object
|
|
{
|
|
$keyPath = getenv('WALLET_SECRET_KEY_PATH');
|
|
$secretKey = '';
|
|
if ($keyPath && file_exists($keyPath)) {
|
|
$secretKey = trim(file_get_contents($keyPath));
|
|
}
|
|
if (!$secretKey) {
|
|
$secretKey = getenv('SECRET_KEY') ?: '';
|
|
}
|
|
$hmacSecret = getenv('SECRET_KEY_HMAC');
|
|
$fpPepper = getenv('FP_PEPPER');
|
|
|
|
error_log('[JWT_DEBUG] ── START authenticateJWT ──────────────────────────');
|
|
error_log('[JWT_DEBUG] isReg=' . ($isReg ? 'true' : 'false'));
|
|
error_log('[JWT_DEBUG] secretKey loaded: ' . (!empty($secretKey) ? 'YES (len=' . strlen($secretKey) . ')' : 'NO ❌'));
|
|
error_log('[JWT_DEBUG] hmacSecret loaded: ' . (!empty($hmacSecret) ? 'YES' : 'NO ❌'));
|
|
error_log('[JWT_DEBUG] fpPepper loaded: ' . (!empty($fpPepper) ? 'YES' : 'NO'));
|
|
|
|
if (!$secretKey || !$hmacSecret) {
|
|
http_response_code(500);
|
|
echo json_encode(['error' => 'Internal server configuration error.']);
|
|
exit;
|
|
}
|
|
|
|
// ── 1. استخراج الـ JWT ──────────────────────────────────────
|
|
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
|
|
$token = null;
|
|
|
|
if (preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
|
|
$token = $matches[1];
|
|
}
|
|
|
|
error_log('[JWT_DEBUG] Authorization header present: ' . (!empty($authHeader) ? 'YES' : 'NO ❌'));
|
|
error_log('[JWT_DEBUG] Token extracted: ' . ($token ? 'YES (len=' . strlen($token) . ')' : 'NO ❌'));
|
|
|
|
if (!$token) {
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Authorization token required']);
|
|
exit;
|
|
}
|
|
|
|
// ── 2. فك التشفير والتحقق ───────────────────────────────────
|
|
try {
|
|
$decoded = JWT::decode($token, new Key($secretKey, 'HS256'));
|
|
error_log('[JWT_DEBUG] JWT decode: SUCCESS ✅');
|
|
error_log('[JWT_DEBUG] JWT payload: ' . json_encode((array)$decoded));
|
|
|
|
} catch (ExpiredException $e) {
|
|
error_log('[JWT_DEBUG] JWT decode FAILED: ExpiredException ❌ | ' . $e->getMessage());
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Token expired']);
|
|
exit;
|
|
|
|
} catch (SignatureInvalidException $e) {
|
|
error_log('[JWT_DEBUG] JWT decode FAILED: SignatureInvalidException ❌ | ' . $e->getMessage());
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Invalid token signature']);
|
|
exit;
|
|
|
|
} catch (BeforeValidException $e) {
|
|
error_log('[JWT_DEBUG] JWT decode FAILED: BeforeValidException ❌ | ' . $e->getMessage());
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Token not yet valid']);
|
|
exit;
|
|
|
|
} catch (Exception $e) {
|
|
error_log('[JWT_DEBUG] JWT decode FAILED: Exception ❌ | ' . $e->getMessage());
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Invalid token']);
|
|
exit;
|
|
}
|
|
|
|
// ── 3. التحقق من الـ Issuer ─────────────────────────────────
|
|
$expectedIssuer = 'Tripz-Wallet';
|
|
$actualIssuer = $decoded->iss ?? '(missing)';
|
|
error_log('[JWT_DEBUG] Issuer check | expected=' . $expectedIssuer . ' | actual=' . $actualIssuer);
|
|
|
|
if ($actualIssuer !== $expectedIssuer) {
|
|
error_log('[JWT_DEBUG] Issuer MISMATCH ❌');
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Invalid token issuer']);
|
|
exit;
|
|
}
|
|
error_log('[JWT_DEBUG] Issuer: OK ✅');
|
|
|
|
// ── user_id ─────────────────────────────────────────────────
|
|
$userId = $decoded->user_id ?? $decoded->sub ?? null;
|
|
error_log('[JWT_DEBUG] user_id extracted: ' . ($userId ?? '(null) ❌'));
|
|
|
|
if (!$userId) {
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Invalid JWT payload']);
|
|
exit;
|
|
}
|
|
|
|
// ── 4. بصمة الجهاز ──────────────────────────────────────────
|
|
if (!$isReg && $fpPepper) {
|
|
$fpInToken = $decoded->fingerPrint ?? null;
|
|
$fpHeader = $_SERVER['HTTP_X_DEVICE_FP'] ?? null;
|
|
|
|
error_log('[JWT_DEBUG] FP check | fpInToken=' . ($fpInToken ?? '(null)'));
|
|
error_log('[JWT_DEBUG] FP check | X-Device-FP header=' . ($fpHeader ?? '(null)'));
|
|
|
|
if ($fpInToken !== null && $fpHeader !== null) {
|
|
$expectedFp = hash('sha256', $fpHeader . $fpPepper);
|
|
$fpMatch = hash_equals($expectedFp, $fpInToken);
|
|
|
|
error_log('[JWT_DEBUG] FP check | expectedFp=' . $expectedFp);
|
|
error_log('[JWT_DEBUG] FP check | match=' . ($fpMatch ? 'YES ✅' : 'NO ❌'));
|
|
|
|
if (!$fpMatch) {
|
|
error_log(sprintf(
|
|
'⚠️ [SECURITY] Device mismatch | user=%s | IP=%s',
|
|
$userId,
|
|
$_SERVER['REMOTE_ADDR'] ?? 'unknown'
|
|
));
|
|
http_response_code(403);
|
|
echo json_encode(['error' => 'Device mismatch']);
|
|
exit;
|
|
}
|
|
} else {
|
|
error_log('[JWT_DEBUG] FP check SKIPPED (token or header is null) ⚠️');
|
|
}
|
|
} else {
|
|
error_log('[JWT_DEBUG] FP check SKIPPED | isReg=' . ($isReg ? 'true' : 'false') . ' | fpPepper=' . (!empty($fpPepper) ? 'set' : 'empty'));
|
|
}
|
|
|
|
// ── 5. HMAC ─────────────────────────────────────────────────
|
|
$hmacHeader = $_SERVER['HTTP_X_HMAC_AUTH'] ?? null;
|
|
error_log('[JWT_DEBUG] HMAC header present: ' . ($hmacHeader !== null ? 'YES' : 'NO (skip)'));
|
|
|
|
if ($hmacHeader !== null) {
|
|
$expectedHmac = hash_hmac('sha256', $userId, $hmacSecret);
|
|
$hmacMatch = hash_equals($expectedHmac, $hmacHeader);
|
|
|
|
error_log('[JWT_DEBUG] HMAC check | match=' . ($hmacMatch ? 'YES ✅' : 'NO ❌'));
|
|
|
|
if (!$hmacMatch) {
|
|
error_log(sprintf(
|
|
'⚠️ [SECURITY] HMAC mismatch | user=%s | IP=%s',
|
|
$userId,
|
|
$_SERVER['REMOTE_ADDR'] ?? 'unknown'
|
|
));
|
|
http_response_code(403);
|
|
echo json_encode(['error' => 'Invalid HMAC']);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
error_log('[JWT_DEBUG] ── ALL CHECKS PASSED ✅ ─────────────────────────');
|
|
return $decoded;
|
|
}
|
|
|
|
|
|
|
|
|
|
function filterRequest($requestname, $type = 'string') {
|
|
if (isset($_POST[$requestname]) && !empty($_POST[$requestname])) {
|
|
$value = trim($_POST[$requestname]);
|
|
// Remove any control characters
|
|
$value = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $value);
|
|
// Remove any HTML or XML tags
|
|
$value = strip_tags($value);
|
|
// Escape any special characters
|
|
$value = htmlspecialchars($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
|
|
|
if ($type === 'numeric') {
|
|
if (filter_var($value, FILTER_VALIDATE_FLOAT) !== false) {
|
|
return $value;
|
|
}
|
|
} else {
|
|
return $value;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
function sendWhatsAppFromServer($to, $message)
|
|
{
|
|
// 1) قائمة السيرفرات المتاحة
|
|
$servers = [
|
|
"https://botmasa.intaleq.xyz/send",//rama tah
|
|
"https://botmasa2.intaleq.xyz/send",//shad
|
|
// "https://bootride.intaleq.xyz/send",//shahd bus
|
|
//"https://bot3.intaleq.xyz/send",//shahd
|
|
//"https://whatsapp.tripz-egypt.com/send"//tripz
|
|
];
|
|
|
|
// 2) اختيار عشوائي
|
|
$url = $servers[array_rand($servers)];
|
|
|
|
// 3) إعداد البيانات
|
|
$payload = [
|
|
"to" => $to,
|
|
"message" => $message
|
|
];
|
|
|
|
// 4) تنفيذ الطلب
|
|
$curl = curl_init();
|
|
curl_setopt_array($curl, [
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_CUSTOMREQUEST => "POST",
|
|
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
|
|
CURLOPT_HTTPHEADER => [
|
|
"Content-Type: application/json"
|
|
],
|
|
]);
|
|
|
|
$response = curl_exec($curl);
|
|
$err = curl_error($curl);
|
|
curl_close($curl);
|
|
|
|
// 5) تسجيل النتيجة
|
|
if ($err) {
|
|
error_log("[sendWhatsAppFromServer] cURL Error on $url: $err");
|
|
return false;
|
|
}
|
|
|
|
return json_decode($response, true);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////
|
|
|
|
function printFailure($message = "none")
|
|
{
|
|
echo json_encode(array("status" => "failure", "message" => $message));
|
|
}
|
|
function printSuccess($message = "none")
|
|
{
|
|
echo json_encode(array("status" => "success", "message" => $message));
|
|
}
|
|
|
|
function result($count)
|
|
{
|
|
if ($count > 0) {
|
|
printSuccess();
|
|
} else {
|
|
printFailure();
|
|
}
|
|
}
|
|
|
|
function sendEmail($from,$to, $title, $body)
|
|
{
|
|
// Sanitize $from to prevent email header injection
|
|
$from = str_replace(["\r", "\n", "\r\n"], '', $from);
|
|
$header = "From: $from" . "\n" . "CC: $from";
|
|
mail($to, $title, $body, $header);
|
|
}
|