mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-08-01 09:48:37 +00:00
Add Server Digest support. Note that the server digest key must be added to an environment variable.
This commit is contained in:
parent
90201150cc
commit
37abf75071
5 changed files with 63 additions and 27 deletions
|
@ -13,8 +13,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
||||||
public IActionResult NetworkSettings()
|
public IActionResult NetworkSettings()
|
||||||
{
|
{
|
||||||
|
var hostname = this.Request.Host;
|
||||||
return this.Ok(
|
return this.Ok(
|
||||||
"ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels true\nAllowModeratedPoppetItems true\nShowLevelBoos true\nTIMEOUT_WAIT_FOR_JOIN_RESPONSE_FROM_PREV_PARTY_HOST 50.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_HOST 30.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_MEMBER 45.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN_FRIEND 15.0\nTIMEOUT_WAIT_FOR_CONNECTION_FROM_HOST 30.0\nTIMEOUT_WAIT_FOR_ROOM_ID_TO_JOIN 60.0\nTIMEOUT_WAIT_FOR_GET_NUM_PLAYERS_ONLINE 60.0\nTIMEOUT_WAIT_FOR_SIGNALLING_CONNECTIONS 120.0\nTIMEOUT_WAIT_FOR_PARTY_DATA 60.0\nTIME_TO_WAIT_FOR_LEAVE_MESSAGE_TO_COME_BACK 20.0\nTIME_TO_WAIT_FOR_FOLLOWING_REQUESTS_TO_ARRIVE 30.0\nTIMEOUT_WAIT_FOR_FINISHED_MIGRATING_HOST 30.0\nTIMEOUT_WAIT_FOR_PARTY_LEADER_FINISH_JOINING 45.0\nTIMEOUT_WAIT_FOR_QUICKPLAY_LEVEL 60.0\nTIMEOUT_WAIT_FOR_PLAYERS_TO_JOIN 30.0\nTIMEOUT_WAIT_FOR_DIVE_IN_PLAYERS 120.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 30.0\nTIMEOUT_DIVE_IN_TOTAL 1000000.0\nTIMEOUT_WAIT_FOR_SOCKET_CONNECTION 120.0\nTIMEOUT_WAIT_FOR_REQUEST_RESOURCE_MESSAGE 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_GET_RESOURCE_LIST 120.0\nTIMEOUT_WAIT_FOR_CLIENT_TO_LOAD_RESOURCES 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_SAVE_GAME_STATE 30.0\nTIMEOUT_WAIT_FOR_ADD_PLAYERS_TO_TAKE 30.0\nTIMEOUT_WAIT_FOR_UPDATE_FROM_CLIENT 90.0\nTIMEOUT_WAIT_FOR_HOST_TO_GET_RESOURCE_LIST 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_SAVE_GAME_STATE 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_ADD_US 30.0\nTIMEOUT_WAIT_FOR_UPDATE 60.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN 50.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_PRESENCE 60.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_CONNECTION 120.0\nSECONDS_BETWEEN_PINS_AWARDED_UPLOADS 300.0\nEnableKeepAlive true\nAllowVoIPRecordingPlayback true\nCDNHostName localhost\nTelemetryServer localhost\nOverheatingThresholdDisallowMidgameJoin 0.95\nMaxCatchupFrames 3\nMaxLagBeforeShowLoading 23\nMinLagBeforeHideLoading 30\nLagImprovementInflectionPoint -1.0\nFlickerThreshold 2.0\nClosedDemo2014Version 1\nClosedDemo2014Expired false\nEnablePlayedFilter true\nEnableCommunityDecorations true\nGameStateUpdateRate 10.0\nGameStateUpdateRateWithConsumers 1.0\nDisableDLCPublishCheck false\nEnableDiveIn true\nEnableHackChecks false");
|
"ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels true\nAllowModeratedPoppetItems true\nShowLevelBoos true\nTIMEOUT_WAIT_FOR_JOIN_RESPONSE_FROM_PREV_PARTY_HOST 50.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_HOST 30.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_MEMBER 45.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN_FRIEND 15.0\nTIMEOUT_WAIT_FOR_CONNECTION_FROM_HOST 30.0\nTIMEOUT_WAIT_FOR_ROOM_ID_TO_JOIN 60.0\nTIMEOUT_WAIT_FOR_GET_NUM_PLAYERS_ONLINE 60.0\nTIMEOUT_WAIT_FOR_SIGNALLING_CONNECTIONS 120.0\nTIMEOUT_WAIT_FOR_PARTY_DATA 60.0\nTIME_TO_WAIT_FOR_LEAVE_MESSAGE_TO_COME_BACK 20.0\nTIME_TO_WAIT_FOR_FOLLOWING_REQUESTS_TO_ARRIVE 30.0\nTIMEOUT_WAIT_FOR_FINISHED_MIGRATING_HOST 30.0\nTIMEOUT_WAIT_FOR_PARTY_LEADER_FINISH_JOINING 45.0\nTIMEOUT_WAIT_FOR_QUICKPLAY_LEVEL 60.0\nTIMEOUT_WAIT_FOR_PLAYERS_TO_JOIN 30.0\nTIMEOUT_WAIT_FOR_DIVE_IN_PLAYERS 120.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 30.0\nTIMEOUT_DIVE_IN_TOTAL 1000000.0\nTIMEOUT_WAIT_FOR_SOCKET_CONNECTION 120.0\nTIMEOUT_WAIT_FOR_REQUEST_RESOURCE_MESSAGE 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_GET_RESOURCE_LIST 120.0\nTIMEOUT_WAIT_FOR_CLIENT_TO_LOAD_RESOURCES 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_SAVE_GAME_STATE 30.0\nTIMEOUT_WAIT_FOR_ADD_PLAYERS_TO_TAKE 30.0\nTIMEOUT_WAIT_FOR_UPDATE_FROM_CLIENT 90.0\nTIMEOUT_WAIT_FOR_HOST_TO_GET_RESOURCE_LIST 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_SAVE_GAME_STATE 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_ADD_US 30.0\nTIMEOUT_WAIT_FOR_UPDATE 60.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN 50.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_PRESENCE 60.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_CONNECTION 120.0\nSECONDS_BETWEEN_PINS_AWARDED_UPLOADS 300.0\nEnableKeepAlive true\nAllowVoIPRecordingPlayback true\nCDNHostName localhost\nTelemetryServer localhost\nOverheatingThresholdDisallowMidgameJoin 0.95\nMaxCatchupFrames 3\nMaxLagBeforeShowLoading 23\nMinLagBeforeHideLoading 30\nLagImprovementInflectionPoint -1.0\nFlickerThreshold 2.0\nClosedDemo2014Version 1\nClosedDemo2014Expired false\nEnablePlayedFilter true\nEnableCommunityDecorations true\nGameStateUpdateRate 10.0\nGameStateUpdateRateWithConsumers 1.0\nDisableDLCPublishCheck false\nEnableDiveIn true\nEnableHackChecks false\n"
|
||||||
|
+ $"TelemetryServer {hostname}\nCDNHostName {hostname}");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("t_conf")]
|
[HttpGet("t_conf")]
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||||
[Produces("text/plain")]
|
// [Produces("text/plain")]
|
||||||
public class MessageController : ControllerBase
|
public class MessageController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly Database database;
|
private readonly Database database;
|
||||||
|
@ -22,15 +22,19 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
User user = await this.database.UserFromRequest(this.Request);
|
User user = await this.database.UserFromRequest(this.Request);
|
||||||
return user == null
|
return user == null
|
||||||
? this.Ok("You aren't logged in, but you're connected to a private LBP server.")
|
? this.Forbid()
|
||||||
: this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n" +
|
: this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n" +
|
||||||
"This is a private testing instance. Please do not make anything public for now, and keep in mind security isn't as tight as a full release would.");
|
"This is a private testing instance. Please do not make anything public for now, and keep in mind security isn't as tight as a full release would.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("announce")]
|
[HttpGet("announce")]
|
||||||
public IActionResult Announce()
|
public async Task<IActionResult> Announce()
|
||||||
{
|
{
|
||||||
return this.Ok("");
|
User user = await this.database.UserFromRequest(this.Request);
|
||||||
|
return user == null
|
||||||
|
? this.Forbid()
|
||||||
|
: this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n" +
|
||||||
|
"This is a private testing instance. Please do not make anything public for now, and keep in mind security isn't as tight as a full release would.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("notification")]
|
[HttpGet("notification")]
|
||||||
|
|
17
ProjectLighthouse/Controllers/StoreController.cs
Normal file
17
ProjectLighthouse/Controllers/StoreController.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||||
|
[Produces("text/xml")]
|
||||||
|
public class StoreController : Controller
|
||||||
|
{
|
||||||
|
[HttpGet("promotions")]
|
||||||
|
public async Task<IActionResult> Promotions()
|
||||||
|
{
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,14 +3,18 @@ using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Match;
|
using LBPUnion.ProjectLighthouse.Types.Match;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
public static class MatchHelper {
|
{
|
||||||
public static IMatchData? Deserialize(string data) {
|
public static class MatchHelper
|
||||||
|
{
|
||||||
|
public static IMatchData? Deserialize(string data)
|
||||||
|
{
|
||||||
string matchType = "";
|
string matchType = "";
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
while(true) {
|
while (true)
|
||||||
if(data[i] == ',') break;
|
{
|
||||||
|
if (data[i] == ',') break;
|
||||||
|
|
||||||
matchType += data[i];
|
matchType += data[i];
|
||||||
i++;
|
i++;
|
||||||
|
@ -21,8 +25,10 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||||
return Deserialize(matchType, matchData);
|
return Deserialize(matchType, matchData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IMatchData? Deserialize(string matchType, string matchData) {
|
public static IMatchData? Deserialize(string matchType, string matchData)
|
||||||
return matchType switch {
|
{
|
||||||
|
return matchType switch
|
||||||
|
{
|
||||||
"UpdateMyPlayerData" => JsonSerializer.Deserialize<UpdateMyPlayerData>(matchData),
|
"UpdateMyPlayerData" => JsonSerializer.Deserialize<UpdateMyPlayerData>(matchData),
|
||||||
"UpdatePlayersInRoom" => JsonSerializer.Deserialize<UpdatePlayersInRoom>(matchData),
|
"UpdatePlayersInRoom" => JsonSerializer.Deserialize<UpdatePlayersInRoom>(matchData),
|
||||||
_ => null,
|
_ => null,
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection.Metadata.Ecma335;
|
using System.Reflection.Metadata.Ecma335;
|
||||||
|
using System.Runtime.InteropServices.ComTypes;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kettu;
|
using Kettu;
|
||||||
using LBPUnion.ProjectLighthouse.Logging;
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
|
@ -61,33 +62,36 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
Stopwatch requestStopwatch = new();
|
Stopwatch requestStopwatch = new();
|
||||||
requestStopwatch.Start();
|
requestStopwatch.Start();
|
||||||
|
|
||||||
|
// Log all headers.
|
||||||
|
foreach (var header in context.Request.Headers)
|
||||||
|
Logger.Log($"{header.Key}: {header.Value}");
|
||||||
|
|
||||||
context.Request.EnableBuffering(); // Allows us to reset the position of Request.Body for later logging
|
context.Request.EnableBuffering(); // Allows us to reset the position of Request.Body for later logging
|
||||||
|
|
||||||
// Client digest check.
|
// Client digest check.
|
||||||
var authCookie = null as string;
|
var authCookie = null as string;
|
||||||
if (!context.Request.Cookies.TryGetValue("MM_AUTH", out authCookie))
|
if (!context.Request.Cookies.TryGetValue("MM_AUTH", out authCookie))
|
||||||
authCookie = string.Empty;
|
authCookie = string.Empty;
|
||||||
if (context.Request.Headers.TryGetValue("X-Digest-A", out var clientDigest))
|
var digestPath = context.Request.Path;
|
||||||
|
var body = context.Request.Body;
|
||||||
|
|
||||||
|
var clientRequestDigest = await DigestUtils.ComputeDigest(digestPath, authCookie, body, serverDigestKey);
|
||||||
|
|
||||||
|
// Check the digest we've just calculated against the X-Digest-A header if the game set the header. They should match.
|
||||||
|
if (context.Request.Headers.TryGetValue("X-Digest-A", out var sentDigest))
|
||||||
{
|
{
|
||||||
var digestPath = context.Request.Path;
|
if (clientRequestDigest != sentDigest)
|
||||||
var body = context.Request.Body;
|
|
||||||
|
|
||||||
var digest = await DigestUtils.ComputeDigest(digestPath, authCookie, body, serverDigestKey);
|
|
||||||
|
|
||||||
if (digest != clientDigest)
|
|
||||||
{
|
{
|
||||||
Logger.Log($"Client digest {clientDigest} does not match server digest {digest}.");
|
context.Response.StatusCode = 403;
|
||||||
context.Abort();
|
context.Abort();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
context.Response.Headers.Add("X-Digest-B", digest);
|
|
||||||
context.Request.Body.Position = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This does the same as above, but for the response stream.
|
context.Response.Headers.Add("X-Digest-B", clientRequestDigest);
|
||||||
|
context.Request.Body.Position = 0;
|
||||||
|
|
||||||
|
// This does the same as above, but for the response stream.
|
||||||
using var responseBuffer = new MemoryStream();
|
using var responseBuffer = new MemoryStream();
|
||||||
var oldResponseStream = context.Response.Body;
|
var oldResponseStream = context.Response.Body;
|
||||||
context.Response.Body = responseBuffer;
|
context.Response.Body = responseBuffer;
|
||||||
|
@ -95,7 +99,7 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
await next(); // Handle the request so we can get the status code from it
|
await next(); // Handle the request so we can get the status code from it
|
||||||
|
|
||||||
// Compute the server digest hash.
|
// Compute the server digest hash.
|
||||||
if (computeDigests && context.Request.Headers.TryGetValue("X-Digest-A", out var a))
|
if (computeDigests)
|
||||||
{
|
{
|
||||||
responseBuffer.Position = 0;
|
responseBuffer.Position = 0;
|
||||||
|
|
||||||
|
@ -105,6 +109,9 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
context.Response.Headers.Add("X-Digest-A", serverDigest);
|
context.Response.Headers.Add("X-Digest-A", serverDigest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the X-Original-Content-Length header to the length of the response buffer.
|
||||||
|
context.Response.Headers.Add("X-Original-Content-Length", responseBuffer.Length.ToString());
|
||||||
|
|
||||||
// Copy the buffered response to the actual respose stream.
|
// Copy the buffered response to the actual respose stream.
|
||||||
responseBuffer.Position = 0;
|
responseBuffer.Position = 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue