the files
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Campus_live_rewrite.api.server;
|
||||
|
||||
namespace Campus_live_rewrite.Controllers
|
||||
{
|
||||
// Patch handshake. CampusPatch (the DLL) POSTs here once at startup (main.cpp) with the
|
||||
// shared secret in the X-Campus-Patch header. The SERVER holds the real secret and compares:
|
||||
// a match answers 200, anything else answers 403. A DLL with the wrong/absent header is
|
||||
// denied here, and main.cpp aborts on a non-200 so that client never connects.
|
||||
//
|
||||
// The secret lives ONLY on the server (ConfigCampus.PatchSignature) - the DLL just echoes
|
||||
// what it was built with; the server is what decides.
|
||||
[ApiController]
|
||||
public class PatchController : ControllerBase
|
||||
{
|
||||
public const string HeaderName = "X-Campus-Patch";
|
||||
|
||||
[HttpPost("/api/patch/verify")]
|
||||
[HttpGet("/api/patch/verify")]
|
||||
public IActionResult Verify()
|
||||
{
|
||||
string sent = Request.Headers[HeaderName].FirstOrDefault() ?? "";
|
||||
string expected = ConfigCampus.PatchSignature ?? "";
|
||||
|
||||
string ip = Request.Headers["CF-Connecting-IP"].FirstOrDefault()
|
||||
?? Request.Headers["X-Forwarded-For"].FirstOrDefault()
|
||||
?? HttpContext.Connection.RemoteIpAddress?.ToString()
|
||||
?? "?";
|
||||
|
||||
bool ok = !string.IsNullOrEmpty(expected) && FixedTimeEquals(sent, expected);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
Console.WriteLine($"[patchverify] DENIED {ip} - signature {(string.IsNullOrEmpty(sent) ? "absent" : "mismatch")}");
|
||||
return StatusCode(StatusCodes.Status403Forbidden, new { ok = false });
|
||||
}
|
||||
|
||||
// Just a friendly startup check for the DLL - real enforcement is the per-request
|
||||
// X-Campus-Patch header validated in PatchGateMiddleware. No whitelist is kept.
|
||||
Console.WriteLine($"[patchverify] OK {ip}");
|
||||
return Ok(new { ok = true });
|
||||
}
|
||||
|
||||
// Constant-time compare so the secret can't be brute-forced a byte at a time by timing.
|
||||
private static bool FixedTimeEquals(string a, string b)
|
||||
{
|
||||
var ab = System.Text.Encoding.UTF8.GetBytes(a ?? "");
|
||||
var bb = System.Text.Encoding.UTF8.GetBytes(b ?? "");
|
||||
return System.Security.Cryptography.CryptographicOperations.FixedTimeEquals(ab, bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user