Add Server Digest support. Note that the server digest key must be added to an environment variable.

This commit is contained in:
Michael VanOverbeek 2021-10-30 20:54:33 -04:00
commit 37abf75071
5 changed files with 63 additions and 27 deletions

View file

@ -13,8 +13,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[SuppressMessage("ReSharper", "StringLiteralTypo")]
public IActionResult NetworkSettings()
{
var hostname = this.Request.Host;
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")]

View file

@ -7,7 +7,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
{
[ApiController]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/plain")]
// [Produces("text/plain")]
public class MessageController : ControllerBase
{
private readonly Database database;
@ -22,15 +22,19 @@ namespace LBPUnion.ProjectLighthouse.Controllers
{
User user = await this.database.UserFromRequest(this.Request);
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 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")]
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")]

View 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();
}
}
}

View file

@ -3,14 +3,18 @@ using System.Linq;
using System.Text.Json;
using LBPUnion.ProjectLighthouse.Types.Match;
namespace LBPUnion.ProjectLighthouse.Helpers {
public static class MatchHelper {
public static IMatchData? Deserialize(string data) {
namespace LBPUnion.ProjectLighthouse.Helpers
{
public static class MatchHelper
{
public static IMatchData? Deserialize(string data)
{
string matchType = "";
int i = 1;
while(true) {
if(data[i] == ',') break;
while (true)
{
if (data[i] == ',') break;
matchType += data[i];
i++;
@ -21,8 +25,10 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
return Deserialize(matchType, matchData);
}
public static IMatchData? Deserialize(string matchType, string matchData) {
return matchType switch {
public static IMatchData? Deserialize(string matchType, string matchData)
{
return matchType switch
{
"UpdateMyPlayerData" => JsonSerializer.Deserialize<UpdateMyPlayerData>(matchData),
"UpdatePlayersInRoom" => JsonSerializer.Deserialize<UpdatePlayersInRoom>(matchData),
_ => null,

View file

@ -2,6 +2,7 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices.ComTypes;
using System.Threading.Tasks;
using Kettu;
using LBPUnion.ProjectLighthouse.Logging;
@ -61,33 +62,36 @@ namespace LBPUnion.ProjectLighthouse
Stopwatch requestStopwatch = new();
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
// Client digest check.
var authCookie = null as string;
if (!context.Request.Cookies.TryGetValue("MM_AUTH", out authCookie))
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;
var body = context.Request.Body;
var digest = await DigestUtils.ComputeDigest(digestPath, authCookie, body, serverDigestKey);
if (digest != clientDigest)
if (clientRequestDigest != sentDigest)
{
Logger.Log($"Client digest {clientDigest} does not match server digest {digest}.");
context.Response.StatusCode = 403;
context.Abort();
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();
var oldResponseStream = context.Response.Body;
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
// Compute the server digest hash.
if (computeDigests && context.Request.Headers.TryGetValue("X-Digest-A", out var a))
if (computeDigests)
{
responseBuffer.Position = 0;
@ -105,6 +109,9 @@ namespace LBPUnion.ProjectLighthouse
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.
responseBuffer.Position = 0;