<?php
/**
 * 판매자센터 → VPN 서버 SSO 자동로그인 토큰 발급 및 리디렉션
 * URL: /mylib/ikev2_partner_server_sso.php?vs_no=<vs_no>
 *
 * 동작: 로그인된 판매자가 자신 소유의 VPN 서버로 자동 로그인할 때 사용.
 * 웹페이지 로그인(아이디/비밀번호)과 달리 HMAC-SHA256 서명 토큰 방식을 사용하며,
 * VPN 서버의 sso_login.php가 토큰을 검증하고 세션을 생성합니다.
 */

define('_GNUBOARD_', true);
include_once(__DIR__ . '/../common.php');

header('Content-Type: text/html; charset=utf-8');

// ── 1. 로그인 확인 ─────────────────────────────────────────────
if ($is_guest) {
    goto_url(G5_BBS_URL . '/login.php?url=' . urlencode($_SERVER['REQUEST_URI']));
}

// ── 2. 파라미터 검증 ──────────────────────────────────────────
$vs_no = (int)($_GET['vs_no'] ?? 0);
if ($vs_no <= 0) {
    alert('잘못된 요청입니다.');
}

// ── 3. 서버 소유권 확인 ──────────────────────────────────────
$mb_id = $member['mb_id'];
$mb_id_esc = sql_real_escape_string($mb_id);
$vs_no_int = (int)$vs_no;

$row = sql_fetch(
    "SELECT vs_no, vs_alias, vs_ip, vs_hostname, vs_key, vs_admin_url
       FROM {$g5['apms_vpn_server']}
      WHERE vs_no = {$vs_no_int} AND pt_id = '{$mb_id_esc}'",
    false
);
if (!is_array($row) || empty($row['vs_no'])) {
    alert('해당 VPN 서버에 대한 접근 권한이 없습니다.');
}

$vs_key      = trim((string)$row['vs_key']);
$vs_admin_url = trim((string)$row['vs_admin_url']);
if ($vs_key === '' || $vs_admin_url === '') {
    alert('서버 키 또는 관리 URL이 설정되지 않았습니다. 서버를 재등록해주세요.');
}

// ── 4. SSO 수신 URL 구성 ─────────────────────────────────────
// vs_admin_url 의 파일명을 sso_login.php 로 교체
$sso_base = rtrim(dirname($vs_admin_url), '/');
$sso_url  = $sso_base . '/sso_login.php';

// ── 5. 공유 비밀키 로드 (IKEV2_SHOP_SYNC_SHARED_SECRET) ──────
$shared_secret = '';
if (isset($_SERVER['IKEV2_SHOP_SYNC_SHARED_SECRET']) && $_SERVER['IKEV2_SHOP_SYNC_SHARED_SECRET'] !== '') {
    $shared_secret = $_SERVER['IKEV2_SHOP_SYNC_SHARED_SECRET'];
} elseif (isset($_ENV['IKEV2_SHOP_SYNC_SHARED_SECRET']) && $_ENV['IKEV2_SHOP_SYNC_SHARED_SECRET'] !== '') {
    $shared_secret = $_ENV['IKEV2_SHOP_SYNC_SHARED_SECRET'];
} else {
    $v = getenv('IKEV2_SHOP_SYNC_SHARED_SECRET');
    if (is_string($v) && $v !== '') $shared_secret = $v;
}
if ($shared_secret === '') {
    $env_path = __DIR__ . '/../.env';
    if (is_readable($env_path)) {
        foreach (@file($env_path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [] as $line) {
            $line = trim((string)$line);
            if ($line === '' || $line[0] === '#') continue;
            $pos = strpos($line, '=');
            if ($pos === false) continue;
            $k = trim(substr($line, 0, $pos));
            if ($k !== 'IKEV2_SHOP_SYNC_SHARED_SECRET') continue;
            $v = trim(substr($line, $pos + 1));
            if (strlen($v) >= 2 && (($v[0] === '"' && substr($v,-1) === '"') || ($v[0] === "'" && substr($v,-1) === "'"))) {
                $v = substr($v, 1, -1);
            }
            $shared_secret = $v;
            break;
        }
    }
}
if ($shared_secret === '') {
    alert('SSO 설정 오류: 공유 비밀키가 설정되지 않았습니다. 관리자에게 문의하세요.');
}

// ── 6. HMAC 토큰 생성 ────────────────────────────────────────
$ts    = time();
$nonce = bin2hex(random_bytes(16));
// payload: 목적구분:판매자ID:타임스탬프:nonce
$payload   = 'vpnsso:' . $mb_id . ':' . $ts . ':' . $nonce;
$hmac_key  = $vs_key . ':' . $shared_secret;
$token     = hash_hmac('sha256', $payload, $hmac_key);

// ── 7. SSO 로그 기록 (DB) ────────────────────────────────────
sso_ensure_log_table($g5['apms_vpn_sso_log']);
$client_ip  = $_SERVER['REMOTE_ADDR'] ?? '';
$user_agent = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 500);
sql_query(
    "INSERT INTO {$g5['apms_vpn_sso_log']}
     (vs_no, vs_alias, login_type, actor, mb_id, client_ip, user_agent, nonce_prefix, sso_at)
     VALUES (
       {$vs_no_int},
       '" . sql_real_escape_string((string)$row['vs_alias']) . "',
       'sso',
       '" . sql_real_escape_string($mb_id) . "',
       '" . sql_real_escape_string($mb_id) . "',
       '" . sql_real_escape_string($client_ip) . "',
       '" . sql_real_escape_string($user_agent) . "',
       '" . sql_real_escape_string(substr($nonce, 0, 8)) . "',
       '" . G5_TIME_YMDHIS . "'
     )"
);

// ── 8. VPN 서버 SSO 수신 URL로 리디렉션 ────────────────────
$redirect = $sso_url
    . '?token='  . urlencode($token)
    . '&mb_id='  . urlencode($mb_id)
    . '&ts='     . $ts
    . '&nonce='  . urlencode($nonce);

header('Location: ' . $redirect);
exit;

// ─────────────────────────────────────────────────────────────
function sso_ensure_log_table($table) {
    $exists = sql_fetch("SHOW TABLES LIKE '{$table}'", false);
    if (is_array($exists) && count($exists) > 0) return;
    sql_query("
        CREATE TABLE IF NOT EXISTS `{$table}` (
          `log_no`       int(11)      NOT NULL AUTO_INCREMENT,
          `vs_no`        int(11)      NOT NULL DEFAULT '0',
          `vs_alias`     varchar(100) NOT NULL DEFAULT '',
          `mb_id`        varchar(20)  NOT NULL DEFAULT '',
          `client_ip`    varchar(45)  NOT NULL DEFAULT '',
          `user_agent`   varchar(500) NOT NULL DEFAULT '',
          `nonce_prefix` varchar(16)  NOT NULL DEFAULT '' COMMENT '추적용 nonce 앞 8자리',
          `sso_at`       datetime     NOT NULL,
          PRIMARY KEY (`log_no`),
          KEY `mb_id`    (`mb_id`),
          KEY `vs_no`    (`vs_no`),
          KEY `sso_at`   (`sso_at`)
        ) ENGINE=MyISAM DEFAULT CHARSET=utf8
    ");
}
