<?php
/*
 * net2ftp SSO handshake endpoint — STANDALONE.
 *
 * WHMCS server POSTs here with {login, pass, domain, exp, nonce, sig, back_url}.
 * We verify HMAC + IP allowlist + freshness, mint a one-time token to disk,
 * and echo {url: 'https://.../_n2f/_puq_launch.php?_sso=<token>'}.
 *
 * The launch page (_puq_launch.php) consumes the token and builds a self-
 * submitting POST form pointing at net2ftp's index.php with all the FTP
 * credentials pre-filled, so the customer's browser auto-submits and lands
 * inside net2ftp already authenticated — no login form ever rendered.
 *
 * Mirrors FileGator's sso.php — same HMAC scheme, same per-server secret,
 * separate token dir so the two engines don't share tokens.
 */

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');

$cfgFile = __DIR__ . '/_puq_config.php';
if (!is_file($cfgFile)) {
    http_response_code(500);
    echo json_encode(['status' => 'error', 'msg' => '_puq_config.php missing']);
    exit;
}
$cfg = require $cfgFile;
$hmacSecret = (string) ($cfg['hmac_secret'] ?? '');
$allowedIps = (array)  ($cfg['allowed_ips'] ?? []);
$tokenDir   = (string) ($cfg['token_dir']   ?? (__DIR__ . '/private/sso_sessions'));

if ($hmacSecret === '') {
    http_response_code(500);
    echo json_encode(['status' => 'error', 'msg' => 'hmac_secret not configured']);
    exit;
}

// --- IP allowlist ---
$sourceIp = $_SERVER['REMOTE_ADDR'] ?? '';
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $list = array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
    $sourceIp = $list[0] ?? $sourceIp;
}
if (!empty($allowedIps) && !in_array($sourceIp, $allowedIps, true)) {
    http_response_code(403);
    echo json_encode(['status' => 'error', 'msg' => 'IP not allowed: ' . $sourceIp]);
    exit;
}

// --- POST fields ---
$login   = (string) ($_POST['login']    ?? '');
$pass    = (string) ($_POST['pass']     ?? '');
$domain  = (string) ($_POST['domain']   ?? '');
$exp     = (int)    ($_POST['exp']      ?? 0);
$nonce   = (string) ($_POST['nonce']    ?? '');
$sig     = (string) ($_POST['sig']      ?? '');
$backUrl = (string) ($_POST['back_url'] ?? '');

if ($login === '' || $pass === '' || $domain === '' || $exp <= 0 || $nonce === '' || $sig === '') {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'msg' => 'missing fields']);
    exit;
}
if ($exp < time()) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'msg' => 'request expired']);
    exit;
}

$canonical = $login . '|' . $pass . '|' . $domain . '|' . $exp . '|' . $nonce;
$expected  = hash_hmac('sha256', $canonical, $hmacSecret);
if (!hash_equals($expected, $sig)) {
    http_response_code(403);
    echo json_encode(['status' => 'error', 'msg' => 'invalid signature']);
    exit;
}

// --- Mint single-use token ---
if (!is_dir($tokenDir)) @mkdir($tokenDir, 0750, true);
if (!is_writable($tokenDir)) {
    http_response_code(500);
    echo json_encode(['status' => 'error', 'msg' => 'token dir not writable: ' . $tokenDir]);
    exit;
}
$token = bin2hex(random_bytes(32));
$file  = $tokenDir . '/' . $token . '.json';
$cleanBack = '';
if ($backUrl !== '' && strlen($backUrl) <= 2048
    && preg_match('#^https?://[^\s<>"]+$#i', $backUrl)) {
    $cleanBack = $backUrl;
}
$payload = [
    'login'    => $login,
    'pass'     => $pass,
    'domain'   => $domain,
    'back_url' => $cleanBack,
    'expires'  => time() + 60,
];
if (file_put_contents($file, json_encode($payload), LOCK_EX) === false) {
    http_response_code(500);
    echo json_encode(['status' => 'error', 'msg' => 'token persist failed']);
    exit;
}
@chmod($file, 0640);

// --- GC old tokens 1-in-10 ---
if (random_int(0, 9) === 0) {
    $cutoff = time() - 300;
    foreach (glob($tokenDir . '/*.json') ?: [] as $f) {
        if (@filemtime($f) < $cutoff) @unlink($f);
    }
}

// --- Build launch URL ---
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) $scheme = $_SERVER['HTTP_X_FORWARDED_PROTO'];
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$base = $_SERVER['REQUEST_URI'] ?? '/_puq_sso.php';
// /_n2f/_puq_sso.php → /_n2f/
$base = preg_replace('#/_puq_sso(?:\.php)?(?:\?.*)?$#', '/', $base);
if ($base === '') $base = '/';
if (substr($base, -1) !== '/') $base .= '/';

$url = $scheme . '://' . $host . $base . '_puq_launch.php?_sso=' . urlencode($token);
echo json_encode(['status' => 'success', 'url' => $url]);
